Python 使用scipy.optimize.curve_拟合权重
根据,参数Python 使用scipy.optimize.curve_拟合权重,python,scipy,curve-fitting,Python,Scipy,Curve Fitting,根据,参数sigma可用于设置拟合中数据点的权重。当参数绝对值\u sigma=True时,这些“描述”1-sigma错误 我有一些关于人工正态分布噪声的数据,这些噪声会发生变化: n = 200 x = np.linspace(1, 20, n) x0, A, alpha = 12, 3, 3 def f(x, x0, A, alpha): return A * np.exp(-((x-x0)/alpha)**2) noise_sigma = x/20 noise = np.ran
sigma
可用于设置拟合中数据点的权重。当参数绝对值\u sigma=True
时,这些“描述”1-sigma错误
我有一些关于人工正态分布噪声的数据,这些噪声会发生变化:
n = 200
x = np.linspace(1, 20, n)
x0, A, alpha = 12, 3, 3
def f(x, x0, A, alpha):
return A * np.exp(-((x-x0)/alpha)**2)
noise_sigma = x/20
noise = np.random.randn(n) * noise_sigma
yexact = f(x, x0, A, alpha)
y = yexact + noise
如果我想使用曲线拟合将嘈杂的y
拟合到f
,我应该将sigma
设置为什么?这里的文档不是很具体,但我通常使用1/noise\u sigma**2
作为权重:
p0 = 10, 4, 2
popt, pcov = curve_fit(f, x, y, p0)
popt2, pcov2 = curve_fit(f, x, y, p0, sigma=1/noise_sigma**2, absolute_sigma=True)
不过,这似乎并没有太大的改善
该选项是否仅用于通过协方差矩阵更好地解释拟合不确定性?这两个人告诉我的有什么不同
In [249]: pcov
Out[249]:
array([[ 1.10205238e-02, -3.91494024e-08, 8.81822412e-08],
[ -3.91494024e-08, 1.52660426e-02, -1.05907265e-02],
[ 8.81822412e-08, -1.05907265e-02, 2.20414887e-02]])
In [250]: pcov2
Out[250]:
array([[ 0.26584674, -0.01836064, -0.17867193],
[-0.01836064, 0.27833 , -0.1459469 ],
[-0.17867193, -0.1459469 , 0.38659059]])
至少对于scipy版本1.1.0,参数sigma
应等于每个参数的误差。具体地说,报告说:
1-d西格玛应包含误差的标准偏差值
伊达塔。在这种情况下,优化的函数是chisq=sum((r/sigma)
**(二)
在您的情况下,这将是:
curve_fit(f, x, y, p0, sigma=noise_sigma, absolute_sigma=True)
我仔细查看了代码,并验证了当您以这种方式指定sigma时,它会最小化((f-data)/sigma)**2
作为旁注,当您知道错误时,这通常是您希望最小化的。给定模型的观测点数据
的可能性如下所示:
L(data|x0,A,alpha) = product over i Gaus(data_i, mean=f(x_i,x0,A,alpha), sigma=sigma_i)
如果取负对数,则变为(不取决于参数的常数因子):
这正是问题所在
我编写了一个测试程序来验证曲线拟合
确实返回了正确的值,并且正确指定了sigma:
from __future__ import print_function
import numpy as np
from scipy.optimize import curve_fit, fmin
np.random.seed(0)
def make_chi2(x, data, sigma):
def chi2(args):
x0, A, alpha = args
return np.sum(((f(x,x0,A,alpha)-data)/sigma)**2)
return chi2
n = 200
x = np.linspace(1, 20, n)
x0, A, alpha = 12, 3, 3
def f(x, x0, A, alpha):
return A * np.exp(-((x-x0)/alpha)**2)
noise_sigma = x/20
noise = np.random.randn(n) * noise_sigma
yexact = f(x, x0, A, alpha)
y = yexact + noise
p0 = 10, 4, 2
# curve_fit without parameters (sigma is implicitly equal to one)
popt, pcov = curve_fit(f, x, y, p0)
# curve_fit with wrong sigma specified
popt2, pcov2 = curve_fit(f, x, y, p0, sigma=1/noise_sigma**2, absolute_sigma=True)
# curve_fit with correct sigma
popt3, pcov3 = curve_fit(f, x, y, p0, sigma=noise_sigma, absolute_sigma=True)
chi2 = make_chi2(x,y,noise_sigma)
# double checking that we get the correct answer
xopt = fmin(chi2,p0,xtol=1e-10,ftol=1e-10)
print("popt = %s, chi2 = %.2f" % (popt,chi2(popt)))
print("popt2 = %s, chi2 = %.2f" % (popt2, chi2(popt2)))
print("popt3 = %s, chi2 = %.2f" % (popt3, chi2(popt3)))
print("xopt = %s, chi2 = %.2f" % (xopt, chi2(xopt)))
哪些产出:
popt = [ 11.93617403 3.30528488 2.86314641], chi2 = 200.66
popt2 = [ 11.94169083 3.30372955 2.86207253], chi2 = 200.64
popt3 = [ 11.93128545 3.333727 2.81403324], chi2 = 200.44
xopt = [ 11.93128603 3.33373094 2.81402741], chi2 = 200.44
正如您所见,当您指定sigma=sigma
作为曲线拟合的参数时,chi2确实被正确地最小化
至于为什么改进不是“更好”,我不太确定。我唯一的猜测是,如果不指定sigma值,您会隐式地假设它们相等,并且在拟合重要的数据部分(峰值),误差“近似”相等
要回答你的第二个问题,不,西格玛选项不仅用于改变协方差矩阵的输出,它实际上改变了最小化的内容。当你说它似乎没有多大改善拟合时,你期望看到什么?成群的角马雄伟地横扫平原。否则,我认为rms拟合残差在“有西格玛”的情况下会更好,但更糟(0.64 vs 1.07)。但是,未加权的算法不是使rms最小化了吗(回想一下我做了很多曲线拟合时记忆模糊的日子)?在这种情况下,权重肯定只会增加它?您告诉它“不要太担心这里的这些点,即使以总体rms为代价,也要更好地拟合这些其他点”注意:R的nls需要权重,看起来Python的sigma
对应于nls权重的平方根。为什么sigma=noise?@KornpobBhirombhakdi如果你知道噪声项,那么你可以从数据中减去它,得到一个完美的信号,你甚至不需要拟合任何东西。对于实际数据,您通常知道误差的标准偏差,但不知道每个数据点的实际误差,这就是您拟合的原因。
popt = [ 11.93617403 3.30528488 2.86314641], chi2 = 200.66
popt2 = [ 11.94169083 3.30372955 2.86207253], chi2 = 200.64
popt3 = [ 11.93128545 3.333727 2.81403324], chi2 = 200.44
xopt = [ 11.93128603 3.33373094 2.81402741], chi2 = 200.44