我试图将多项式拟合到一组数据中。有时可能会发生numpy.ployfit
返回的协方差矩阵仅由inf
组成,尽管拟合似乎很有用。没有numpy.inf
或' numpy.nan'在数据中!
示例:
import numpy as np
# sample data, does not contain really x**2-like behaviour,
# but that should be visible in the fit results
x = [-449., -454., -459., -464., -469.]
y = [ 0.9677024, 0.97341953, 0.97724978, 0.98215678, 0.9876293]
fit, cov = np.polyfit(x, y, 2, cov=True)
print 'fit: ', fit
print 'cov: ', cov
结果:
fit: [ 1.67867158e-06 5.69199547e-04 8.85146009e-01]
cov: [[ inf inf inf]
[ inf inf inf]
[ inf inf inf]]
np.cov(x,y)
给出了
[[ 6.25000000e+01 -6.07388099e-02]
[ -6.07388099e-02 5.92268942e-05]]
因此np.cov
与np.polyfit
返回的协方差不同。有谁知道发生了什么?
编辑:
我现在明白numpy.cov
不是我想要的。我需要多项式系数的方差,但如果(len(x) - order - 2.0) == 0
,我不会得到它们。是否有另一种方法来获得拟合多项式系数的方差?
答案 0 :(得分:4)
正如rustil的回答所说,这是由应用于协方差方程的分母的偏差校正引起的,这导致该输入的零分割。这种修正背后的原因类似于Bessel's Correction背后的原因。这实际上表明,以明确定义的方式估计协方差的数据点太少。
如何解决这个问题?好吧,这个版本的polyfit
接受权重。你可以添加另一个数据点,但在epsilon上加权。这相当于将this formula中的2.0
缩减为1.0
。
x = [-449., -454., -459., -464., -469.]
y = [ 0.9677024, 0.97341953, 0.97724978, 0.98215678, 0.9876293]
x_extra = x + x[-1:]
y_extra = y + y[-1:]
weights = [1.0, 1.0, 1.0, 1.0, 1.0, sys.float_info.epsilon]
fit, cov = np.polyfit(x, y, 2, cov=True)
fit_extra, cov_extra = np.polyfit(x_extra, y_extra, 2, w=weights, cov=True)
print fit == fit_extra
print cov_extra
输出。请注意,拟合值是相同的:
>>> print fit == fit_extra
[ True True True]
>>> print cov_extra
[[ 8.84481850e-11 8.11954338e-08 1.86299297e-05]
[ 8.11954338e-08 7.45405039e-05 1.71036963e-02]
[ 1.86299297e-05 1.71036963e-02 3.92469307e+00]]
我非常不确定这会特别有意义,但它是一种解决问题的方法。虽然它有点像kludge。对于更健壮的东西,您可以修改polyfit
以接受其自己的ddof
参数,也许代替cov
当前接受的布尔值。 (我只是opened an issue建议尽可能多。)
关于cov
计算的快速最后说明:如果您查看least squares regression上的维基百科页面,您会看到系数协方差的简化公式为{{ 1}},在numpy代码中有corresponding line - 至少粗略地说。在这种情况下,inv(dot(dot(X, W), X))
是Vandermonde matrix,权重已经是multiplied in。 numpy代码也进行了一些缩放(我理解;它是最小化数值误差的策略的一部分),并将结果乘以残差的范数(我不明白;我只能猜测它是协方差公式的另一个版本的一部分。)
答案 1 :(得分:2)
差异应该在于自由度。在polyfit
方法中,它已经考虑到您的学位是2,从而导致:
RuntimeWarning: divide by zero encountered in true_divide
fac = resids / (len(x) - order - 2.0)
您可以传递np.cov
ddof=
个关键字(ddof = delta自由度),您将遇到同样的问题