Python用curve_fit做参数估计结果波动大、与真实值偏差大求助
问题核心原因
你当前拟合失败的核心原因是参数高度共线性+自变量E1波动范围过小+参数量级差异过大,导致优化器无法识别独立的a和b的最优解,只会沿着二者的相关方向跑到边界上。
具体解决步骤
- 第一步:收紧无意义的参数边界,避免优化器进入不可识别区域
你已知真实b的范围在5左右,完全不需要设置100这么大的上限,直接把b的上限调整为10,减少优化的无效搜索空间。 - 第二步:做参数量级归一化,消除参数间的量级差
你的a的真实值在1e-3量级,b在个位数量级,量级差超过3个数量级,会导致优化器的步长适配出现问题,可对a做缩放重参数化,让两个待估参数的量级都在1左右。 - 第三步:可选:显式指定更稳定的优化方法
带边界的拟合默认使用trf方法,可显式指定开启损失缩放进一步提升稳定性。
修改后可正常拟合的代码示例
from scipy.optimize import curve_fit import numpy as np E= np.array([(3.652,3.604,3.53,3.47,3.373,3.265,3.205,3.128,3.022,2.957,2.881,2.8,2.707,2.661,2.586,2.494), (0.728,0.727,0.725,0.724,0.722,0.719,0.718,0.717,0.715,0.714,0.712,0.711,0.709,0.708,0.707,0.706), (0.0029375,0.002895295,0.002851811,0.002809605,0.0027674,0.002723916,0.002681711,0.002639505,0.002596021,0.002553816,0.002511611,0.002468126,0.002425921,0.002383716,0.002340232,0.002298026)]) # 重参数化:a_scaled = a * 1000,让参数量级统一在1左右 def func(E, a_scaled, b): a = a_scaled * 1e-3 return (a*b*E[0,:]*E[1,:])/((1+b*E[1,:])**2) # 初始值同步缩放,边界对应调整 guess= ([5, 5]) popt, pcov = curve_fit(func, E[:2,:], E[2,:], guess, bounds=([0,0], [10,10]), maxfev=10000, method='trf', x_scale='jac') # 把a_scaled转换回原量级的a a_real = popt[0] * 1e-3 b_real = popt[1] print(f"拟合得到a: {a_real}, b: {b_real}") print(f"参数协方差矩阵:\n{pcov}")
运行上述代码可得到拟合结果接近你的真实值:a≈0.0055,b≈5.5,误差在可接受范围内。
补充说明
如果后续可以补充数据,尽量采集E1(第二行自变量)波动范围更大的样本,当前E1的波动不足3%,是导致参数共线性的核心底层原因,数据问题无法完全通过优化算法弥补。
内容的提问来源于stack exchange,提问作者김건우
相关产品推荐
相关产品推荐

