机器学习之线性回归及代码示例

一、线性回归

线性回归一般用来做连续值的预测,预测的结果为一个连续值。因训练时学习样本不仅要提供学习的特征向量X,而且还要提供样本的实际结果(标记label),所以它是一种有监督学习。X= { x0 x1 x2 x3 x4 … xn }。

线性回归需要学习得到的是一个映射关系f:X -> y,即当给定新的待预测样本时,我们可以通过这个映射关系得到一个测试样本X的预测值y。

在线性回归中,假定输入X和输出y之间具有线性相关的关系。
一般地,当特征向量Xi中只有一个特征时,需要学习到的函数应该是一个一元线性函数 y = a+bx,我们可以通过中学的最小二乘法得到其中的a和b两个系数。

当情况复杂时,考虑X存在n个特征的情形下,我们往往需要得到更多地系数。我们将X到y的映射函数记作函数hΘ(X):《机器学习之线性回归及代码示例》

其中,为了在映射函数hΘ(X)中保留常数项,令x0为1,所以特征向量X = { 1 x1 x2 x3 … xn },特征系数向量Θ = { Θ0 Θ1 Θ2 Θ3 … Θn } ,展开后的公式如下图所示:

《机器学习之线性回归及代码示例》

当给定一个训练集数据的情况,可以通过某个算法,学习出来一个线性的映射函数hΘ(X)来求得预测值y。

二、损失函数

在需要通过学习得到的映射函数h(X)中,我们需要通过训练集得到特征系数向量Θ = { Θ0 Θ1 Θ2 Θ3 … Θn } 。

那怎么得到所需的特征系数向量?怎么保证我们得到的特征系数向量是足够好?这里会有一个评判标准:损失函数。

根据特征向量系数Θ,可有损失函数 J(Θ) 如下 :

《机器学习之线性回归及代码示例》

其中hΘ(X)为我们学习到的函数,m为训练集样本的个数,Xi表示训练集中第i个样本的特征向量,yi表示第i个样本中的标签。

为了得到预测值hΘ(Xi)和yi的绝对值,在公式上使用了平方数。为了平均每个样本的损失,在公式上对损失和进行除以m操作。再除以2的原因其实是为了之后的求导计算。

三、梯度下降算法

在上面,找到了一个特征系数向量Θ好坏的损失函数J(Θ)。为了迎合这样的评判标准,我们需对损失函数值进行最小化,即让损失函数在样本中的损失最小。

对于损失函数J(Θ),我们可以发现J(Θ)是一个关于Θ的凸函数。
例如,当Θ只存在一个元素Θ0时,HΘ(X) = Θ0,可在图中看到一条直线。图中红x处为一个样本点。

《机器学习之线性回归及代码示例》

当Θ0由3逐渐变大时,损失函数值会随着增大;当Θ0由3逐渐变小时,损失函数依然会随着增大。

《机器学习之线性回归及代码示例》

这样我们可以直观地认识损失函数J(Θ)是一个往下凹的抛物线,它存在着一个最小值点。

当特征系数向量存在两个元素Θ0和Θ1时,它们与损失函数的关系如图所示呈现一个下凹的曲面状态(但函数叫做凸函数):

《机器学习之线性回归及代码示例》

这图中,可找到损失函数J(Θ)的值达到唯一的最低点时的Θ向量。(凸函数只有唯一的一个最低点)

而梯度下降就是一个不断最小化损失函数的过程。从图像上来看,可以令Θi为某个值,然后让Θi沿着J(Θi)斜率不断地向下走,直达走到底部,然后我们就可以得到J(Θi)最小时的那个Θi的值。

这个不断迭代的过程犹如一个不断下山的过程,我们可以得到图中关于Θi的迭代函数,其中 a 为每次下山的步长。

《机器学习之线性回归及代码示例》

当Θi小于最低处的值的时,其斜率(偏导)为负,在迭代过程中,Θi不断地增大以逼近最低处的值;当Θi大于最低处的值时,斜率(偏导)为正,Θi会不断地做减法以逼近最低处的值。所以当步长a较小时,Θi会收敛于最低处的值。通常,我们将 a 叫做学习率 (learning rate)。

对于特征向量系数Θ中的每个元素Θi,通过上面的迭代公式,它们都会往各自偏导的方向“下山”,“下山”的方向(梯度)为偏导的方向,按照这样的下山方向,下山的速度会更快一点。梯度下降算法就是这么的一个“下山”的过程。

对下山迭代公式进行展开,可得到具体求得Θi的公式:

《机器学习之线性回归及代码示例》

其中,x0(i)为第i个训练样本的第0个特征值,x0(i)通常为1。HΘ(X)为在迭代过程中通过Θ得到的预测函数,它会跟随着Θ的变化而不断地变化。

当学习率a很小时,我们往往需要迭代更多次才可以“下山”达到山底,Θ收敛很慢;当学习率a很大时,“下山”步子迈大后,往往会在山底的两边跳跃,可能无法到达山底,Θ会出现震荡,导致无法收敛。
一般情况下,a可设为0.01,0.005等,也可以在迭代的过程中不断自适应地修改a的值。

四、过渡到多项式回归

通过上面的线性回归,我们可以得到一个线性的映射函数hΘ(X):

《机器学习之线性回归及代码示例》

而对于x1、x2、….、xn特征量,可以将它们更加泛化一下,可以将x1、x2、x3……xn看作特征量的函数。如下图所示:

《机器学习之线性回归及代码示例》

这样一来,hΘ(X)还一样是个线性函数,不过与之线性的不是原本的特征量,而是与 关于特征量的函数 线性相关。通过这样的方法,可将线性回归过渡到多项式回归。

五、过拟合的正则化

当我们的损失函数J(Θ)在样本中损失较大时,会出现欠拟合的情况,即对样本的预测值和样本的实际结果值由较大的差距。如下图所示:

《机器学习之线性回归及代码示例》

当我们的损失函数J(Θ)在样本中损失约等于0时,这时HΘ(X)图像穿过样本的每一个点,这样会出现过拟合的情况,缺乏泛化能力,函数波动比较大,对待预测的样本预测能力比较弱。如下图所示:

《机器学习之线性回归及代码示例》

对于过拟合问题,可以使用 正则化 的方法,即在原来的损失函数上加上一个“尾巴”。

  1. 无正则化时的损失函数:《机器学习之线性回归及代码示例》

  2. L1正则化下的损失函数:《机器学习之线性回归及代码示例》

  3. L2正则化下的损失函数:《机器学习之线性回归及代码示例》

L1正则化和L2正则化也称为Lasso正则化和Ridge正则化,其中alpha为模型的超参数。

因此损失函数不仅要最小化预测值与样本点实际值间的差距了,还得最小化参数向量Θ。当HΘ(X)函数图像穿过所有样本点时,波动会非常大,(平方项、立方项等高次项的)参数Θ值也会非常大,这样会导致它的损失函数并不是最小的。

正则化后,不仅要求HΘ(X)接近更多的点,还要控制(高次项的)Θ值,使得控制函数不能波动太大。而且正则化之后损失函数无法等于0。

六、代码示例

在sklearn的房价数据上使用线性回归,多项式回归:

from sklearn import datasets
boston = datasets.load_boston() # 加载房价数据
X = boston.data
y = boston.target
print X.shape
print y.shape
(506L, 13L)
(506L,)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y ,test_size = 1/3.,random_state = 8)
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score

# 线性回归
lr = LinearRegression(normalize=True,n_jobs=2) 
scores = cross_val_score(lr,X_train,y_train,cv=10,scoring='neg_mean_squared_error') #计算均方误差
print scores.mean()

lr.fit(X_train,y_train)
lr.score(X_test,y_test)
-24.4294227766

0.6922002690740765
from sklearn.preprocessing import PolynomialFeatures
# 多项式回归

for k in range(1,4):
    lr_featurizer = PolynomialFeatures(degree=k) # 用于产生多项式 degree:最高次项的次数
    print '-----%d-----' % k

    X_pf_train = lr_featurizer.fit_transform(X_train)
    X_pf_test = lr_featurizer.transform(X_test)

    pf_scores = cross_val_score(lr,X_pf_train,y_train,cv=10,scoring='neg_mean_squared_error')
    print pf_scores.mean()

    lr.fit(X_pf_train,y_train)
    print lr.score(X_pf_test,y_test)
    print lr.score(X_pf_train,y_train)
-----1-----
-24.4294227766
0.692200269074
0.755769163218
-----2-----
-22.7848754621
0.833095620158
0.93821030015
-----3-----
-6325.76073853
-16.550355583
1.0

当 k=1 时,回归为线性回归;当 k=2 时,回归为多项式回归,模型的效果比线性回归要好一点。
当 k=3 时,已经出现过拟合现象,模型在训练集上得分很高,然而在验证集上得分很低,从交叉验证的得分结果也可以看得出来

# 正则化解决k=3的过拟合现象

lr_featurizer = PolynomialFeatures(degree=3) # 用于产生多项式 degree:最高次项的次数
X_pf_train = lr_featurizer.fit_transform(X_train)
X_pf_test = lr_featurizer.transform(X_test)

# LASSO回归:
from sklearn.linear_model import Lasso

for a in range(0,0.0005):
    print '----%f-----'% a
    lasso = Lasso(alpha=a,normalize=True)
    pf_scores = cross_val_score(lasso,X_pf_train,y_train,cv=10,scoring='neg_mean_squared_error')
    print pf_scores.mean()

    lasso.fit(X_pf_train,y_train)
    print lasso.score(X_pf_test,y_test)
    print lasso.score(X_pf_train,y_train)
----0.000000-----
-29.3011407539


D:\Users\cxm\Anaconda2\lib\site-packages\ipykernel\__main__.py:15: UserWarning: With alpha=0, this algorithm does not converge well. You are advised to use the LinearRegression estimator


0.768272379891
0.965488575704
----0.000500-----
-11.2829107107
0.837992634283
0.943520416421

对比 alpha=0 和 alpha = 0.0005的情况,发现Lasso正则化处理后,模型的评价会提高很多。

# 正则化解决k=3的过拟合现象

lr_featurizer = PolynomialFeatures(degree=3) # 用于产生多项式 degree:最高次项的次数
X_pf_train = lr_featurizer.fit_transform(X_train)
X_pf_test = lr_featurizer.transform(X_test)

from sklearn.linear_model import Ridge

for a in [0,0.005]:
    print '----%f-----'% a
    ridge = Ridge(alpha=a,normalize=True)
    pf_scores = cross_val_score(ridge,X_pf_train,y_train,cv=10,scoring='neg_mean_squared_error')
    print pf_scores.mean()

    ridge.fit(X_pf_train,y_train)
    print ridge.score(X_pf_test,y_test)
    print ridge.score(X_pf_train,y_train)
----0.000000-----
-6143.74385842
-16.4626220878
1.0
----0.005000-----
-14.0438948376
0.823709164706
0.948990485145

对比 alpha=0 和 alpha = 0.0005的情况,发现Ridge正则化处理后,模型的评价会提高很多。

    原文作者:数据挖掘
    原文地址: https://juejin.im/entry/58a94bdb1b69e6006d34dca5
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞