十一、线性回归
作者:Chris Albon
译者:飞龙
添加交互项

# 加载库from sklearn.linear_model import LinearRegressionfrom sklearn.datasets import load_bostonfrom sklearn.preprocessing import PolynomialFeaturesimport warnings# 屏蔽警告warnings.filterwarnings(action="ignore", module="scipy", message="^internal gelsd")# 加载只有两个特征的数据boston = load_boston()X = boston.data[:,0:2]y = boston.target
通过添加一个新的特征,它是交互特征的乘积,来添加交互项。

其中
和
分别是两个特征的值,
表示两者之间的交互。使用 scikit-learn 的PolynomialFeatures,来为所有特征组合创建交互术项会很有用。 然后,我们可以使用模型选择策略,来识别产生最佳模型的特征和交互项的组合。
# 创建交互项(非多项式特征)interaction = PolynomialFeatures(degree=3, include_bias=False, interaction_only=True)X_inter = interaction.fit_transform(X)# 创建线性回归regr = LinearRegression()# 拟合线性回归model = regr.fit(X_inter, y)
创建交互特征
# 加载库from sklearn.preprocessing import PolynomialFeaturesimport numpy as np# 创建特征矩阵X = np.array([[2, 3],[2, 3],[2, 3]])# 创建 PolynomialFeatures 对象,它的 interaction_only 设为 Trueinteraction = PolynomialFeatures(degree=2, interaction_only=True, include_bias=False)# 转换特征矩阵interaction.fit_transform(X)'''array([[ 2., 3., 6.],[ 2., 3., 6.],[ 2., 3., 6.]])'''
Lasso 回归的 Alpha 的效果
我们通常希望执行一个称为正则化的过程,其中我们会惩罚模型中的系数数量,以便仅保留最重要的系数。 当你拥有带有 100,000 多个系数的数据集时,这一点尤为重要。
Lasso 回归)是正则化的常用建模技术。 它背后的数学非常有趣,但实际上,你需要知道的是,Lasso 回归带有一个参数alpha,而alpha越高,大多数特征系数越会为零。
也就是说,当alpha为0时,Lasso 回归产生与线性回归相同的系数。 当alpha非常大时,所有系数都为零。
在本教程中,我运行三个 Lasso 回归,具有不同的alpha值,并显示对系数结果的影响。
from sklearn.linear_model import Lassofrom sklearn.preprocessing import StandardScalerfrom sklearn.datasets import load_bostonimport pandas as pdboston = load_boston()scaler = StandardScaler()X = scaler.fit_transform(boston["data"])Y = boston["target"]names = boston["feature_names"]# 创建函数 lassodef lasso(alphas):'''接受 alpha 列表。输出数据帧,包含每个 alpha 的 Lasso 回归的系数。'''# 创建空数据帧df = pd.DataFrame()# 创建特征名称列df['Feature Name'] = names# 对于每个列表中的 alpha 值,for alpha in alphas:# 创建这个 alpha 值的 laaso 回归,lasso = Lasso(alpha=alpha)# 拟合 lasso 回归lasso.fit(X, Y)# 为这个 alpha 值创建列名称column_name = 'Alpha = %f' % alpha# 创建系数列df[column_name] = lasso.coef_# 返回数据帧return df# 调用函数 lassolasso([.0001, .5, 10])
| Feature Name | Alpha = 0.000100 | Alpha = 0.500000 | Alpha = 10.000000 | |
|---|---|---|---|---|
| 0 | CRIM | -0.920130 | -0.106977 | -0.0 |
| 1 | ZN | 1.080498 | 0.000000 | 0.0 |
| 2 | INDUS | 0.142027 | -0.000000 | -0.0 |
| 3 | CHAS | 0.682235 | 0.397399 | 0.0 |
| 4 | NOX | -2.059250 | -0.000000 | -0.0 |
| 5 | RM | 2.670814 | 2.973323 | 0.0 |
| 6 | AGE | 0.020680 | -0.000000 | -0.0 |
| 7 | DIS | -3.104070 | -0.169378 | 0.0 |
| 8 | RAD | 2.656950 | -0.000000 | -0.0 |
| 9 | TAX | -2.074110 | -0.000000 | -0.0 |
| 10 | PTRATIO | -2.061921 | -1.599574 | -0.0 |
| 11 | B | 0.856553 | 0.545715 | 0.0 |
| 12 | LSTAT | -3.748470 | -3.668884 | -0.0 |
请注意,随着alpha值的增加,更多特征的系数为 0。
Lasso 回归
# 加载库from sklearn.linear_model import Lassofrom sklearn.datasets import load_bostonfrom sklearn.preprocessing import StandardScaler# 加载数据boston = load_boston()X = boston.datay = boston.target# 标准化特征scaler = StandardScaler()X_std = scaler.fit_transform(X)
超参数
让我们控制我们对系数的惩罚程度,更高的
值创建更简单的模型。
的理想值应该像任何其他超参数一样调整。 在 scikit-learn中,使用alpha参数设置
。
# 创建带有某个 alpha 值的 Lassoregr = Lasso(alpha=0.5)# 拟合 Lasso 回归model = regr.fit(X_std, y)
线性回归
本教程的目的是,简要介绍机器学习中使用的统计模型构建的逻辑。如果你想更加了解本教程背后的理论,请查看统计学习导论。
让我们开始吧。
import pandas as pdfrom sklearn import linear_modelimport randomimport numpy as np%matplotlib inline
添加这些库后,让我们加载数据集(数据集可以在他的站点的 GitHub 仓库中找到)。
# 加载数据df = pd.read_csv('../data/simulated_data/battledeaths_n300_cor99.csv')# 打乱数据的行(这是必要的,# 仅仅由于我使用 DrawMyData 创建数据的方式。真正的分析中通常不需要df = df.sample(frac=1)
让我们看一下数据的前几行,以便了解它。
# 查看数据的前几行df.head()
| friendly_battledeaths | enemy_battledeaths | |
|---|---|---|
| 7 | 8.2051 | 9.6154 |
| 286 | 88.7179 | 86.1538 |
| 164 | 14.3590 | 8.8462 |
| 180 | 38.9744 | 36.5385 |
| 89 | 93.0769 | 93.0769 |
现在让我们绘制数据,以便我们可以看到它的结构。
# 绘制两个变量,彼此对照df.plot(x='friendly_battledeaths', y='enemy_battledeaths', kind='scatter')# <matplotlib.axes._subplots.AxesSubplot at 0x1145cdb00>

现在是真正的工作了。 为了判断我们的模型有多好,我们需要一些东西来测试它。 我们可以使用称为交叉验证的技术来实现这一目标。 交叉验证可以变得更加复杂和强大,但在这个例子中,我们将使用这种技术的最简单版本。
步骤
- 将数据集划分为两个数据集:我们将用于训练模型的“训练”数据集,和我们将用于判断该模型准确率的“测试”数据集。
- 在“训练”数据上训练模型。
- 将该模型应用于测试数据的
X变量,创建模型对测试数据Y的猜测。 - 比较模型对测试数据
Y的预测,与实际测试数据Y的接近程度。
# 创建我们的预测器/自变量# 以及我们的响应/因变量X = df['friendly_battledeaths']y = df['enemy_battledeaths']# 从前 30 个观测中创建测试数据X_test = X[0:30].reshape(-1,1)y_test = y[0:30]# 从剩余的观测中创建我们的训练数据X_train = X[30:].reshape(-1,1)y_train = y[30:]
让我们使用我们的训练数据训练模型。
# 创建 OLS 回归对象ols = linear_model.LinearRegression()# 使用训练数据来训练模型model = ols.fit(X_train, y_train)
以下是模型的一些基本输出,特别是系数和 R 方得分。
# 查看训练模型的系数model.coef_# array([ 0.97696721])# 查看 R 方得分model.score(X_test, y_test)# 0.98573393818904709
现在我们已经使用训练数据,来训练一个名为model的模型,我们可以将它应用于测试数据的X,来预测测试数据的Y。
以前我们使用X_train和y_train来训练线性回归模型,我们将其存储为一个名为model的变量。 代码model.predict(X_test)将训练好的模型应用于X_test数据,这是模型以前从未见过的数据,来生成Y的预测值。
只需运行代码即可轻松看到:
# 在 X_test 上运行模型并显示前五个结果list(model.predict(X_test)[0:5])'''[7.4633347104887342,86.121700007313791,13.475493202059415,37.523931774900845,90.380300060086256]'''
这个数组是模型对测试数据Y值的最佳猜测。 将它们与实际测试数据Y值进行比较:
# 查看前五个测试 Y 值list(y_test)[0:5]'''[9.6153999999999993,86.153800000000004,8.8461999999999996,36.538499999999999,93.076899999999995]'''
模型的预测值与实际值之间的差异,是我们判断模型的准确率的方式,因为完全准确的模型没有残差。
但是,要判断模型,我们需要一个可用作度量的统计量(数字)。 我们希望这个度量能够捕获数据中所有观测的预测值与实际值之间的差异。
用于量化Y的最常见统计量是残差平方和:

不要让数学符号吓到:
是我们训练的模型:model.predict(X_test)
是测试数据的y:y_test
是指数:**2
是求和:.sum()
在残差的平方和中,对于每个观测,我们找到模型的预测Y和实际Y值之间的差异,然后将该差异平方来使所有值为正。 然后我们将所有这些平方差加在一起得到一个数字。 最终结果是一个统计量,表示模型的预测与实际值的距离。
# 将我们使用训练数据创建的模型# 应用于测试数据,并计算RSS。((y_test - model.predict(X_test)) **2).sum()# 313.6087355571951
注意:你还可以使用均方差(MSE),它是 RSS 除以自由度。 但我发现用 RSS 来思考是有帮助的。
# 计算 MSEnp.mean((model.predict(X_test) - y_test) **2)# 10.45362451857317
Sklearn 线性回归
# 加载库from sklearn.linear_model import LinearRegressionfrom sklearn.datasets import load_bostonimport warnings# 屏蔽警告warnings.filterwarnings(action="ignore", module="scipy", message="^internal gelsd")# 加载数据boston = load_boston()X = boston.datay = boston.target# 创建线性回归regr = LinearRegression()# 拟合线性回归model = regr.fit(X, y)# 查看截距(偏差)model.intercept_# 36.491103280361038# 查看特征系数(权重)model.coef_'''array([ -1.07170557e-01, 4.63952195e-02, 2.08602395e-02,2.68856140e+00, -1.77957587e+01, 3.80475246e+00,7.51061703e-04, -1.47575880e+00, 3.05655038e-01,-1.23293463e-02, -9.53463555e-01, 9.39251272e-03,-5.25466633e-01])'''
岭回归

# 加载库from sklearn.linear_model import Ridgefrom sklearn.datasets import load_bostonfrom sklearn.preprocessing import StandardScaler# 加载数据boston = load_boston()X = boston.datay = boston.target# 标准化特征scaler = StandardScaler()X_std = scaler.fit_transform(X)
超参数
让我们控制我们对系数的惩罚程度,更高的
值创建更简单的模型。
的理想值应该像任何其他超参数一样调整。 在 scikit-learn中,使用alpha参数设置
。
# 创建带有 alpha 值的岭回归regr = Ridge(alpha=0.5)# 拟合岭回归model = regr.fit(X_std, y)
为岭回归选择最佳的 alpha 值
# 加载库from sklearn.linear_model import RidgeCVfrom sklearn.datasets import load_bostonfrom sklearn.preprocessing import StandardScaler# 加载数据boston = load_boston()X = boston.datay = boston.target
注意:因为在线性回归中,系数的值由特征的尺度部分确定,并且在正则化的模型中,所有系数加在一起,我们必须确保在训练之前将特征标准化。
# 标准化特征scaler = StandardScaler()X_std = scaler.fit_transform(X)# 创建带有三个可能 alpha 值的岭回归regr_cv = RidgeCV(alphas=[0.1, 1.0, 10.0])
scikit-learn 包含RidgeCV方法,允许我们为
选择理想值:
# 拟合岭回归model_cv = regr_cv.fit(X_std, y)# 查看 alphamodel_cv.alpha_# 1.0
