我将scipy.optimize.minimize
(https://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html)函数与method='L-BFGS-B
一起使用。
它返回的一个例子如上:
fun: 32.372210618549758
hess_inv: <6x6 LbfgsInvHessProduct with dtype=float64>
jac: array([ -2.14583906e-04, 4.09272616e-04, -2.55795385e-05,
3.76587650e-05, 1.49213975e-04, -8.38440428e-05])
message: 'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'
nfev: 420
nit: 51
status: 0
success: True
x: array([ 0.75739412, -0.0927572 , 0.11986434, 1.19911266, 0.27866406,
-0.03825225])
x
值正确包含拟合参数。如何计算与这些参数相关的错误?
答案 0 :(得分:2)
解决这个常见问题的一种方法是在scipy.optimize.leastsq
使用&{39} L-BFGS-B&#39;后使用minimize
。从用L-BFGS-B&#39;发现的溶液开始。也就是说,leastsq
将(通常)包含和估计1-sigma错误以及解决方案。
当然,这种方法有几个假设,包括可以使用leastsq
并且可能适合解决问题。从实际的角度来看,这要求目标函数返回一个残差值数组,其中至少有与变量一样多的元素,而不是成本函数。
您可能会发现lmfit
(https://lmfit.github.io/lmfit-py/)在这里很有用:它支持L-BFGS-B&#39;和&#39; leastsq&#39;并围绕这些和其他最小化方法给出一个统一的包装器,以便您可以对两个方法使用相同的目标函数(并指定如何将残余数组转换为成本函数)。此外,参数边界可用于两种方法。这样就可以很容易地首先使用L-BFGS-B&#39;然后使用&#39; leastsq&#39;,使用来自&L-BFGS-B&#39;作为起始值。
如果您怀疑leastsq
使用的简单但快速的方法可能不够,Lmfit还提供了更详细地更明确地探索参数值置信度限制的方法。
答案 1 :(得分:2)
TL; DR:您实际上可以对最小化例程找到参数最佳值的精确度设置上限。请参见此答案末尾的代码片段,该代码片段显示了如何直接执行此操作,而无需诉诸其他最小化例程。
此方法的documentation说
当
(f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} <= ftol
时,迭代停止。
粗略地说,当您要最小化的函数f
的值最小化到最佳值ftol
之内时,最小化停止。 (如果f
大于1,这是一个相对错误,否则为绝对错误;为简单起见,我认为这是绝对错误。)在更标准的语言中,您可能会想到函数{{1} }作为卡方值。因此,这大致表明您会期望
当然,您正在应用这样的最小化例程的事实就假设您的函数运行良好,从某种意义上来说,它是相当平滑的,并且可以通过参数的二次函数很好地找到最优值。 em> x i 接近最佳值:
其中Δ x i 是参数 x i 的发现值与其最佳值之间的差,而 H ij 是Hessian矩阵。一个小的(令人惊讶的是平凡的)线性代数可以使您得到一个相当标准的结果,以估计任何数量 X 中的不确定性,这是参数 x i 的函数:
这让我们写
通常,这是最有用的公式,但是对于这里的特定问题,我们只有 X = x i ,因此简化为
最后,要完全明确,假设您将优化结果存储在名为f
的变量中。逆黑森州可以作为res
使用,该函数接受一个向量并返回该逆黑森州与该向量的乘积。因此,例如,我们可以使用以下代码段显示优化的参数以及不确定性估计:
res.hess_inv
请注意,假设ftol = 2.220446049250313e-09
tmp_i = np.zeros(len(res.x))
for i in range(6):
tmp_i[i] = 1.0
uncertainty_i = np.sqrt(max(1, abs(res.fun))*ftol*res.hess_inv(tmp_i)[i])
tmp_i[i] = 0.0
print('{0:12.4e} ± {1:.1e}'.format(res.x[i], uncertainty_i))
和max
与最终输出值f^k
基本相同,我从文档中合并了f^{k+1}
行为,确实应该是一个很好的近似值。另外,对于小问题,您可以使用res.fun
来获取完整的逆并立即提取对角线。但是对于大量变量,我发现这是一个慢得多的选择。最后,我添加了默认值np.diag(res.hess_inv.todense())
,但是如果在ftol
的参数中更改默认值,则显然需要在此处更改它。
答案 2 :(得分:1)
这真的取决于你所说的“错误”。你的问题没有一般的答案,因为这取决于你的拟合程度以及你所做的假设。
最简单的情况是最常见的情况之一:当你最小化的函数是负对数似然。在这种情况下,拟合返回的粗糙矩阵是描述高斯近似最大似然的协方差,这是估计似然最大化误差的标准方法。
请注意,如果您正在使用其他类型的函数或进行不同的假设,那么这不适用。