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

时间:2017-10-01 07:37:36

标签: python-3.x scikit-learn statistics regression linear-regression

我正在尝试拟合线性模型,并且我的数据集被归一化,其中每个要素除以最大可能值。所以这些值的范围是0-1。现在我从上一篇文章中了解Linear Regression vs Closed form Ordinary least squares in Python scikit中的线性回归学习当fit_intercept参数设置为false时,与闭合形式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真/假给出了线性回归的不同结果,我不能完全决定它们背后的直觉。哪一个更好,为什么?

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

让我们退后一步,考虑一下您说的以下句子:

  

由于仅将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

无拦截模型

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

regression

使用此方法,由于只有一个预测变量,所以我们得到一个回归系数:

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学习:

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件事:

  1. 我们现在有2个系数。第一个是我们的截距,第二个是x预测变量
  2. 的回归系数
  3. 当我们设置x时,fit_intercept = True的系数与上面的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,则计算出的列为1时,得到的答案实际上与普通方程式相同。

何时应设置True / False?顾名思义,当您不想在模型中包含截距时,可以将其设置为False。当您确实希望截距时,将True设置为True,这会理解系数值会发生变化,但是当数据中包含1的列时,它将与法线方程式相匹配

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