numpy.polyfit:如何获取估计曲线周围的1-sigma不确定性?

3
1个回答

9
如果您有足够的数据点,可以通过 cov=True 参数从 polyfit() 获取一个估计的协方差矩阵。请记住,您可以将多项式 p[0]*t**n + p[1]*t**(n-1) + ... + p[n] 写成矩阵乘积的形式 np.dot(tt, p),其中 tt=[t**n, tt*n-1, ..., 1]t 可以是单个值或列向量。由于这是一条线性方程,因此对于参数 p 的协方差矩阵 C_p,值的协方差矩阵为 np.dot(tt, np.dot(C_p tt.T))
下面是一个简单的例子:
import numpy as np
import matplotlib.pyplot as plt

# sample data:
x = np.array([0.0, 1.0, 2.0, 3.0,  4.0,  5.0,  6.0])
y = np.array([0.0, 0.8, 0.9, 0.1, -0.8, -1.0, -3.0])

n = 3  # degree of polynomial
p, C_p = np.polyfit(x, y, n, cov=True)  # C_z is estimated covariance matrix

# Do the interpolation for plotting:
t = np.linspace(-0.5, 6.5, 500)
# Matrix with rows 1, t, t**2, ...:
TT = np.vstack([t**(n-i) for i in range(n+1)]).T
yi = np.dot(TT, p)  # matrix multiplication calculates the polynomial values
C_yi = np.dot(TT, np.dot(C_p, TT.T)) # C_y = TT*C_z*TT.T
sig_yi = np.sqrt(np.diag(C_yi))  # Standard deviations are sqrt of diagonal

# Do the plotting:
fg, ax = plt.subplots(1, 1)
ax.set_title("Fit for Polynomial (degree {}) with $\pm1\sigma$-interval".format(n))
ax.fill_between(t, yi+sig_yi, yi-sig_yi, alpha=.25)
ax.plot(t, yi,'-')
ax.plot(x, y, 'ro')
ax.axis('tight')

fg.canvas.draw()
plt.show()

给出带1-sigma区间的Polyfit

请注意,计算完整矩阵C_yi在计算和内存方面效率不高。

更新 - 根据@oliver-w的要求,对方法进行简述:

polyfit假定参数x_i是确定性的,而y_i是无关的随机变量,具有期望值y_i和相同的方差sigma。因此,这是一个线性估计问题,可以使用普通最小二乘法。通过确定残差的样本方差,可以近似估计sigma。基于sigma,可以像最小二乘法维基百科文章中所示那样计算pp的协方差矩阵。这几乎是polyfit()使用的方法:其中使用更加保守的因子S/(n-m-2)而不是S/(n-m)来表示sigma


1
有趣。你能引用一个能够证明这种方法的来源吗?到目前为止,我看到了几个人使用不同的技术来向这些图添加某种统计度量,比如这个(一种非常常见的方法,但显然也是不正确的),但很少有人解释为什么它是正确的,读者只是认为它是正确的,因为它看起来很合理。 - Oliver W.
1
这种效果的起源是什么,即在图形的边缘,“填充区域”变宽?这是绘图的效果还是与数据的端点有关? - Christoph Pohl
1
如果更多的数据点靠近给定位置x,那么在该位置的估计值会变得更好,而离该位置越远的下一个数据点,估计值就会变得更糟。 - Dietrich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接