fit_intercept 参数如何影响 scikit learn 的线性回归

Posted

技术标签:

【中文标题】fit_intercept 参数如何影响 scikit learn 的线性回归【英文标题】:How fit_intercept parameter impacts linear regression with scikit learn 【发布时间】:2018-03-12 14:57:22 【问题描述】:

我正在尝试拟合线性模型,并且我的数据集已标准化,其中每个特征都除以最大可能值。所以值的范围是 0-1。现在我从我之前的帖子中了解到,当 fit_intercept 参数设置为 false 时,scikit learn 中的线性回归 Linear Regression vs Closed form Ordinary least squares in Python 会产生与封闭形式 OLS 相同的结果。我不太明白fit_intercept 的工作原理。

对于任何线性问题,如果 y 是预测值。

y(w, x) = w_0 + w_1 x_1 + ... + w_p x_p

在整个模块中,向量 w = (w_1, ..., w_p) 表示为 coef_,w_0 表示为 intercept_

在封闭形式的 OLS 中,w_0 也有一个偏差值,我们在计算点积之前引入向量 X_0=[1...1] 并使用矩阵乘法和逆矩阵求解。

w = np.dot(X.T, X) 
w1 = np.dot(np.linalg.pinv(w), np.dot(X.T, Y))

fit_intercept 为 True 时,如果 y 是预测值,scikit-learn 线性回归解决问题。

y(w, x) = w_0 + w_1 x_1 + ... + w_p x_p + b 其中 b 是拦截项。

在模型中使用fit_intercept 有何不同,何时应将其设置为 True/False。我试图查看源代码,似乎系数已按一定比例进行了归一化。

if self.fit_intercept:
    self.coef_ = self.coef_ / X_scale
    self.intercept_ = y_offset - np.dot(X_offset, self.coef_.T)
else:
    self.intercept_ = 0

这种缩放究竟做了什么。我想解释这两种方法(线性回归,封闭形式 OLS)中的系数,但由于仅设置 fit_intercept True/False 会为线性回归给出不同的结果,我无法完全确定它们背后的直觉。哪个更好,为什么?

【问题讨论】:

OLS 的链接答案中没有拦截项。您确实提供了一些伪代码(或者至少看起来像那样)。正确实施它,您将获得相同的结果(如果您在规范化方面没有差异)。 我使用 fit_intercept=False 获得了更接近的结果。但在这里我的问题是一种理论上的问题。假设我想根据从上述步骤中找到的系数提取重要特征。现在只需设置 fit_intercept True/False 会给出完全不同的结果,因此最好考虑哪一个。在所有机器学习书籍中,线性回归方法在没有截距参数的情况下解决了它,但 scikit-learn 引入了它。 cs229.stanford.edu/notes/cs229-notes1.pdf,我也学过 Andrew Ng 的 ML 课程。所以这个 fit_intercept 是我无法与我所知道的联系起来的。是否有任何论文参考资料可供我查找 fit_intercept 的解释。 资源太多了。我无法想象你没有偶然发现任何有用的东西。 Here 例如。如果您没有充分的理由不这样做,就使用它。 【参考方案1】:

在不涉及数学公式的细节的情况下,当拟合截距设置为 false 时,估计器故意将截距设置为零,这反过来会影响其他回归器,因为减少误差的“责任”落在这些因素上.因此,如果它对截距项的存在敏感,则在任何一种情况下结果都可能非常不同。缩放会移动原点,从而允许相同的闭环解决方案同时用于拦截和无拦截模型。

【讨论】:

【参考方案2】:

让我们退后一步,想想你说的下面这句话:

因为仅设置 fit_intercept True/False 会为线性回归提供不同的结果

这并不完全正确。它可能会或可能不会不同,这完全取决于您的数据。这将有助于理解回归权重的计算内容。我的意思有点字面意思:您的输入 (x) 数据是什么样的?

了解您的输入数据并了解其重要性,将帮助您了解为什么有时会得到不同的结果,而有时结果却是相同的

数据设置

让我们设置一些测试数据:

import numpy as np
from sklearn.linear_model import LinearRegression

np.random.seed(1243)

x = np.random.randint(0,100,size=10)
y = np.random.randint(0,100,size=10)

我们的xy 变量如下所示:

   X   Y
  51  29
   3  73
   7  77
  98  29
  29  80
  90  37
  49   9
  42  53
   8  17
  65  35

无拦截模型

回想一下,回归权重的计算有一个封闭形式的解,我们可以使用正规方程获得:

使用这种方法,我们得到一个回归系数,因为我们只有 1 个预测变量:

x = x.reshape(-1,1)
w = np.dot(x.T, x)
w1 = np.dot(np.linalg.pinv(w), np.dot(x.T, y))

print(w1)
[ 0.53297593]

现在,让我们看看设置fit_intercept = False时的scikit-learn:

clf = LinearRegression(fit_intercept=False)

print(clf.fit(x, y).coef_)
[ 0.53297593]

当我们改为设置fit_intercept = True 时会发生什么?

clf = LinearRegression(fit_intercept=True)

print(clf.fit(x, y).coef_)
[-0.35535884]

似乎将fit_intercept 设置为 True 和 False 会给出不同的答案,并且只有当我们将其设置为 False 时才会出现“正确”答案,但这并不完全正确...

拦截模型

此时我们必须考虑我们的输入数据实际上是什么。在上面的模型中,我们的数据矩阵(也称为特征矩阵,或统计学中的设计矩阵)只是一个包含我们x 值的向量。 y 变量不包含在设计矩阵中。如果我们想在模型中添加截距,一种常见的方法是在设计矩阵中添加一列 1,因此x 变为:

x_vals = x.flatten()
x = np.zeros((10, 2))
x[:,0] = 1
x[:,1] = x_vals

   intercept     x
0        1.0  51.0
1        1.0   3.0
2        1.0   7.0
3        1.0  98.0
4        1.0  29.0
5        1.0  90.0
6        1.0  49.0
7        1.0  42.0
8        1.0   8.0
9        1.0  65.0

现在,当我们使用它作为我们的设计矩阵时,我们可以再次尝试封闭形式的解决方案:

w = np.dot(x.T, x)
w1 = np.dot(np.linalg.pinv(w), np.dot(x.T, y))

print(w1)
[ 59.60686058  -0.35535884]

注意两件事:

    我们现在有 2 个系数。第一个是我们的截距,第二个是x 预测变量的回归系数 当我们设置fit_intercept = True 时,x 的系数与上面 scikit-learn 输出的系数相匹配

那么在上面的 scikit-learn 模型中,为什么 True 和 False 之间存在差异?因为在一种情况下,没有对截距进行建模。在另一种情况下,基础模型包含一个截距,当您在求解正规方程时手动添加截距项/列时会确认这一点

如果你在 scikit-learn 中使用这个新的设计矩阵,不管你为 fit_intercept 设置 True 还是 False,预测变量的系数都不会改变(截距值会不同,因为居中,但这与本次讨论无关):

clf = LinearRegression(fit_intercept=False)
print(clf.fit(x, y).coef_)
[ 59.60686058  -0.35535884]

clf = LinearRegression(fit_intercept=True)
print(clf.fit(x, y).coef_)
[ 0.         -0.35535884]

总结

您获得的输出(即系数值)将完全取决于您输入到这些计算中的矩阵(无论是其正规方程、scikit-learn 还是任何其他)

在模型中使用 fit_intercept 有何不同,何时应将其设置为 True/False

如果您的设计矩阵包含 1 的列,那么正规方程和 scikit-learn (fit_intercept = False) 将为您提供相同的答案(如您所述)。但是,如果您将参数设置为 True,如果您计算 with 为 1 的列,您得到的答案实际上将与正规方程相同。

什么时候应该设置 True/False?顾名思义,当您不想在模型中包含截距时,您设置 False。当您确实想要截距时设置 True ,并理解系数值会发生变化,但当您的数据包含 1 列时将匹配正规方程方法

因此,在考虑相同的基础模型时,True/False 实际上并没有给您不同的结果(与正规方程相比)。您观察到的差异是因为您正在查看两种不同的统计模型(一个带有截距项,一个没有截距项)。 fit_intercept 参数存在的原因是您可以创建截距模型,而无需手动添加该 1 的列。它有效地允许您在两个基础统计模型之间切换。

【讨论】:

以上是关于fit_intercept 参数如何影响 scikit learn 的线性回归的主要内容,如果未能解决你的问题,请参考以下文章

LassoLarsCV算法参数

通俗得说线性回归算法线性回归实战

机器学习算法:线性回归API详细介绍

为啥当 fit_intercept=False 时 Sklearn R-squared 与 statsmodels 不同?

Sklearn实现逻辑回归

sklearn