python中高斯曲线与吸收线的拟合

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

我试图将高斯分布拟合到我的数据中,这是在一个相当窄的光谱窗口中获取的。我们得到了2个连续点,然后是10-11个点,它们是直线的一部分。我认为,拟合它仍然是可能的,但曲线拟合每次都失败了,我不知道为什么

运行时,我获取运行时错误:未找到最佳参数:函数调用数已达到maxfev=800

代码和数据:

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的起点。如果它是一条直线,那么起点就远了, 但仍在向某个方向靠拢。等待我的编辑。