python - curve_fit 和 scipy.odr 的比较 - 绝对西格玛

标签 python optimization scipy curve-fitting data-fitting

我目前想要拟合 x 和 y 中有错误的数据,我使用 scipy.odr 包来获得我的结果。我只是想知道如何正确使用错误 sx 和 sy。所以这是一个例子。

假设我针对不同的电流 I 测量电压 V。 所以我测量了 1V,误差为 +- 0.1V 等等。因此,如果我假设电流测量没有错误,我可以按如下方式使用 spipy.curve_fit。 Absolute_sigma 设置为 True,因为我的绝对误差为 +- 0.1V。

所以我得到:

from scipy.optimize import curve_fit
y=[1,2.5,3,4]
x=[1,2,3,4]
yerr=[0.1,0.1,0.1,0.1]

def func(x, a, b):
    return a*x+b

popt, pcov = curve_fit(func, x, y,sigma=yerr,absolute_sigma=True)

print(popt)
print(np.sqrt(np.diag(pcov)))

[0.95 0.25]
[0.04472136 0.12247449]

在第二步中,我想使用电流和电压均有误差的 odr 包。 根据文档,它应该按如下方式使用:sx 和 sy 是我的测量数据的误差。 因此,如果我对 sx 使用非常小的误差,我应该假设得到与 curve_fit 相似的结果。

from scipy.odr import *
x_err = [0.0000000001]*x.__len__()
y_err = yerr

def linear_func(p, x):
   m, c = p
   return m*x+c

linear_model = Model(linear_func)

data = RealData(x, y, sx=x_err, sy=y_err)

odr = ODR(data, linear_model, beta0=[0.4, 0.4])

out = odr.run()

out.pprint()

Beta: [0.94999996 0.24999994]
Beta Std Error: [0.13228754 0.36228459]

但是如您所见,结果与上面 curve_fit absolute_sigma=True 的结果不同。

将相同的数据与 curve_fit 和 absolute_sigma=False 一起使用会导致与 ODR-Fit 相同的结果。

popt, pcov = curve_fit(func, x, y,sigma=yerr,absolute_sigma=False)

print(popt)
print(np.sqrt(np.diag(pcov)))

[0.95 0.25]
[0.13228756 0.36228442]

所以我猜 ODR-Fit 并没有像 curve_fit 和 absolute_sigma=True 那样真正处理我的绝对误差。有什么办法可以做到这一点,还是我遗漏了什么?

最佳答案

curve_fit() 中的选项 absolute_sigma=True 给出了 实协方差矩阵 在这个意义上 np.sqrt( np.diag(pcov)) 产生 1-sigma 标准偏差作为定义的误差,例如 Numerical Recipes,即它可以有一个单位,如 meter 左右。 kmpfit 附带一个非常有用的摘要

但是,ODR 给出了从缩放协方差矩阵导出的标准误差。看这里,How to compute standard error from ODR results?或下面的示例。

通过 ODR 执行这种缩放,使得减少的 chi2 - 使用以相同方式缩放的输入权重计算 - 产生大约 1。或来自 curve_fit docs :

This constant is set by demanding that the reduced chisq for the optimal parameters popt when using the scaled sigma equals unity.

现在剩下的问题是:sd_beta 到底是什么意思? 这是标准错误,参见例如Standard error of mean versus standard deviation (可能存在两者大小相同的情况。请参阅下面的评论) 另见前面的讨论:https://mail.python.org/pipermail/scipy-user/2013-February/034196.html

现在,通过使用缩减的 chi2 缩放 pcov,对于参数误差,获得与 a) curve_fit(..., absolute_sigma=False) 和 b 相同的输出) ODR a priory 相对错误:

# calculate chi2
residuals = (y - func(x, *popt))
chi_arr =  residuals / yerr
chi2_red = (chi_arr**2).sum() / (len(x)-len(popt))
print('red. chi2:\t\t\t\t', chi2_red)
print('np.sqrt(np.diag(pcov) * chi2_red):\t', np.sqrt(np.diag(pcov) * chi2_red))

产量:

red. chi2:                           8.75
np.sqrt(np.diag(pcov) * chi2_red):   [0.13228756 0.36228442]

请注意,但是,对于 curve_fit(..., absolute_sigma=True) 和 ODR,协方差矩阵 pcov 来自 curve_fit 和ODR 输出的 cov_beta 仍然相同。在这里,来回重新缩放的缺点变得显而易见!

相对误差 现在当然意味着,如果缩放输入误差,则相对误差的大小保持不变:

# scaled uncertainty
yerr = np.asfarray([0.1, 0.1, 0.1, 0.1]) * 2

popt, pcov = curve_fit(func, x, y, sigma=yerr, absolute_sigma=False)

print('popt:\t\t\t', popt)
print('np.sqrt(np.diag(pcov)):\t', np.sqrt(np.diag(pcov)))

相同的输出:

popt:                    [0.95 0.25]
np.sqrt(np.diag(pcov)):  [0.13228756 0.36228442]

关于python - curve_fit 和 scipy.odr 的比较 - 绝对西格玛,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62460399/

相关文章:

java - 重构/优化 Java 代码以获取 HostNameVerifier

python - Python 中的稳健线性回归结果与 Stata 不一致

python - gensim - Doc2Vec : Difference iter vs. 纪元

python - 在 mysql 中自动用虚拟数据填充表

python - 树莓派 3 : Unusual behaviour with mpd, PiFi DAC+ 音频

python - 自动检测/转换数据类型?

algorithm - Firebug 算法: How to understand the movement formula

c++ - 环形缓冲区的有效边界检查

python - 需要使用 `non-ndarray sequence` 进行 numpy 基本索引的示例

python - numpy.fft.fft 中参数 n 的影响是什么