适合scipy.optimize参数的错误

时间:2017-04-24 16:42:04

标签: numpy scipy curve-fitting

我将scipy.optimize.minimizehttps://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值正确包含拟合参数。如何计算与这些参数相关的错误?

3 个答案:

答案 0 :(得分:2)

解决这个常见问题的一种方法是在scipy.optimize.leastsq使用&{39} L-BFGS-B&#39;后使用minimize。从用L-BFGS-B&#39;发现的溶液开始。也就是说,leastsq将(通常)包含和估计1-sigma错误以及解决方案。

当然,这种方法有几个假设,包括可以使用leastsq并且可能适合解决问题。从实际的角度来看,这要求目标函数返回一个残差值数组,其中至少有与变量一样多的元素,而不是成本函数。

您可能会发现lmfithttps://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)

这真的取决于你所说的“错误”。你的问题没有一般的答案,因为这取决于你的拟合程度以及你所做的假设。

最简单的情况是最常见的情况之一:当你最小化的函数是负对数似然。在这种情况下,拟合返回的粗糙矩阵是描述高斯近似最大似然的协方差,这是估计似然最大化误差的标准方法。

请注意,如果您正在使用其他类型的函数或进行不同的假设,那么这不适用。