Python LMFIT曲线拟合模块有时不支持';不要显示错误

Python LMFIT曲线拟合模块有时不支持';不要显示错误,python,curve-fitting,least-squares,lmfit,Python,Curve Fitting,Least Squares,Lmfit,我有各种各样的光谱图,我正试图适合一个函数。LMFIT有一个我正在使用的复合模型功能,我的模型基本上是恒定背景下Voigt或gaussian峰值的总和。使用scipy峰值查找器功能找到峰值中心的初始猜测 实际上,即使对于具有许多峰值的数据集,拟合也非常好。我的问题是,有时(对于一些具有更多峰值的较大数据集),拟合报告上的错误不会显示,但有时会显示 通过阅读关于类似主题的其他问题,我似乎已经收集到,这可能是由于没有使用参数,或者被推到我设置的边界。有鉴于此,我尝试移除所有边界,只为每个峰值设置初始

我有各种各样的光谱图,我正试图适合一个函数。LMFIT有一个我正在使用的复合模型功能,我的模型基本上是恒定背景下Voigt或gaussian峰值的总和。使用scipy峰值查找器功能找到峰值中心的初始猜测

实际上,即使对于具有许多峰值的数据集,拟合也非常好。我的问题是,有时(对于一些具有更多峰值的较大数据集),拟合报告上的错误不会显示,但有时会显示

通过阅读关于类似主题的其他问题,我似乎已经收集到,这可能是由于没有使用参数,或者被推到我设置的边界。有鉴于此,我尝试移除所有边界,只为每个峰值设置初始条件。它仍然没有显示错误

我意识到将15条左右重叠的高斯曲线拟合到一张光谱图上可能需要很多,但由于这种拟合用肉眼看来效果很好,我认为它一定在某种程度上起作用

基本上,我想知道如何获得具有多个峰值的数据集的fit报告中的错误,就像具有两个峰值的数据集一样

以下是两个拟合报告示例:

出现两个峰值,误差如下所示:

 [[Model]]
    ((Model(constant) + Model(voigt, prefix='g0_')) + Model(voigt, prefix='g1_'))
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 186
    # data points      = 564
    # variables        = 9
    chi-square         = 1342.58147
    reduced chi-square = 2.41906571
    Akaike info crit   = 507.154526
    Bayesian info crit = 546.170014
[[Variables]]
    g0_sigma:      7.58224056 +/- 0.07787554 (1.03%) (init = 7)
    g0_center:     657.390036 +/- 0.02496585 (0.00%) (init = 656.4029)
    g0_amplitude:  1549654.58 +/- 5871.81065 (0.38%) (init = 57643.33)
    g0_gamma:      3.70825451 +/- 0.10708503 (2.89%) (init = 0.7)
    g0_fwhm:       27.3059988 +/- 0.28045426 (1.03%) == '3.6013100*g0_sigma'
    g0_height:     57414.5545 +/- 137.261488 (0.24%) == 'g0_amplitude*wofz((1j*g0_gamma)/(g0_sigma*sqrt(2))).real/(g0_sigma*sqrt(2*pi))'
    g1_sigma:      7.66546221 +/- 0.55266628 (7.21%) (init = 7)
    g1_center:     803.744461 +/- 0.16381855 (0.02%) (init = 803.2903)
    g1_amplitude:  315684.011 +/- 6421.21329 (2.03%) (init = 10676.22)
    g1_gamma:      6.21905616 +/- 0.67178258 (10.80%) (init = 0.7)
    g1_fwhm:       27.6057057 +/- 1.99032260 (7.21%) == '3.6013100*g1_sigma'
    g1_height:     9525.49591 +/- 130.820663 (1.37%) == 'g1_amplitude*wofz((1j*g1_gamma)/(g1_sigma*sqrt(2))).real/(g1_sigma*sqrt(2*pi))'
    c:             1096.67100 +/- 6.42230443 (0.59%) (init = 0)
[[Correlations]] (unreported correlations are < 0.250)
    C(g0_sigma, g0_gamma)     = -0.929
    C(g1_sigma, g1_gamma)     = -0.926
    C(g0_amplitude, g0_gamma) =  0.828
    C(g1_amplitude, g1_gamma) =  0.821
    C(g0_sigma, g0_amplitude) = -0.659
    C(g1_sigma, g1_amplitude) = -0.650
这里还有一个代码的简化版本(伪代码?),它不运行,但显示了我正在尝试做的事情。我运行的实际代码,所以可以说,这不是代码的真正问题,但它可能会说明我正在尝试做什么。我相信这是非常优化的,所以请在回答中随意嘲笑我

#read in data

#decide on stn ratio prominence and other values, the model type to use etc



#find estimate for peak centre, using this scipy function
peaks = scipy.signal.find_peaks(y,height = error*StN, width = width,prominence=PStN)
.
.
.
.
.

#obviously cut out some of the other code but this loops to make a gaussian or a voigt or whatever for each peak found above
model_array = {}
pars = lm.Parameters()
while n < peakamt:
    model_array[n] = modeltype(prefix = "g"+str(n)+"_")
    pars.update(model_array[n].make_params())
    pars['g'+str(n)+'_center'].set(value=xpeaks[n])
    pars['g'+str(n)+'_sigma'].set(value=7)
    pars['g'+str(n)+'_amplitude'].set(value=ypeaks[n])
    if modeltype == VoigtModel:
        pars["g"+str(n)+'_gamma'].set(value=0.7, vary=True, expr = '')
    #print(n)
    n = n + 1

#adds the constant model
const = ConstantModel()
pars.update(const.make_params())

#makes the entire composite model, adding each peak model to the constant model
model = const
m = 0
while m < n:
    model = model + model_array[m]
    time.sleep(0.1)
    print(".")
    m = m+1


#here is the fitting

out = model.fit(y, pars, x=x, weights = weight)
final_fit = np.array(out.best_fit)
residuals = final_fit - y

#creating main figure
fig = plt.subplot(2,1,1)
#fig.plot(w,Lorentz)
fig.plot(x,final_fit)
fig.plot(x, y, 'ro', markersize = 2)
fig.errorbar(x,y,yerr=e, linestyle='none')
fig.set_title(str(ElementName) + " Deg " + str(Degrees))
fig.set_ylabel('Intensity (counts)')
fig.set_xlabel('Wavenumber (cm^-1)')

#creating residual figure
res = plt.subplot(2,1,2)
res.plot(x,residuals, 'r+')


res.errorbar(x,residuals,yerr=e,linestyle='none')
res.set_title("Residuals")

#Formatting the figures
plt.tight_layout()


#Output
print(out.fit_report(min_correl=0.25))
print('\n')


plt.show()
#读入数据
#决定stn比率突出值和其他值、要使用的型号等
#使用此scipy函数查找峰值中心的估计值
峰值=scipy.signal.find_峰值(y,高度=错误*StN,宽度=宽度,突出度=PStN)
.
.
.
.
.
#显然,删掉了一些其他的代码,但是这个循环会为上面发现的每个峰值生成一个高斯或voigt或其他任何东西
模型_数组={}
pars=lm.Parameters()
当n

非常感谢您阅读本文,希望有人能帮助我。我道歉,如果这是酷刑阅读,我没有太多的经验,这个网站或编码一般。我希望不是太糟糕。

最新版本的
lmfit
应该在报告中包含一些信息,说明为什么它无法估计不确定性。通常,如果某个参数偏离太远,以致其贡献对模型或拟合没有影响,或者某个参数卡在边界上,就会发生这种情况。报告应该对此给出一些提示

在您的例子中,
gamma
参数似乎都变得非常负,并且完全疯狂。对于Voigt函数,
gamma<0
并不完全是“荒谬的”,但它确实使函数不完全是一个“峰值”,更像是“尖锐的洛伦兹-广义高斯”的混合物。您可能希望在
gamma
上设置一个下限,可能是0

还有其他的可能性,比如将
伽马
限制为某个因数乘以
西格玛
,并对所有峰值使用相同的因数,比如说like

pars = lm.Parameters()
pars.add('gamma_scale', value=0.7, min=0, max=100, vary=True)
while n < peakamt:
    pref = 'g%d_' % n
    model_array[n] = modeltype(prefix =pref)
    pars.update(model_array[n].make_params())
    pars['%s_center' % pref].set(value=xpeaks[n])
    pars['%s_sigma' % pref].set(value=7)
    pars['%s_amplitude' % pref].set(value=ypeaks[n])
    if modeltype == VoigtModel:
        pars['%s_gamma' % pref].set(expr='gamma_scale*%s_sigma' % pref)
    n = n + 1
pars=lm.Parameters()
部分相加(“伽马刻度”,值=0.7,最小值=0,最大值=100,变化值=True)
当n
这仍将允许Voigt峰值与
伽马
有一定的可变性,但将它们限制为具有相同数量的
伽马
-ness。这是否是您真正想要做的,可能取决于数据的性质

pars = lm.Parameters()
pars.add('gamma_scale', value=0.7, min=0, max=100, vary=True)
while n < peakamt:
    pref = 'g%d_' % n
    model_array[n] = modeltype(prefix =pref)
    pars.update(model_array[n].make_params())
    pars['%s_center' % pref].set(value=xpeaks[n])
    pars['%s_sigma' % pref].set(value=7)
    pars['%s_amplitude' % pref].set(value=ypeaks[n])
    if modeltype == VoigtModel:
        pars['%s_gamma' % pref].set(expr='gamma_scale*%s_sigma' % pref)
    n = n + 1