[英]scipy.optimize.leastsq in Python not returning covariance matrix when fitting data
我正在使用 optimize.leastsq 来拟合我从穆斯堡尔光谱实验中收集的数据。 数据拟合成功,返回的最佳拟合参数良好。 但是当我想象我应该得到一个矩阵时,第二个 output cov_x,如文档中所称,给出了 1 的 integer。 为什么会发生这种情况以及如何获得正确的矩阵?
编辑:@slothrop 澄清说,我认为是 cov_x 的 output 实际上是 ier,一个 integer 代表一个错误。 1 代表 [“平方和的实际和预测相对减少\n 最多为 %f” % ftol,无]。 谁能帮我理解这是什么意思?
编辑 2:已解决。 @slotrop 礼貌地告诉我,我必须传递参数 full_output=1 才能让 optimize.leastsq 返回 cov_x。
PS 我不想使用 optimize.curve_fit 因为我想将参数作为列表而不是单个变量传递给我的 model function。
文档: https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.leastsq.html
这是我的代码。 由于我想概括为任意起点、终点,它的某些部分似乎是不必要的。
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize, signal
# sample of data
x = np.array([100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179])
y = np.array([17714, 17582, 17377, 17292, 17210, 17248, 16667, 16479, 16609, 16461, 16584, 16898, 17033, 17162, 17231, 17349, 17420, 17762, 17650, 17511, 17607, 17525, 17818, 17628, 17576, 17576, 17865, 17963, 18005, 17860, 17769, 17935, 17829, 17770, 17847, 17855, 18085, 18123, 17706, 17790, 17766, 17864, 17864, 18094, 17826, 17662, 17693, 17767, 17905, 17805, 17738, 17812, 17690, 17722, 17747, 17679, 17763, 17405, 17570, 17396, 17291, 16892, 16727, 16797, 17003, 17180, 17245, 17436, 17565, 17388, 17522, 17504, 17715, 17585, 17782, 17652, 17736, 17897, 17766, 17789])
def lorentz(x, xpeak, linewidth, intensity): # parameters: xpeak, linewidth, intensity
return -intensity*(linewidth/2)**2/((x-xpeak)**2+(linewidth/2)**2)
def curve_fit(start,stop):
xp_est = signal.find_peaks(-y[start:stop], width=5, height=-17250)[0] # parameter estimates
xp_est = start + xp_est
npeaks = np.size(xp_est)
lw_est = np.full(npeaks,7)
I_est = (17800-y[xp_est])
estimates = [xp_est, lw_est, I_est]
def model(x, par): # sum of lorentz distributions of peaks
xpeak = par[:npeaks]
linewidth = par[npeaks:2*npeaks]
intensity = par[2*npeaks:]
lorentz_sum = 17800
for i in range(npeaks):
lorentz_sum = lorentz_sum + lorentz(x,xpeak[i],linewidth[i],intensity[i])
return lorentz_sum
def residual(par, x, y):
return y - model(x, par)
par, cov = optimize.leastsq(residual, estimates, (x[start:stop], y[start:stop]))
plt.plot(x[start:stop], y[start:stop], '.', markersize=2)
plt.plot(x[start:stop], model(x[start:stop], par))
return par, cov
par, cov = curve_fit(0, 80)
print(par, type(par))
print(cov, type(cov))
plt.show()
Output
[ 162.67354556 108.5074825 5.99266549 7.74311055 1048.1092175
1361.99804297] <class 'numpy.ndarray'>
1 <class 'int'>
[link]
默认情况下,它只输出结果(一维数组)和一个 integer 标志(你得到的 integer 数字)。 如果你想要完整的 output,使用这个:
x0, cov, info, msg, status = optimize.leastsq(residual, estimates, (x[start:stop], y[start:stop]), full_output=True)
cov
就是你想要的
您必须在leastsq()
function 中传递full_output=True
参数
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.