为啥误差这么大?
Posted
技术标签:
【中文标题】为啥误差这么大?【英文标题】:Why are the errors so large?为什么误差这么大? 【发布时间】:2021-11-17 21:50:36 【问题描述】:我正在尝试使用来自scripy.optimize
的curve_fit
将a*x**b+c
形式的幂律拟合到某些数据点。
这是 MWE:
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
def func_powerlaw(x, m, c, c0):
return c0 + x**m * c
x = np.array([1.05, 1.0, 0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.65, 0.6, 0.55])
y = np.array([1.26, 1.24, 1.2, 1.17, 1.1, 1.01, 0.95, 0.84, 0.75, 0.71, 0.63])
dy = np.array([0.078]*11)
fig, (a1) = plt.subplots(ncols=1,figsize=(10,10))
a1.errorbar(x, y, yerr = dy, ls = '', marker='o')
popt, pcov = curve_fit(func_powerlaw, x, y, sigma = dy, p0 = [0.3, 1, 1], bounds=[(0.1, -2, -2), (0.9, 10, 2)], absolute_sigma=False, maxfev=10000, method = 'trf')
perr=np.sqrt(np.diag(pcov))
xp = np.linspace(x[0],x[-1], 100)
a1.plot(xp, func_powerlaw(xp, *popt), lw=3, zorder = 1, c = 'b')
print(popt, perr)
输出:[0.35609897 3.24929422 -2.] [0.47034928 3.9030258 3.90965249]
对于所有三个参数,误差都大于值估计本身。从经验来看,这不可能是正确的,因为这条线非常适合数据点。
即使我没有设置任何界限和/或初始猜测,值也会改变,但错误仍然太高。
唯一需要的边界是0.1<=m<=0.9
。
我究竟做错了什么?
非常感谢任何帮助!
【问题讨论】:
不确定性dy
表示任何值y_i +/- dy
都与观察到的数据y
兼容。观测数据的大误差会导致拟合参数的大误差。尝试以下操作:for y in np.random.uniform(y - dy, y + dy, size=(25, len(y))): ...
,然后对每个随机采样的y
(在其不确定性边界内采样)执行拟合,但没有表明拟合过程存在错误(sigma
)。然后记录生成的参数估计值 (popt
) 并查看np.mean(popts), np.std(popts)
。第二个值应与您的匹配值相匹配。
用盐的海洋来发表我的意见,因为我从来没有做过这种事情,但它可能会过度拟合吗?
@a_guest 按照这个逻辑,不应该完全删除 sigma 以获得更好的拟合吗?因为似乎恰恰相反。
@chess_lover_6 我也尝试过lmfit
,据我所知,它是curve_fit 的包装器,它打印了 χ^2 值。它们很糟糕,甚至不接近 1。所以我认为这不是因为过度拟合。
@George 首先,将sigma
与absolute_sigma=False
一起使用的值与absolute_sigma=False
一起使用没有任何效果,因为如文档中所述,如果False
(默认),只有 sigma 值的相对大小很重要。尽管如此,这似乎与您手头的问题无关,因为当您完全删除sigma
时,这仍然会导致perr
很大。如果我理解正确,这是您的实际问题:生成的曲线非常适合数据点(例如从绘图或 R2 分数判断),但是报告的 perr
非常大。
【参考方案1】:
拟合参数中的误差大小部分取决于测量误差的大小(代码中的 dy)。正如您在图中看到的那样,sigma 相对于点的分散来说很大,因此各种曲线都可以拟合数据。 dy 值在这里是硬编码的,它们是真实值吗?尝试制作更小,看看它如何影响曲线拟合错误。而且它们在图中看起来像绝对 sigma,因此您应该将 absolute_sigma 标志设置为 True。
作为补充说明,如果您未在 sigma 参数中提供测量误差,则默认值为 1.0(在您的情况下非常大),而不是每个 y 值的 0.0。这就解释了为什么省略 sigma 会产生更大的拟合误差。
【讨论】:
dy 确实是真正的价值。如果 sigma 值是造成大错误的罪魁祸首,不应该完全删除它们会降低错误值吗?尝试这样做会大大增加错误值。将 absolute_sigma 值设置为 true 也是如此。 如果为sigma传入None(默认),每个y点使用默认的测量误差,即1.0。在您的情况下,这是一个很大的误差,因此拟合参数的误差很大。在这种情况下,默认值不是很有帮助! 尝试将测量误差设置为 0.01(例如),看看拟合效果如何。请记住,这些假设为 1 sigma 误差,因此如果测量值正态分布在真实值附近,则最佳拟合线应通过大约 2/3 的误差线。以上是关于为啥误差这么大?的主要内容,如果未能解决你的问题,请参考以下文章