python中高斯曲线与吸收线的拟合
我试图将高斯分布拟合到我的数据中,这是在一个相当窄的光谱窗口中获取的。我们得到了2个连续点,然后是10-11个点,它们是直线的一部分。我认为,拟合它仍然是可能的,但曲线拟合每次都失败了,我不知道为什么 运行时,我获取运行时错误:未找到最佳参数:函数调用数已达到maxfev=800 代码和数据:python中高斯曲线与吸收线的拟合,python,curve-fitting,gaussian,Python,Curve Fitting,Gaussian,我试图将高斯分布拟合到我的数据中,这是在一个相当窄的光谱窗口中获取的。我们得到了2个连续点,然后是10-11个点,它们是直线的一部分。我认为,拟合它仍然是可能的,但曲线拟合每次都失败了,我不知道为什么 运行时,我获取运行时错误:未找到最佳参数:函数调用数已达到maxfev=800 代码和数据: import matplotlib.pyplot as plt from scipy.optimize import curve_fit import numpy as np x = np.arange
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import numpy as np
x = np.arange(13)
xx = np.arange(130)/13.
y = np.array([19699.959 , 21679.445 , 21143.195 , 20602.875 , 16246.769 ,
11635.25 , 8602.465 , 7035.493 , 6697.0337, 6510.092 ,
7717.772 , 12270.446 , 16807.81 ])
# weighted arithmetic mean (corrected - check the section below)
mean = sum(x * y) / sum(y)
sigma = np.sqrt(sum(y * (x - mean)**2) / sum(y))
def Gauss(x, a, x0, sigma):
return a * np.exp(-(x - x0)**2 / (2 * sigma**2))
popt,pcov = curve_fit(Gauss, x, y, p0=[max(y), mean, sigma])
plt.plot(x, y, 'b+:', label='data')
plt.plot(xx, Gauss(xx, *popt), 'r-', label='fit')
plt.legend()
plt.show()
正如错误所说,寻找最优值的过程并不收敛。如果你真的认为你所拥有的可以用高斯曲线来拟合,那么这通常意味着你的起点不好 你如何给出起始点可能是个问题,特别是你如何提供西格玛,因为在位置11、12和13,你有可能是另一个信号的开始。无论如何,这不是这次最大的问题,而是你忘记给高斯函数加一个偏移量
# ----> new parameter in signature
# |
def Gauss(x, y0, a, x0, sigma):
return y0 + a * np.exp(-(x - x0)**2 / (2 * sigma**2))
# |
# -------> adding and offset
然后,您可以决定如何为偏移量提供一个起点,但通过观察,我确实设置了5000
popt, pcov = curve_fit(Gauss, x, y, p0=[5000, max(y), mean, sigma])
那样做,我会大发雷霆。但是,由于最后三个数据点,这不是一个很好的数据点
如果避免使用这些值,则拟合会显著提高
编辑:
正如在评论中所指出的,高斯分布的中心在8左右,向下看,这是一条吸收线
在这种情况下,偏移应位于最大~22000处,然后振幅参数应为负~-maxy-miny~-16000
作为补充,最好将xx改为如下
xx = np.linspace(0, 13, 100)
或
这将给
检查popt,你基本上得到了我提到的/估计的值,只要看看图2180,-16000,8,σ为2.7,这是唯一一个我没有立即感觉到如何估计的值
我的猜测是,你实际上应该拟合高斯和柯西/洛伦兹线型的混合物,或者更好的,来解释实验加宽。正如错误所说,找到最佳值的过程并不收敛。如果你真的认为你所拥有的可以用高斯曲线来拟合,那么这通常意味着你的起点不好 你如何给出起始点可能是个问题,特别是你如何提供西格玛,因为在位置11、12和13,你有可能是另一个信号的开始。无论如何,这不是这次最大的问题,而是你忘记给高斯函数加一个偏移量
# ----> new parameter in signature
# |
def Gauss(x, y0, a, x0, sigma):
return y0 + a * np.exp(-(x - x0)**2 / (2 * sigma**2))
# |
# -------> adding and offset
然后,您可以决定如何为偏移量提供一个起点,但通过观察,我确实设置了5000
popt, pcov = curve_fit(Gauss, x, y, p0=[5000, max(y), mean, sigma])
那样做,我会大发雷霆。但是,由于最后三个数据点,这不是一个很好的数据点
如果避免使用这些值,则拟合会显著提高
编辑:
正如在评论中所指出的,高斯分布的中心在8左右,向下看,这是一条吸收线
在这种情况下,偏移应位于最大~22000处,然后振幅参数应为负~-maxy-miny~-16000
作为补充,最好将xx改为如下
xx = np.linspace(0, 13, 100)
或
这将给
检查popt,你基本上得到了我提到的/估计的值,只要看看图2180,-16000,8,σ为2.7,这是唯一一个我没有立即感觉到如何估计的值
我的猜测是,你实际上应该拟合高斯和柯西/洛伦兹线型的混合物,或者更好的a,来解释实验加宽。我这边的p0中的额外参数不太合适。p0=[5000,最大值,平均值,西格玛]。上面写着TypeError:Gauss正好有4个参数5,因为我不确定你为什么要在Gauss函数签名中添加一个参数?是的,不。它也是一个向上向下的gaussian,我想a会处理这个问题,我的想法正确吗?“峰值”应该是最低的部分,如果它是一个以位置8为中心的倒高斯分布,那么偏移量应该是22000~maxy,然后a应该是负的,但是你最好提供一个负值作为a的起点。如果它是一条直线,那么起点是远的,但仍然会收敛到某个地方。等待我的编辑。它不喜欢我这边p0中的额外参数。p0=[5000,最大值,平均值,西格玛]。上面写着TypeError:Gauss正好有4个参数5,因为我不确定你为什么要在Gauss函数签名中添加一个参数?是的,不。它也是一个向上向下的gaussian,我想a会处理这个问题,我的想法正确吗?“峰值”应该是最低的部分如果它是一个以位置8为中心的倒高斯分布,那么偏移量应该是22000~maxy,然后a应该是负的,但是你最好提供一个负值作为a的起点。如果它是一条直线,那么起点就远了, 但仍在向某个方向靠拢。等待我的编辑。