我正在使用一些测试数据并使用以下代码在Python 2.7中运行适配器lmfit
。我需要权重为1/y
(使用Leven-Marq。例程)。我已经定义的权重,并在这里使用它们:Python lmfit在加权合适后缩小了卡方太小
from __future__ import division
from numpy import array, var
from lmfit import Model
from lmfit.models import GaussianModel, LinearModel
import matplotlib.pyplot as plt
import seaborn as sns
xd = array([1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276,
1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288,
1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300,
1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312,
1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324,
1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334])
yd = array([238, 262, 255, 271, 270, 281, 261, 278, 280, 254, 289, 285, 304, 314,
329, 342, 379, 450, 449, 564, 613, 705, 769, 899, 987, 1043, 1183, 1295, 1298,
1521, 1502, 1605, 1639, 1572, 1659, 1558, 1476, 1397, 1267, 1193, 1016, 951,
835, 741, 678, 558, 502, 480, 442, 399, 331, 334, 308, 283, 296, 265, 264,
273, 258, 270, 262, 263, 239, 263, 251, 246, 246, 234])
mod = GaussianModel() + LinearModel()
pars = mod.make_params(amplitude=25300, center=1299, sigma=7, slope=0, intercept=450)
result = mod.fit(yd, pars, method='leastsq', x=xd, weights=1./yd)
rsq = 1 - result.residual.var()/var(yd)
print(result.fit_report())
print rsq
plt.plot(xd, yd, 'bo', label='raw')
plt.plot(xd, result.init_fit, 'k--', label='Initial_Guess')
plt.plot(xd, result.best_fit, 'r-', label='Best')
plt.legend()
plt.show()
的输出是:
[[Model]]
(Model(gaussian) + Model(linear))
[[Fit Statistics]]
# function evals = 27
# data points = 68
# variables = 5
chi-square = 0.099
reduced chi-square = 0.002
Akaike info crit = -434.115
Bayesian info crit = -423.017
[[Variables]]
sigma: 7.57360038 +/- 0.063715 (0.84%) (init= 7)
center: 1299.41410 +/- 0.071046 (0.01%) (init= 1299)
amplitude: 25369.3304 +/- 263.0961 (1.04%) (init= 25300)
slope: -0.15015228 +/- 0.071540 (47.65%) (init= 0)
intercept: 452.838215 +/- 93.28860 (20.60%) (init= 450)
fwhm: 17.8344656 +/- 0.150037 (0.84%) == '2.3548200*sigma'
height: 1336.33919 +/- 17.28192 (1.29%) == '0.3989423*amplitude/max(1.e-15, sigma)'
.
.
.
.
0.999999993313
最后一行(刚好高于此处,或立即plt.plot(xd, yd, 'bo', label='raw')
之前)是R^2,将所得配合附在这里。 。
R^2和输出的视觉检查表明这是一个合理的拟合。我期待1.00的订单减少卡方(source)。但是,降低的卡方值的返回值比1.00小几个数量级。
由于默认值是no weightslmfit
我需要一个加权拟合,我已经定义了权重,但我认为我需要以不同的方式指定它们。我的怀疑是这种重量的规格可能会导致减小的卡方非常小。
是否有不同的方式来指定权重或其他参数,使得曲线拟合后的减少的卡方接近或等于1.00的相同量级?
好吧有三个问题:我确实已将缩小的卡方变成了'0.790',并附有您的重量规格。我试着用'np.sum(((yd-result.best_fit)** 2)/result.best_fit)/(68-5)'手动计算降低的卡方,并得到了略微不同的值“0.78065” 。我把68作为点的数量,把5作为拟合参数的数量(即问题中的约束条数),所以自由度的数量是63.差别几乎可以忽略不计...... .... lmfit'使用a估计降低的卡方的方法略有不同。 –
感谢您的好评!另一个后续问题:直到你对比例不确定性的评论之前,我没有想到这个问题,但是:当我使用(a)scale_covar = True时,参数误差(例如)在幅度上更接近67.4%的置信水平从'result.ci_report()'与(b)'scale_covar = False'报告,幅度参数误差远大于从result.ci_report()报告的67.4%置信度。如果1 *'sigma' par。不确定性是需要的,应该只使用'.ci_report()'输出吗? 1'sigma'有没有办法让'.fit_report()'不确定? –
关于权重 - 是的,使用'sqrt(yd)'给出接近1.0的红色平方值。再次感谢这个伟大的解释。好的,我的第三个问题和我对你的答案的主要问题:你已经将方差称为“sqrt(yd)”。我对权重([维基链接](https://en.wikipedia.org/wiki/Least_squares#Weighted_least_squares))的理解是它们应该是方差的倒数(即权重= 1 /'sigma'^2),其中方差= 'sigma'^2。你也使用了方差的倒数,但是指的是标准偏差('sigma',即方差的平方根)的'sqrt(yd)'? –