Python LMFIT曲线拟合模块有时不支持';不要显示错误
我有各种各样的光谱图,我正试图适合一个函数。LMFIT有一个我正在使用的复合模型功能,我的模型基本上是恒定背景下Voigt或gaussian峰值的总和。使用scipy峰值查找器功能找到峰值中心的初始猜测 实际上,即使对于具有许多峰值的数据集,拟合也非常好。我的问题是,有时(对于一些具有更多峰值的较大数据集),拟合报告上的错误不会显示,但有时会显示 通过阅读关于类似主题的其他问题,我似乎已经收集到,这可能是由于没有使用参数,或者被推到我设置的边界。有鉴于此,我尝试移除所有边界,只为每个峰值设置初始条件。它仍然没有显示错误 我意识到将15条左右重叠的高斯曲线拟合到一张光谱图上可能需要很多,但由于这种拟合用肉眼看来效果很好,我认为它一定在某种程度上起作用 基本上,我想知道如何获得具有多个峰值的数据集的fit报告中的错误,就像具有两个峰值的数据集一样 以下是两个拟合报告示例: 出现两个峰值,误差如下所示:Python LMFIT曲线拟合模块有时不支持';不要显示错误,python,curve-fitting,least-squares,lmfit,Python,Curve Fitting,Least Squares,Lmfit,我有各种各样的光谱图,我正试图适合一个函数。LMFIT有一个我正在使用的复合模型功能,我的模型基本上是恒定背景下Voigt或gaussian峰值的总和。使用scipy峰值查找器功能找到峰值中心的初始猜测 实际上,即使对于具有许多峰值的数据集,拟合也非常好。我的问题是,有时(对于一些具有更多峰值的较大数据集),拟合报告上的错误不会显示,但有时会显示 通过阅读关于类似主题的其他问题,我似乎已经收集到,这可能是由于没有使用参数,或者被推到我设置的边界。有鉴于此,我尝试移除所有边界,只为每个峰值设置初始
[[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