摘要: 线性回归是众所周知的非常基本的算法,但也存在很多不足。为了是算法模型能够具有更好的泛化能够,不至于模型过拟合,当前研究就传统的线性回归算法的基础上增加正则项,添加 l 1 l_1 l1正则就是LASSO回归,添加 l 2 l_2 l2正则就是岭回归,本文通过对这几个算法进行比较来说明各自的特点。
关键字: 线性回归,岭回归,LASSO回归。
线性回归算法是机器学习算法中的一个入门算法,简单容易理解,但是传统的线性回归算法有很多缺点,容易过拟合等等。为了克服这种缺点,当前研究提出增加正则项(很多机器学习方法都使用)的方式降低模型的过拟合,提高模型的泛化能力。
传统对于有一个有 n n n个特征的数据 x x x的线性回归模型如下,也可参考我之前的文章:【机器学习】吴恩达机器学习视频作业-线性回归。
h ( x ) = w 1 x 1 + w 2 x 2 + ⋯ + w n x n + b h\left( x \right) =w_1x_1+w_2x_2+\cdots +w_nx_n+b h(x)=w1x1+w2x2+⋯+wnxn+b
对于一些线性回归的任务可以做,但是不采取一些方式容易过拟合(机器学习算法都是如此)。我们使用波斯顿房价数据集看看,处理过的波斯顿房价数据集的特征增加到了105个。
from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_boston
from sklearn.preprocessing import MinMaxScaler, PolynomialFeatures
from sklearn.model_selection import train_test_split
def load_extended_boston():
boston = load_boston()
X = boston.data
X = MinMaxScaler().fit_transform(boston.data) # 数据归一化处理
# 使用多项式的方法来进行的,如果有a,b两个特征,那么它的2次多项式为(1,a,b,a^2,ab, b^2),degree:控制多项式的度
# interaction_only: 默认为False,如果指定为True,那么就不会有特征自己和自己结合的项,上面的二次项中没有a^2和b^2。
# include_bias:默认为True。如果为True的话,那么就会有上面的 1那一项。
X = PolynomialFeatures(degree=2, include_bias=False).fit_transform(X)
return X, boston.target
X, y = load_extended_boston()
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
lr = LinearRegression().fit(X_train, y_train)
print("Training set score:{:.2f}".format(lr.score(X_train, y_train))) # 训练集的测试分数
print("Training set score:{:.2f}".format(lr.score(X_test, y_test))) # 测试集的测试分数
"""
Training set score:0.95
Training set score:0.61
"""
从测试得分可以看出,在训练集得分较高而测试集分数较低,也就是说过拟合了。
补充: 如何查看训练好模型中的权重参数 w w w和截距 b b b呢?其分布保存在:coef_
和intercept_
,查看方式如下:
print("lr.coef_:{}".format(lr.coef_))
print("lr.intercept_:{}".format(lr.intercept_))
"""
lr.coef_:[-4.12710947e+02 -5.22432068e+01 -1.31898815e+02 -1.20041365e+01
-1.55107129e+01 2.87163342e+01 5.47040992e+01 -4.95346659e+01
....
1.19553429e+01 6.77025947e-01 2.73452009e+00 3.03720012e+01]
lr.intercept_:30.934563673637694
"""
岭回归也是一种用于回归的线性模型,与传统的线性模型有很多相似之处。为了降低过拟合的情况,也就是说不仅要在训练集上的数据效果好,在测试集上的数据也要好,这样模型才具有不错的泛化能力。这里是希望特征数据的权重尽可能小,减小数据受权重的制约,一般来说,我们是权重参数 w w w接近于0。这里就引入正则化(regularization),避免模型过拟合。岭回归就是具有 l 2 l_2 l2正则化的回归,相关内容可以参考:【机器学习】模型优化改进建议。下面我们来看看如何使用sklearn实现岭回归。
from sklearn.linear_model import Ridge
ridge = Ridge().fit(X_train, y_train)
print("Training set score:{:.2f}".format(ridge.score(X_train, y_train))) # 训练集的测试分数
print("Training set score:{:.2f}".format(ridge.score(X_test, y_test))) # 测试集的测试分数
"""
Training set score:0.89
Training set score:0.75
"""
从结果可以看出Ridge训练集的分数低于LinerRegression,在测试集上的分数更高。这就是使用正则降低过拟合的结果。当然我们也可以通过修改参数alpha指定正则化项的系数,Ridge默认是1。当然,alpha过大过小都不好,这也是需要进行模型调参了,因为这是需要根据数据集进行处理的。例如我们使用alpha=0.5来测试一下模型的性能:
ridge = Ridge(alpha=0.5).fit(X_train, y_train)
print("Training set score:{:.2f}".format(ridge.score(X_train, y_train))) # 训练集的测试分数
print("Training set score:{:.2f}".format(ridge.score(X_test, y_test))) # 测试集的测试分数
"""
Training set score:0.90
Training set score:0.77
"""
注意,减小alpha可以让系数(w)受到的限制更小,当alpha特别小的时候就可以普通的LinearRegression没什么区别了。使用正则化进行优化模型的相关概念在【机器学习】模型优化改进建议已经介绍,不再赘述。
这种方法是 l 1 l_1 l1正则化(就是系数绝对值之和)。使用lasso时某些系数刚好为0(这是一个最优化问题,可参考文献1),也就是一些特征就会被模型忽略了。下面我们做一下实验:
from sklearn.linear_model import Lasso
import numpy as np
lasso = Lasso().fit(X_train, y_train)
print("Training set score:{:.2f}".format(lasso.score(X_train, y_train)))
print("Test set score:{:.2f}".format(lasso.score(X_test, y_test)))
print("Number of features used:{}".format(np.sum(lasso.coef_ != 0)))
"""
Training set score:0.29
Test set score:0.21
Number of features used:4
"""
可以看出这个结果惨不忍睹,使用的特征也仅仅只有4个。这时我们就需要通过控制正则化的系数alpha(默认为1.0)来改变这个状况。同时,为了降低欠拟合,可以尝试较小alpha,这个和Ridge相似,并且还需要增加max_iter的值,即增加运行迭代的最大次数。修改如下:
lasso001 = Lasso(alpha=0.01, max_iter=100000).fit(X_train, y_train)
print("Training set score:{:.2f}".format(lasso001.score(X_train, y_train)))
print("Test set score:{:.2f}".format(lasso001.score(X_test, y_test)))
print("Number of features used:{}".format(np.sum(lasso001.coef_ != 0)))
"""
Training set score:0.90
Test set score:0.77
Number of features used:33
"""
这个时候我们就可以看出,不管是在训练集上还是测试集上表现得都挺不错,同时也只是用了105个特征中的33个。当然如果将alpha这个参数调得太小也就和传统得LinearRegression类似了。