我测试了一些代码,其中包括对一些数据运行形式为y = m * x + b
的线性回归。为了简单起见,我将x和y数据设置为相等,期望模型为斜率返回一,为截距返回零。然而,这并不是我所看到的。下面是一个非常简单的例子,主要取自numpy文档:
>>> y = np.arange(5)
>>> x = np.arange(5)
>>> A = np.vstack([x, np.ones(5)]).T
>>> np.linalg.lstsq(A, y)
(array([ 1.00000000e+00, -8.51331872e-16]), array([ 7.50403936e-31]), 2, array([ 5.78859314, 1.22155205]))
>>> # ^slope ^intercept ^residuals ^rank ^singular values
Numpy找到了最适合的真实线的确切斜率(一),但报告了一个截距,虽然非常非常小,但不为零。此外,即使数据可以通过线性方程y = 1 * x + 0
完美地建模,因为没有找到这个精确的方程,numpy报告了一个微小但非零的残差值。
作为一种理智的检查,我在R(我的"母语")中尝试了一下,并观察到了类似的结果:
> x <- c(0 : 4)
> y <- c(0 : 4)
> lm(y ~ x)
Call:
lm(formula = y ~ x)
Coefficients:
(Intercept) x
-3.972e-16 1.000e+00
我的问题是,为什么以及在什么情况下会发生这种情况?这是寻找完美拟合模型的假象,还是回归输出中总是有一点点我们通常看不到的噪音?在这种情况下,答案几乎肯定接近于零,所以我主要是受学术好奇心的驱使。然而,我也想知道,在某些情况下,这种影响是否会被放大,相对于数据来说是不平凡的。
到目前为止,我可能已经揭示了这一点,但我基本上不了解较低级别的编程语言,虽然我曾经粗略地了解过如何"手工"完成这种线性代数,但它早就从我的脑海中消失了。
看起来像是数值误差,y截距非常小。
Python(包括numpy)默认情况下使用双精度浮点数。这些数字被格式化为具有52位系数(浮点解释见此,"基数"的科学符号解释见此)
在你的情况下,你发现y截距约为4e-16。事实证明,52位系数的精度大约为2e-16。基本上,在回归中,你从与它非常相似的东西中减去一个1阶的数字,并达到双浮点的数值精度。