gpt4 book ai didi

python - 使用 python 中的 optimize.leastsq 方法获取拟合参数的标准误差

转载 作者:IT老高 更新时间:2023-10-28 21:50:34 30 4
gpt4 key购买 nike

我有一组数据(位移 vs 时间),我使用 optimize.leastsq 方法将它们拟合到几个方程中。我现在正在寻找拟合参数的错误值。查看文档,输出的矩阵是雅可比矩阵,我必须将其乘以残差矩阵才能得到我的值。不幸的是,我不是统计学家,所以我对术语有些不知所措。

据我所知,我需要的是与我的拟合参数相匹配的协方差矩阵,因此我可以对对角线元素求平方以获得拟合参数的标准误差。我有一个模糊的阅读内存,协方差矩阵无论如何都是从 optimize.leastsq 方法输出的。这样对吗?如果不是,你将如何让残差矩阵与输出的雅可比矩阵相乘以获得我的协方差矩阵?

任何帮助将不胜感激。我对 python 很陌生,因此如果问题是一个基本问题,我深表歉意。

拟合代码如下:

fitfunc = lambda p, t: p[0]+p[1]*np.log(t-p[2])+ p[3]*t # Target function'

errfunc = lambda p, t, y: (fitfunc(p, t) - y)# Distance to the target function

p0 = [ 1,1,1,1] # Initial guess for the parameters


out = optimize.leastsq(errfunc, p0[:], args=(t, disp,), full_output=1)

args t 和 disp 是时间和位移值的数组(基本上只有 2 列数据)。我已经在代码的顶部导入了所有需要的东西。拟合值和输出提供的矩阵如下:
[  7.53847074e-07   1.84931494e-08   3.25102795e+01  -3.28882437e-11]

[[ 3.29326356e-01 -7.43957919e-02 8.02246944e+07 2.64522183e-04]
[ -7.43957919e-02 1.70872763e-02 -1.76477289e+07 -6.35825520e-05]
[ 8.02246944e+07 -1.76477289e+07 2.51023348e+16 5.87705672e+04]
[ 2.64522183e-04 -6.35825520e-05 5.87705672e+04 2.70249488e-07]]

无论如何,我怀疑现在的合身有点可疑。当我可以解决错误时,这将得到确认。

最佳答案

2016 年 4 月 6 日更新

在大多数情况下,在拟合参数中获得正确的错误可能是微妙的。

让我们考虑拟合一个函数 y=f(x)您有一组数据点 (x_i, y_i, yerr_i) ,其中 i是运行在每个数据点上的索引。

在大多数物理测量中,误差 yerr_i是测量设备或程序的系统不确定度,因此可以将其视为不依赖于 i 的常数。 .

使用哪个拟合函数,以及如何获取参数误差?
optimize.leastsq方法将返回分数协方差矩阵。将此矩阵的所有元素乘以残差方差(即减少的卡方)并取对角元素的平方根,您将得到拟合参数标准偏差的估计值。我已经在以下功能之一中包含了执行此操作的代码。

另一方面,如果您使用 optimize.curvefit ,上述过程的第一部分(乘以减少的卡方)是在幕后为您完成的。然后,您需要取协方差矩阵的对角元素的平方根,以获得拟合参数标准偏差的估计值。

此外,optimize.curvefit提供可选参数来处理更一般的情况,其中 yerr_i每个数据点的值都不同。来自 documentation :

sigma : None or M-length sequence, optional
If not None, the uncertainties in the ydata array. These are used as
weights in the least-squares problem
i.e. minimising ``np.sum( ((f(xdata, *popt) - ydata) / sigma)**2 )``
If None, the uncertainties are assumed to be 1.

absolute_sigma : bool, optional
If False, `sigma` denotes relative weights of the data points.
The returned covariance matrix `pcov` is based on *estimated*
errors in the data, and is not affected by the overall
magnitude of the values in `sigma`. Only the relative
magnitudes of the `sigma` values matter.

我如何确定我的错误是正确的?

确定拟合参数中标准误差的正确估计是一个复杂的统计问题。协方差矩阵的结果,由 optimize.curvefit 实现和 optimize.leastsq实际上依赖于关于错误概率分布和参数之间相互作用的假设;可能存在的相互作用,取决于您的特定拟合函数 f(x) .

在我看来,处理复杂的最好方法 f(x)是使用 bootstrap 方法,在 this link 中进行了概述。 .

让我们看一些例子

首先,一些样板代码。让我们定义一个波浪线函数并生成一些带有随机误差的数据。我们将生成一个随机误差很小的数据集。
import numpy as np
from scipy import optimize
import random

def f( x, p0, p1, p2):
return p0*x + 0.4*np.sin(p1*x) + p2

def ff(x, p):
return f(x, *p)

# These are the true parameters
p0 = 1.0
p1 = 40
p2 = 2.0

# These are initial guesses for fits:
pstart = [
p0 + random.random(),
p1 + 5.*random.random(),
p2 + random.random()
]

%matplotlib inline
import matplotlib.pyplot as plt
xvals = np.linspace(0., 1, 120)
yvals = f(xvals, p0, p1, p2)

# Generate data with a bit of randomness
# (the noise-less function that underlies the data is shown as a blue line)

xdata = np.array(xvals)
np.random.seed(42)
err_stdev = 0.2
yvals_err = np.random.normal(0., err_stdev, len(xdata))
ydata = f(xdata, p0, p1, p2) + yvals_err

plt.plot(xvals, yvals)
plt.plot(xdata, ydata, 'o', mfc='None')

fig01

现在,让我们使用各种可用的方法来拟合函数:

`optimize.leastsq`
def fit_leastsq(p0, datax, datay, function):

errfunc = lambda p, x, y: function(x,p) - y

pfit, pcov, infodict, errmsg, success = \
optimize.leastsq(errfunc, p0, args=(datax, datay), \
full_output=1, epsfcn=0.0001)

if (len(datay) > len(p0)) and pcov is not None:
s_sq = (errfunc(pfit, datax, datay)**2).sum()/(len(datay)-len(p0))
pcov = pcov * s_sq
else:
pcov = np.inf

error = []
for i in range(len(pfit)):
try:
error.append(np.absolute(pcov[i][i])**0.5)
except:
error.append( 0.00 )
pfit_leastsq = pfit
perr_leastsq = np.array(error)
return pfit_leastsq, perr_leastsq

pfit, perr = fit_leastsq(pstart, xdata, ydata, ff)

print("\n# Fit parameters and parameter errors from lestsq method :")
print("pfit = ", pfit)
print("perr = ", perr)
# Fit parameters and parameter errors from lestsq method :
pfit = [ 1.04951642 39.98832634 1.95947613]
perr = [ 0.0584024 0.10597135 0.03376631]



`optimize.curve_fit`
def fit_curvefit(p0, datax, datay, function, yerr=err_stdev, **kwargs):
"""
Note: As per the current documentation (Scipy V1.1.0), sigma (yerr) must be:
None or M-length sequence or MxM array, optional
Therefore, replace:
err_stdev = 0.2
With:
err_stdev = [0.2 for item in xdata]
Or similar, to create an M-length sequence for this example.
"""
pfit, pcov = \
optimize.curve_fit(f,datax,datay,p0=p0,\
sigma=yerr, epsfcn=0.0001, **kwargs)
error = []
for i in range(len(pfit)):
try:
error.append(np.absolute(pcov[i][i])**0.5)
except:
error.append( 0.00 )
pfit_curvefit = pfit
perr_curvefit = np.array(error)
return pfit_curvefit, perr_curvefit

pfit, perr = fit_curvefit(pstart, xdata, ydata, ff)

print("\n# Fit parameters and parameter errors from curve_fit method :")
print("pfit = ", pfit)
print("perr = ", perr)
# Fit parameters and parameter errors from curve_fit method :
pfit = [ 1.04951642 39.98832634 1.95947613]
perr = [ 0.0584024 0.10597135 0.03376631]

`引导`
def fit_bootstrap(p0, datax, datay, function, yerr_systematic=0.0):

errfunc = lambda p, x, y: function(x,p) - y

# Fit first time
pfit, perr = optimize.leastsq(errfunc, p0, args=(datax, datay), full_output=0)


# Get the stdev of the residuals
residuals = errfunc(pfit, datax, datay)
sigma_res = np.std(residuals)

sigma_err_total = np.sqrt(sigma_res**2 + yerr_systematic**2)

# 100 random data sets are generated and fitted
ps = []
for i in range(100):

randomDelta = np.random.normal(0., sigma_err_total, len(datay))
randomdataY = datay + randomDelta

randomfit, randomcov = \
optimize.leastsq(errfunc, p0, args=(datax, randomdataY),\
full_output=0)

ps.append(randomfit)

ps = np.array(ps)
mean_pfit = np.mean(ps,0)

# You can choose the confidence interval that you want for your
# parameter estimates:
Nsigma = 1. # 1sigma gets approximately the same as methods above
# 1sigma corresponds to 68.3% confidence interval
# 2sigma corresponds to 95.44% confidence interval
err_pfit = Nsigma * np.std(ps,0)

pfit_bootstrap = mean_pfit
perr_bootstrap = err_pfit
return pfit_bootstrap, perr_bootstrap

pfit, perr = fit_bootstrap(pstart, xdata, ydata, ff)

print("\n# Fit parameters and parameter errors from bootstrap method :")
print("pfit = ", pfit)
print("perr = ", perr)
# Fit parameters and parameter errors from bootstrap method :
pfit = [ 1.05058465 39.96530055 1.96074046]
perr = [ 0.06462981 0.1118803 0.03544364]

观察

我们已经开始看到一些有趣的东西,所有三种方法的参数和误差估计几乎一致。那很好!

现在,假设我们想告诉拟合函数我们的数据中还有一些其他的不确定性,也许是一种系统性的不确定性,它会导致 err_stdev 值的 20 倍的额外误差。 .这是一个很大的错误,事实上,如果我们用这种错误模拟一些数据,它看起来像这样:

enter image description here

我们当然没有希望在这种噪音水平下恢复拟合参数。

首先,让我们意识到 leastsq甚至不允许我们输入这个新的系统误差信息。看什么 curve_fit当我们告诉它错误时会这样做:
pfit, perr = fit_curvefit(pstart, xdata, ydata, ff, yerr=20*err_stdev)

print("\nFit parameters and parameter errors from curve_fit method (20x error) :")
print("pfit = ", pfit)
print("perr = ", perr)
Fit parameters and parameter errors from curve_fit method (20x error) :
pfit = [ 1.04951642 39.98832633 1.95947613]
perr = [ 0.0584024 0.10597135 0.03376631]

什么??这肯定是错误的!

这曾经是故事的结局,但最近 curve_fit添加了 absolute_sigma可选参数:
pfit, perr = fit_curvefit(pstart, xdata, ydata, ff, yerr=20*err_stdev, absolute_sigma=True)

print("\n# Fit parameters and parameter errors from curve_fit method (20x error, absolute_sigma) :")
print("pfit = ", pfit)
print("perr = ", perr)
# Fit parameters and parameter errors from curve_fit method (20x error, absolute_sigma) :
pfit = [ 1.04951642 39.98832633 1.95947613]
perr = [ 1.25570187 2.27847504 0.72600466]

这样好一些,但仍然有点可疑。 curve_fit认为我们可以从这个嘈杂的信号中得到一个拟合,在 p1 中有 10% 的误差水平范围。看什么 bootstrap不得不说:
pfit, perr = fit_bootstrap(pstart, xdata, ydata, ff, yerr_systematic=20.0)

print("\nFit parameters and parameter errors from bootstrap method (20x error):")
print("pfit = ", pfit)
print("perr = ", perr)
Fit parameters and parameter errors from bootstrap method (20x error):
pfit = [ 2.54029171e-02 3.84313695e+01 2.55729825e+00]
perr = [ 6.41602813 13.22283345 3.6629705 ]

啊,这可能是对拟合参数误差的更好估计。 bootstrap自以为知道 p1大约有 34% 的不确定性。

概括
optimize.leastsqoptimize.curvefit为我们提供了一种估计拟合参数误差的方法,但我们不能只使用这些方法而不稍微质疑它们。 bootstrap是一种使用蛮力的统计方法,在我看来,它倾向于在可能难以解释的情况下更好地工作。

我强烈建议查看特定问题,然后尝试 curvefitbootstrap .如果它们相似,则 curvefit计算成本要低得多,因此可能值得使用。如果它们显着不同,那么我的钱将放在 bootstrap 上。 .

关于python - 使用 python 中的 optimize.leastsq 方法获取拟合参数的标准误差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14581358/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com