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)
我们的x
和y
变量如下所示:
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 的线性回归的主要内容,如果未能解决你的问题,请参考以下文章
为啥当 fit_intercept=False 时 Sklearn R-squared 与 statsmodels 不同?