十一、线性回归

作者:Chris Albon

译者:飞龙

协议:CC BY-NC-SA 4.0

添加交互项

十一、线性回归 - 图1

  1. # 加载库
  2. from sklearn.linear_model import LinearRegression
  3. from sklearn.datasets import load_boston
  4. from sklearn.preprocessing import PolynomialFeatures
  5. import warnings
  6. # 屏蔽警告
  7. warnings.filterwarnings(action="ignore", module="scipy", message="^internal gelsd")
  8. # 加载只有两个特征的数据
  9. boston = load_boston()
  10. X = boston.data[:,0:2]
  11. y = boston.target

通过添加一个新的特征,它是交互特征的乘积,来添加交互项。

十一、线性回归 - 图2

其中 十一、线性回归 - 图3十一、线性回归 - 图4 分别是两个特征的值,十一、线性回归 - 图5 表示两者之间的交互。使用 scikit-learn 的PolynomialFeatures,来为所有特征组合创建交互术项会很有用。 然后,我们可以使用模型选择策略,来识别产生最佳模型的特征和交互项的组合。

  1. # 创建交互项(非多项式特征)
  2. interaction = PolynomialFeatures(degree=3, include_bias=False, interaction_only=True)
  3. X_inter = interaction.fit_transform(X)
  4. # 创建线性回归
  5. regr = LinearRegression()
  6. # 拟合线性回归
  7. model = regr.fit(X_inter, y)

创建交互特征

  1. # 加载库
  2. from sklearn.preprocessing import PolynomialFeatures
  3. import numpy as np
  4. # 创建特征矩阵
  5. X = np.array([[2, 3],
  6. [2, 3],
  7. [2, 3]])
  8. # 创建 PolynomialFeatures 对象,它的 interaction_only 设为 True
  9. interaction = PolynomialFeatures(degree=2, interaction_only=True, include_bias=False)
  10. # 转换特征矩阵
  11. interaction.fit_transform(X)
  12. '''
  13. array([[ 2., 3., 6.],
  14. [ 2., 3., 6.],
  15. [ 2., 3., 6.]])
  16. '''

Lasso 回归的 Alpha 的效果

我们通常希望执行一个称为正则化的过程,其中我们会惩罚模型中的系数数量,以便仅保留最重要的系数。 当你拥有带有 100,000 多个系数的数据集时,这一点尤为重要。

Lasso 回归)是正则化的常用建模技术。 它背后的数学非常有趣,但实际上,你需要知道的是,Lasso 回归带有一个参数alpha,而alpha越高,大多数特征系数越会为零。

也就是说,当alpha0时,Lasso 回归产生与线性回归相同的系数。 当alpha非常大时,所有系数都为零。

在本教程中,我运行三个 Lasso 回归,具有不同的alpha值,并显示对系数结果的影响。

  1. from sklearn.linear_model import Lasso
  2. from sklearn.preprocessing import StandardScaler
  3. from sklearn.datasets import load_boston
  4. import pandas as pd
  5. boston = load_boston()
  6. scaler = StandardScaler()
  7. X = scaler.fit_transform(boston["data"])
  8. Y = boston["target"]
  9. names = boston["feature_names"]
  10. # 创建函数 lasso
  11. def lasso(alphas):
  12. '''
  13. 接受 alpha 列表。输出数据帧,包含每个 alpha 的 Lasso 回归的系数。
  14. '''
  15. # 创建空数据帧
  16. df = pd.DataFrame()
  17. # 创建特征名称列
  18. df['Feature Name'] = names
  19. # 对于每个列表中的 alpha 值,
  20. for alpha in alphas:
  21. # 创建这个 alpha 值的 laaso 回归,
  22. lasso = Lasso(alpha=alpha)
  23. # 拟合 lasso 回归
  24. lasso.fit(X, Y)
  25. # 为这个 alpha 值创建列名称
  26. column_name = 'Alpha = %f' % alpha
  27. # 创建系数列
  28. df[column_name] = lasso.coef_
  29. # 返回数据帧
  30. return df
  31. # 调用函数 lasso
  32. lasso([.0001, .5, 10])
Feature NameAlpha = 0.000100Alpha = 0.500000Alpha = 10.000000
0CRIM-0.920130-0.106977-0.0
1ZN1.0804980.0000000.0
2INDUS0.142027-0.000000-0.0
3CHAS0.6822350.3973990.0
4NOX-2.059250-0.000000-0.0
5RM2.6708142.9733230.0
6AGE0.020680-0.000000-0.0
7DIS-3.104070-0.1693780.0
8RAD2.656950-0.000000-0.0
9TAX-2.074110-0.000000-0.0
10PTRATIO-2.061921-1.599574-0.0
11B0.8565530.5457150.0
12LSTAT-3.748470-3.668884-0.0

请注意,随着alpha值的增加,更多特征的系数为 0。

Lasso 回归

  1. # 加载库
  2. from sklearn.linear_model import Lasso
  3. from sklearn.datasets import load_boston
  4. from sklearn.preprocessing import StandardScaler
  5. # 加载数据
  6. boston = load_boston()
  7. X = boston.data
  8. y = boston.target
  9. # 标准化特征
  10. scaler = StandardScaler()
  11. X_std = scaler.fit_transform(X)

超参数 十一、线性回归 - 图6 让我们控制我们对系数的惩罚程度,更高的 十一、线性回归 - 图7 值创建更简单的模型。十一、线性回归 - 图8 的理想值应该像任何其他超参数一样调整。 在 scikit-learn中,使用alpha参数设置 十一、线性回归 - 图9

  1. # 创建带有某个 alpha 值的 Lasso
  2. regr = Lasso(alpha=0.5)
  3. # 拟合 Lasso 回归
  4. model = regr.fit(X_std, y)

线性回归

来源:scikit-learnDrawMyData.

本教程的目的是,简要介绍机器学习中使用的统计模型构建的逻辑。如果你想更加了解本教程背后的理论,请查看统计学习导论

让我们开始吧。

  1. import pandas as pd
  2. from sklearn import linear_model
  3. import random
  4. import numpy as np
  5. %matplotlib inline

添加这些库后,让我们加载数据集(数据集可以在他的站点的 GitHub 仓库中找到)。

  1. # 加载数据
  2. df = pd.read_csv('../data/simulated_data/battledeaths_n300_cor99.csv')
  3. # 打乱数据的行(这是必要的,
  4. # 仅仅由于我使用 DrawMyData 创建数据的方式。真正的分析中通常不需要
  5. df = df.sample(frac=1)

让我们看一下数据的前几行,以便了解它。

  1. # 查看数据的前几行
  2. df.head()
friendly_battledeathsenemy_battledeaths
78.20519.6154
28688.717986.1538
16414.35908.8462
18038.974436.5385
8993.076993.0769

现在让我们绘制数据,以便我们可以看到它的结构。

  1. # 绘制两个变量,彼此对照
  2. df.plot(x='friendly_battledeaths', y='enemy_battledeaths', kind='scatter')
  3. # <matplotlib.axes._subplots.AxesSubplot at 0x1145cdb00>

png

现在是真正的工作了。 为了判断我们的模型有多好,我们需要一些东西来测试它。 我们可以使用称为交叉验证的技术来实现这一目标。 交叉验证可以变得更加复杂和强大,但在这个例子中,我们将使用这种技术的最简单版本。

步骤

  • 将数据集划分为两个数据集:我们将用于训练模型的“训练”数据集,和我们将用于判断该模型准确率的“测试”数据集。
  • 在“训练”数据上训练模型。
  • 将该模型应用于测试数据的X变量,创建模型对测试数据Y的猜测。
  • 比较模型对测试数据Y的预测,与实际测试数据Y的接近程度。
  1. # 创建我们的预测器/自变量
  2. # 以及我们的响应/因变量
  3. X = df['friendly_battledeaths']
  4. y = df['enemy_battledeaths']
  5. # 从前 30 个观测中创建测试数据
  6. X_test = X[0:30].reshape(-1,1)
  7. y_test = y[0:30]
  8. # 从剩余的观测中创建我们的训练数据
  9. X_train = X[30:].reshape(-1,1)
  10. y_train = y[30:]

让我们使用我们的训练数据训练模型。

  1. # 创建 OLS 回归对象
  2. ols = linear_model.LinearRegression()
  3. # 使用训练数据来训练模型
  4. model = ols.fit(X_train, y_train)

以下是模型的一些基本输出,特别是系数和 R 方得分。

  1. # 查看训练模型的系数
  2. model.coef_
  3. # array([ 0.97696721])
  4. # 查看 R 方得分
  5. model.score(X_test, y_test)
  6. # 0.98573393818904709

现在我们已经使用训练数据,来训练一个名为model的模型,我们可以将它应用于测试数据的X,来预测测试数据的Y

以前我们使用X_trainy_train来训练线性回归模型,我们将其存储为一个名为model的变量。 代码model.predict(X_test)将训练好的模型应用于X_test数据,这是模型以前从未见过的数据,来生成Y的预测值。

只需运行代码即可轻松看到:

  1. # 在 X_test 上运行模型并显示前五个结果
  2. list(model.predict(X_test)[0:5])
  3. '''
  4. [7.4633347104887342,
  5. 86.121700007313791,
  6. 13.475493202059415,
  7. 37.523931774900845,
  8. 90.380300060086256]
  9. '''

这个数组是模型对测试数据Y值的最佳猜测。 将它们与实际测试数据Y值进行比较:

  1. # 查看前五个测试 Y 值
  2. list(y_test)[0:5]
  3. '''
  4. [9.6153999999999993,
  5. 86.153800000000004,
  6. 8.8461999999999996,
  7. 36.538499999999999,
  8. 93.076899999999995]
  9. '''

模型的预测值与实际值之间的差异,是我们判断模型的准确率的方式,因为完全准确的模型没有残差。

但是,要判断模型,我们需要一个可用作度量的统计量(数字)。 我们希望这个度量能够捕获数据中所有观测的预测值与实际值之间的差异。

用于量化Y的最常见统计量是残差平方和

十一、线性回归 - 图11

不要让数学符号吓到:

  • 十一、线性回归 - 图12 是我们训练的模型:model.predict(X_test)
  • 十一、线性回归 - 图13 是测试数据的yy_test
  • 十一、线性回归 - 图14 是指数:**2
  • 十一、线性回归 - 图15 是求和:.sum()

在残差的平方和中,对于每个观测,我们找到模型的预测Y和实际Y值之间的差异,然后将该差异平方来使所有值为正。 然后我们将所有这些平方差加在一起得到一个数字。 最终结果是一个统计量,表示模型的预测与实际值的距离。

  1. # 将我们使用训练数据创建的模型
  2. # 应用于测试数据,并计算RSS。
  3. ((y_test - model.predict(X_test)) **2).sum()
  4. # 313.6087355571951

注意:你还可以使用均方差(MSE),它是 RSS 除以自由度。 但我发现用 RSS 来思考是有帮助的。

  1. # 计算 MSE
  2. np.mean((model.predict(X_test) - y_test) **2)
  3. # 10.45362451857317

Sklearn 线性回归

  1. # 加载库
  2. from sklearn.linear_model import LinearRegression
  3. from sklearn.datasets import load_boston
  4. import warnings
  5. # 屏蔽警告
  6. warnings.filterwarnings(action="ignore", module="scipy", message="^internal gelsd")
  7. # 加载数据
  8. boston = load_boston()
  9. X = boston.data
  10. y = boston.target
  11. # 创建线性回归
  12. regr = LinearRegression()
  13. # 拟合线性回归
  14. model = regr.fit(X, y)
  15. # 查看截距(偏差)
  16. model.intercept_
  17. # 36.491103280361038
  18. # 查看特征系数(权重)
  19. model.coef_
  20. '''
  21. array([ -1.07170557e-01, 4.63952195e-02, 2.08602395e-02,
  22. 2.68856140e+00, -1.77957587e+01, 3.80475246e+00,
  23. 7.51061703e-04, -1.47575880e+00, 3.05655038e-01,
  24. -1.23293463e-02, -9.53463555e-01, 9.39251272e-03,
  25. -5.25466633e-01])
  26. '''

岭回归

十一、线性回归 - 图16

  1. # 加载库
  2. from sklearn.linear_model import Ridge
  3. from sklearn.datasets import load_boston
  4. from sklearn.preprocessing import StandardScaler
  5. # 加载数据
  6. boston = load_boston()
  7. X = boston.data
  8. y = boston.target
  9. # 标准化特征
  10. scaler = StandardScaler()
  11. X_std = scaler.fit_transform(X)

超参数 十一、线性回归 - 图17 让我们控制我们对系数的惩罚程度,更高的 十一、线性回归 - 图18 值创建更简单的模型。十一、线性回归 - 图19 的理想值应该像任何其他超参数一样调整。 在 scikit-learn中,使用alpha参数设置 十一、线性回归 - 图20

  1. # 创建带有 alpha 值的岭回归
  2. regr = Ridge(alpha=0.5)
  3. # 拟合岭回归
  4. model = regr.fit(X_std, y)

为岭回归选择最佳的 alpha 值

  1. # 加载库
  2. from sklearn.linear_model import RidgeCV
  3. from sklearn.datasets import load_boston
  4. from sklearn.preprocessing import StandardScaler
  5. # 加载数据
  6. boston = load_boston()
  7. X = boston.data
  8. y = boston.target

注意:因为在线性回归中,系数的值由特征的尺度部分确定,并且在正则化的模型中,所有系数加在一起,我们必须确保在训练之前将特征标准化。

  1. # 标准化特征
  2. scaler = StandardScaler()
  3. X_std = scaler.fit_transform(X)
  4. # 创建带有三个可能 alpha 值的岭回归
  5. regr_cv = RidgeCV(alphas=[0.1, 1.0, 10.0])

scikit-learn 包含RidgeCV方法,允许我们为 十一、线性回归 - 图21 选择理想值:

  1. # 拟合岭回归
  2. model_cv = regr_cv.fit(X_std, y)
  3. # 查看 alpha
  4. model_cv.alpha_
  5. # 1.0