为什么sklearn线性回归会给出通过(0,0)的直线一个非零截距?

3

给定一条线的一些数据点 y = 3x:

from sklearn import datasets, linear_model
X = [[1],[2],[3],[4],[5]]
y = [[3],[6],[9],[12],[15]]
regr = linear_model.LinearRegression()
regr.fit(X,y)

然后:
regr.predict([[6], [7], [8], [9], [10]])

如预期,输出:

array([[ 18.],
       [ 21.],
       [ 24.],
       [ 27.],
       [ 30.]])

regr.coef_是3,正如预期的一样。但为什么regr.intercept_不是0呢?

regr.intercept_
array([ -3.55271368e-15])

3
这句话的意思是“这是0加上舍入误差”。 - user2357112
2个回答

3

这是一个浮点数问题——该数字非常接近于0。你可以使用numpy内置的测试套件来检查。

>>> from numpy.testing import assert_almost_equal
>>> assert_almost_equal(regr.intercept_, 0)

为什么结果不是零,你可以沿着以下的兔子洞找答案:
- sklearn 使用 scipy.linalg.lstsq 进行线性回归拟合, - scipy.linalg.lstsq 使用 LAPACK 中的 gelss 找到 A*x = b 的最小二乘解, - gelss 使用 A 的奇异值分解来求解。
我猜测 gelss 是引入微小误差的地方。

2
-3.55271368e-15可以写成0.000 000 000 000 003 552 713,所以你可以把它看作是零和一个舍入误差。由于我没有阅读sklearn源代码,因此其余部分只是猜测,但它不是真正的零的原因可能是:
  • LinearRegression.fit()需要解决最小化问题(找到ax+b模型和数据集之间平方误差的ab)。
  • 为了解决这个问题,可能会使用收敛到解决方案的迭代算法(梯度下降?)。
  • 它的终止条件可能是类似于Stop when abs(error(step n) - error(step n+1)) < epsilon的东西,其中epsilon是一个固定的小值。

编辑:话说回来,这并不是神经网络。我非常确定线性(或多项式)回归可以通过求导平方误差表达式来精确解决。我觉得sklearn实现它是很奇怪的。


线性回归在这种情况下可以通过解析方法直接求解,无需像你所描述的迭代算法。舍入误差是这种偏差的原因,而不是梯度下降收敛的原因。 - economy
是的,我已经在我的回答底部写了那句话...也许我应该干脆删除整个回答。 - Eloims
我会把它留下来,里面还有很好的信息。没有看到你的编辑,抱歉,我只是想指出,在这种情况下,sklearn无论如何都会使用分析方法来解决线性回归问题。 - economy

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