Python 曲线拟合与scipy.odr-绝对西格玛的比较

Python 曲线拟合与scipy.odr-绝对西格玛的比较,python,optimization,scipy,curve-fitting,data-fitting,Python,Optimization,Scipy,Curve Fitting,Data Fitting,目前,我希望使用scipy.odr包拟合x和y中存在错误的数据以及im,以获得结果。我只是想知道错误sx和sy的正确用法。下面是一个例子 假设im测量不同电流I的电压V。 所以我测量了1V,误差为+-0.1V,以此类推。所以如果我假设电流测量没有误差,我可以使用spipy.curve_拟合,如下所示。绝对_σ设置为真,因为我的绝对误差为+-0.1V 所以我得到: from scipy.optimize import curve_fit y=[1,2.5,3,4] x=[1,2,3,4] yerr

目前,我希望使用scipy.odr包拟合x和y中存在错误的数据以及im,以获得结果。我只是想知道错误sx和sy的正确用法。下面是一个例子

假设im测量不同电流I的电压V。 所以我测量了1V,误差为+-0.1V,以此类推。所以如果我假设电流测量没有误差,我可以使用spipy.curve_拟合,如下所示。绝对_σ设置为真,因为我的绝对误差为+-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使用一个非常小的误差,我应该假设得到类似于曲线拟合的结果

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]
但是正如你所看到的,结果不同于上面的曲线拟合,绝对值为真

使用与曲线拟合和绝对σ=假相同的数据会导致与ODR拟合相同的结果

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拟合并没有像曲线拟合和绝对σ=真那样考虑我的绝对误差。有没有办法做到这一点,或者我遗漏了什么?

曲线拟合()中的选项
绝对值
给出了真正的协方差矩阵,即
np.sqrt(np.diag(pcov))
产生1-sigma标准偏差,如数值公式中定义的误差,即它可以有一个单位,像米左右。附带了一个非常有用的摘要

然而,ODR给出了从标度协方差矩阵导出的标准误差。请参见此处或下面的示例

通过ODR进行此缩放,使得减小的chi2(使用相同方式缩放的输入权重计算)产生约1。或从:

该常数是通过要求在使用标度sigma时,最佳参数popt的简化chisq等于单位来设置的

现在剩下的问题是:
sd_beta
到底意味着什么? 这是标准误差,参见示例。, (可能存在两种程度相同的情况。见下文注释) 另请参见前面的讨论:

现在,通过使用减少的chi2缩放
pcov
,可以获得参数误差的相同输出a)
曲线拟合(…,绝对σ=假)
和b)ODR,这是一个基本的相对误差:

#计算chi2
残差=(y-func(x,*popt))
chi_arr=残差/年
chi2_red=(chi_arr**2.sum()/(len(x)-len(popt))
打印('red.chi2:\t\t\t\t',chi2\u-red)
打印('np.sqrt(np.diag(pcov)*chi2_红):\t',np.sqrt(np.diag(pcov)*chi2_红))
屈服:

red. chi2:                           8.75
np.sqrt(np.diag(pcov) * chi2_red):   [0.13228756 0.36228442]
但是,请注意,对于
曲线拟合(…,绝对值
和ODR,来自
曲线拟合的协方差矩阵
pcov
和来自ODR输出的
cov\u beta
仍然是相同的。在这里,来回重新缩放的缺点变得显而易见

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

#标度不确定性
yerr=np.asfarray([0.1,0.1,0.1,0.1])*2
popt,pcov=曲线拟合(func,x,y,sigma=yerr,绝对值sigma=False)
打印('popt:\t\t\t',popt)
打印('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]

我不确定你的结论是否正确。如果您在leastsq模式下使用ODR来拟合带有正常噪声的常数,您将看到sd_β与数据的标准偏差相匹配(曲线_拟合与绝对_σ=False的情况相同)。看看这里:-sd_β实际上是参数的标准偏差。是的,在leastsq模式下的ODR将给出与
np.sqrt(diag(pcov))
(s.a.)相同的
曲线拟合(..,绝对σ=False)
。对于两个cov。矩阵按红色缩放。chi2:对于
曲线拟合(…=假/真)
pcov的输出变化,ODR给出裸cov。矩阵,并在计算
sd_β
之前进行缩放(参见odrpack_guide.pdf中VCVI第85页上的条目。但是,这是标准错误(而不是开发)(参见
out.pprint()
的输出)。ODR文档有时也会讨论sd(参见矢量SDI).我认为这不是一个真正的错误,而是一个不吉利的惯例混合。作为@ChristianK.评论的一个快速补充,是的,它们实际上可以反映真实的标准偏差,但前提是样本量远远大于自由度。我承认,我必须做完整的数学计算才能完全解决这个问题……也许这里有人,哈这已经基本上在这里解释了:对于小的自由度,必须根据学生的统计数据来考虑不确定性的增加。