【问题标题】:Too large variances from the covariance matrix when fitting data using curve_fit使用curve_fit拟合数据时协方差矩阵的方差太大
【发布时间】:2020-02-12 12:11:02
【问题描述】:

我在尝试使用 curve_fit 拟合数据时遇到了一些麻烦。

首先,我从协方差矩阵中得到的方差太大:对于一些找到的参数,标准误差的相对幅度超过 100%。然而,拟合曲线非常适合数据,但如果我给参数提供协方差矩阵中指示的偏差,曲线将非常强烈地偏离。如果我降低拟合数据的多项式的次数,方差会变小。但随后曲线在数据上变得更糟。令我困惑的另一件事是,最初对参数的猜测并没有改善这种情况。

这是我的代码:

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit 

#experimental_data
x=np.array([1842., 1885., 2149., 2164., 2195., 2208., 2234., 2254., 2266., 2284., 2292., 2315., 2334., 2350., 2361., 2381., 2387., 2427., 2435., 2458., 2484., 2498., 2563., 2592.,  830.,  269., 1498.,1918., 2100., 2112., 2312.])
y=np.array([5336., 5401., 5852., 5882., 5945., 5976., 6030., 6074., 6096., 6143., 6164., 6217., 6267., 6305., 6334., 6383., 6402., 6507., 6533., 6599., 6678., 6717., 6929., 7032., 4358., 4047., 4916., 5461., 5770., 5791., 6234.])

#fitting_function
def f_fit(x,a,b,c,d,g):
    return a*x**4+b*x**3+c*x**2+d*x+g

X=np.linspace(min(x),max(x))
popt, pcov = curve_fit(f = f_fit, xdata= x, ydata=y)
plt.figure(figsize=(10,7))
plt.plot(x,y, 'x') #experimental_data
plt.plot(X,f_fit(X, *popt))

perr=np.sqrt(np.diag(pcov)) #standard errors
#perturbed plots
plt.plot(X,f_fit(X, *popt+perr))
plt.plot(X,f_fit(X, *popt-perr))

其次,如果我添加absoulute_sigma=True,我会得到更小的绘图偏差。但这对我来说没有任何意义。在最小二乘法中,我们通常不知道 ydata 的不确定性,但大多数情况下它都能正常工作。而且我不明白为什么添加absoulute_sigma=True 会使差异变得如此之小。

popt, pcov = curve_fit(f = f_fit, xdata= x, ydata=y) 将我引向这样的情节:

对不起,如果我的问题很原始,我只是这方面的初学者。

【问题讨论】:

  • 你问的是编程问题还是数学问题?
  • 我真的不知道。这取决于我错在哪里:代码或数学。
  • 作为测试,尝试“numpy,polyfit(x, y, 4)”,返回参数作为curve_fit()的初始参数。请注意,从 numpy 文档中 polyfit() 返回“多项式系数,最高功率优先”。
  • @JamesPhillips 我已经找到了初始参数,尽管方式略有不同。无论如何,拟合都不是问题;找到的曲线很好地拟合了数据。但是找到的参数的方差(以及因此的标准误差)仍然很大。这是主要问题。
  • 我的意思是尝试这个作为测试。

标签: python curve-fitting least-squares variance


【解决方案1】:

curve_fit() 估计参数值及其协方差,并且

perr = np.sqrt(np.diag(pcov)) 

为 a、b、c、d、g 提供参数估计的标准误差。

图中误差带的宽度由

决定
f_fit(x,*popt+perr) - f_fit(x,*popt), 

等于

perr(a)*x^4 + perr(b)*x^3 + perr(c)*x^2+ perr(d)*x + perr(g)

首先,您可以看到,x 越大,误差带越宽,即使在精确估计参数并且 perr 值非常小的情况下也是如此。因此,在 x 值较大时,误差带可能会变得非常宽,因为多项式的高阶项非常大。下表显示了每个多项式项对 X 中每个值的标准误差带宽度的贡献,您可以清楚地看到更高阶项使误差带在较大的 X 值处非常宽:

       perr(g)  perr(d)X  perr(c)X^2  perr(b)X^3 perr(a)X^4  f_fit(X, *perr)
X                       
269.00    22.84    27.38      9.390     1.23        0.06      60.90
316.41    22.84    32.20      13.00     2.01        0.11      70.15
363.82    22.84    37.03      17.18     3.05        0.18      80.29
...
...
2497.18   22.84   254.17     809.55   986.50      409.22    2482.27
2544.59   22.84   258.99     840.58  1043.76      441.19    2607.36
2592.00   22.84   263.82     872.19  1103.19      475.00    2737.04

由于您的参数是非常精确估计的,其中一些参数几乎为零 - 在您的示例中,

popt = [ 1.23384779e-10, -4.87863958e-07,  9.15360533e-04, -8.15143637e-02, 4.01221128e+03]

perr = [1.05233894e-11 6.33499440e-08 1.29819675e-04 1.01781887e-01 2.28383194e+01]

您可能会受益于从 f_fit() 中删除 x^4 和 x^3 项,这将有助于减少回归的误差,而不会显着影响曲线的拟合。

关于 absolute_sigma=True,您应该仅在指定 sigma 参数时使用此选项,即当您有充分的理由对您的观察应用权重时。

【讨论】:

  • 感谢您的回答。参数的标准误差不是表示由 y 值的不确定性决定的参数的不确定程度吗?那么,如果它们变得如此之大,那么如此好的合身是如何产生的呢?此外,如果我们去掉 $x^4$(或者特别是 $x^3$)这个词,那么即使是肉眼也可以看出拟合已经变差了。您的回答还表明最大的相对误差是由 x 参数提供的。我试图将其从拟合功能中删除,并且随着拟合的轻微恶化,错误确实显着减少。这令人困惑。
  • 回归曲线非常适合您的数据,回归误差确实必须很小。但是,您创建的误差带并不代表回归误差。回归错误为 err=(y-f_fit(x,*popt))。如果要绘制回归线 +/- 回归标准误差,则计算 err 的标准差并绘制 f_fit(x,*popt) +/- std_err
猜你喜欢
  • 2013-06-24
  • 1970-01-01
  • 1970-01-01
  • 2014-03-06
  • 1970-01-01
  • 2019-08-02
  • 2013-02-01
  • 1970-01-01
  • 2018-11-10
相关资源
最近更新 更多