使用scipy的curve_fit拟合幂律模型时参数误差过大如何解决?
问题原因
- 拟合解落在参数边界上
你设置的c0参数下界为-2,从输出结果可以看到拟合得到的c0刚好等于-2,说明最优解卡在了边界位置。而curve_fit返回的协方差矩阵是基于无约束最小二乘的局部二次近似推导的,当解落在边界上时这个假设不成立,得到的参数误差估计自然不准确。 - 参数存在强共线性
你的x取值仅在0.55~1.05的窄区间内,x**m在这个区间的变化幅度非常小,c * x**m + c0的组合近似于线性项加常数项,此时调整c的数值只要同步反向调整c0,就能得到几乎一致的拟合效果,两个参数高度相关,会进一步放大所有参数的误差估计值。
解决方法
你只需要约束0.1<=m<=0.9,其余参数的边界完全没有必要设置,放开这部分约束即可,修改后的拟合代码如下:
import numpy as np from scipy.optimize import curve_fit import matplotlib.pyplot as plt def func_powerlaw(x, m, c, c0): return c0 + x**m * c x = np.array([1.05, 1.0, 0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.65, 0.6, 0.55]) y = np.array([1.26, 1.24, 1.2, 1.17, 1.1, 1.01, 0.95, 0.84, 0.75, 0.71, 0.63]) dy = np.array([0.078]*11) # 仅保留m的约束,放开c和c0的边界 popt, pcov = curve_fit(func_powerlaw, x, y, sigma = dy, p0 = [0.3, 1, 1], bounds=[(0.1, -np.inf, -np.inf), (0.9, np.inf, np.inf)], absolute_sigma=False, maxfev=10000, method = 'trf') perr=np.sqrt(np.diag(pcov)) print(popt, perr)
修改后运行得到的参数误差会大幅缩小,符合你对拟合精度的预期。如果后续还需要进一步降低共线性影响,可以尝试扩大x的取值范围,或者如果你的场景允许固定c0的数值,也可以直接固定该参数减少待拟合变量。
内容的提问来源于stack exchange,提问作者George
相关产品推荐
相关产品推荐

