前言

线性回归主要用于对于预测方面的使用,比如房价预测,最经典的案例就是波士顿房价预测,这个在下文将会提到

线性回归

线性回归(Linear regression)是利用回归方程(函数)一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。

  • 特点:只有一个自变量的情况称为单变量回归,多于一个自变量情况的叫做多元回归

线性回归用矩阵表示举例

mark

那么怎么理解呢?我们来看几个例子

  • 期末成绩:0.7×考试成绩+0.3×平时成绩
  • 房子价格 = 0.02×中心区域的距离 + 0.04×城市一氧化氮浓度 + (-0.12×自住房平均房价) + 0.254×城镇犯罪率

上面两个例子,我们看到特征值与目标值之间建立了一个关系,这个关系可以理解为线性模型

线性回归的基本API

线性回归的api主要是在sklearn.linear_model下

基本的demo如下:

from sklearn.linear_model import LinearRegression
#创建数据集
x = [[80, 86],
[82, 80],
[85, 78],
[90, 90],
[86, 82],
[82, 90],
[78, 80],
[92, 94]]
y = [84.2, 80.6, 80.1, 90, 83.2, 87.6, 79.4, 93.4]
#创建线性回归模型
estimator = LinearRegression()
#模型训练
estimator.fit(x, y)

print("系数是 \n", estimator.coef_)
#预测值
y_pre = estimator.predict([[100, 60]])
print("预测的最终成绩 \n", y_pre)

运行结果为:

系数是 
[0.3 0.7]
预测的最终成绩
[72.]

这个demo虽然简单但是已经具备了基本的线性回归的所有条件

损失函数

但是使用线性回归的时候,我们难免遇到一个问题,这个回归系数,真的就是我们数据集对应的系数吗?

这个问题的答案,往往是否定的,在使用线性回归的过程中,我们预测出来的系数,往往是接近真实系数,但一般条件下并不是完全和真实系数相同的,这样就存在了损失这一过程

我们能做的就是在预测值出来后,去减小损失

而总损失函数的定义为

mark

  • yi为第i个训练样本的真实值
  • h(xi)为第i个训练样本特征值组合预测函数

这个函数又叫做最小二乘法

我们在这里知道了这个损失函数的公式,而线性回归中也有方法去优化这个总损失的值

优化算法

线性回归经常使用的两种优化算法

正规方程

mark

理解:X为特征值矩阵,y为目标值矩阵。直接求到最好的结果

缺点:当特征过多过复杂时,求解速度太慢并且得不到结果

这个方程的推导,其实是把损失函数转换为矩阵写法

mark

其中y是真实值矩阵,X是特征值矩阵,w是权重矩阵

对其求解关于w的最小值,起止y,X 均已知二次函数直接求导,导数为零的位置,即为最小值。

求导:

mark

注:式(1)到式(2)推导过程中, X是一个m行n列的矩阵,并不能保证其有逆矩阵,但是右乘XT把其变成一个方阵,保证其有逆矩阵。

式(5)到式(6)推导过程中,和上类似。

梯度下降
什么是梯度下降

梯度下降法的基本思想可以类比为一个下山的过程。

假设这样一个场景:一个人被困在山上,需要从山上下来(i.e. 找到山的最低点,也就是山谷)。但此时山上的浓雾很大,导致可视度很低。因此,下山的路径就无法确定,他必须利用自己周围的信息去找到下山的路径。这个时候,他就可以利用梯度下降算法来帮助自己下山。具体来说就是,以他当前的所处的位置为基准,寻找这个位置最陡峭的地方,然后朝着山的高度下降的地方走,(同理,如果我们的目标是上山,也就是爬到山顶,那么此时应该是朝着最陡峭的方向往上走)。然后每走一段距离,都反复采用同一个方法,最后就能成功的抵达山谷。

mark

梯度下降的基本过程就和下山的场景很类似。

首先,我们有一个可微分的函数。这个函数就代表着一座山。

我们的目标就是找到这个函数的最小值,也就是山底。

根据之前的场景假设,最快的下山的方式就是找到当前位置最陡峭的方向,然后沿着此方向向下走,对应到函数中,就是找到给定点的梯度 ,然后朝着梯度相反的方向,就能让函数值下降的最快!因为梯度的方向就是函数之变化最快的方向。 所以,我们重复利用这个方法,反复求取梯度,最后就能到达局部的最小值,这就类似于我们下山的过程。而求取梯度就确定了最陡峭的方向,也就是场景中测量方向的手段。

梯度的概念

梯度是微积分中一个很重要的概念

在单变量的函数中,梯度其实就是函数的微分,代表着函数在某个给定点的切线的斜率

在多变量函数中,梯度是一个向量,向量有方向,梯度的方向就指出了函数在给定点的上升最快的方向

这也就说明了为什么我们需要千方百计的求取梯度!我们需要到达山底,就需要在每一步观测到此时最陡峭的地方,梯度就恰巧告诉了我们这个方向。梯度的方向是函数在给定点上升最快的方向,那么梯度的反方向就是函数在给定点下降最快的方向,这正是我们所需要的。所以我们只要沿着梯度的反方向一直走,就能走到局部的最低点.

梯度下降举例

我们假设有一个单变量的函数 :J(θ) = θ2

函数的微分:J、(θ) = 2θ

初始化,起点为: θ0 = 1

学习率:α = 0.4

我们开始进行梯度下降的迭代计算过程:

mark

如图,经过四次的运算,也就是走了四步,基本就抵达了函数的最低点,也就是山底

mark

梯度下降

mark

1) α是什么含义?

α在梯度下降算法中被称作为学习率或者步长,意味着我们可以通过α来控制每一步走的距离,就是不要走太快,错过了最低点。同时也要保证不要走的太慢,导致太阳下山了,还没有走到山下。所以α的选择在梯度下降法中往往是很重要的,α不能太大也不能太小,太小的话,可能导致迟迟走不到最低点,太大的话,会导致错过最低点.

mark

  • 2) 为什么梯度要乘以一个负号

梯度前加一个负号,就意味着朝着梯度相反的方向前进!我们在前文提到,梯度的方向实际就是函数在此点上升最快的方向!而我们需要朝着下降最快的方向走,自然就是负的梯度的方向,所以此处需要加上负号

我们通过两个图更好理解梯度下降的过程:

mark

mark

所以有了梯度下降这样一个优化算法,回归就有了"自动学习"的能力

  • 梯度下降和正规方程的对比
梯度下降 正规方程
需要选择学习率 不需要
需要迭代求解 一次运算得出
特征数量较大可以使用 需要计算方程,时间复杂度高O(n3)
梯度下降法

常见的梯度下降算法有:

  • 全梯度下降算法(Full gradient descent),
  • 随机梯度下降算法(Stochastic gradient descent),
  • 随机平均梯度下降算法(Stochastic average gradient descent)
  • 小批量梯度下降算法(Mini-batch gradient descent)

1 全梯度下降算法(FG)

计算训练集所有样本误差,对其求和再取平均值作为目标函数。

权重向量沿其梯度相反的方向移动,从而使当前目标函数减少得最多。

因为在执行每次更新时,我们需要在整个数据集上计算所有的梯度,所以批梯度下降法的速度会很慢,同时,批梯度下降法无法处理超出内存容量限制的数据集。

批梯度下降法同样也不能在线更新模型,即在运行的过程中,不能增加新的样本。

其是在整个训练数据集上计算损失函数关于参数θ的梯度:

mark

2 随机梯度下降算法(SG)

由于FG每迭代更新一次权重都需要计算所有样本误差,而实际问题中经常有上亿的训练样本,故效率偏低,且容易陷入局部最优解,因此提出了随机梯度下降算法。

其每轮计算的目标函数不再是全体样本误差,而仅是单个样本误差,即每次只代入计算一个样本目标函数的梯度来更新权重,再取下一个样本重复此过程,直到损失函数值停止下降或损失函数值小于某个可以容忍的阈值。

此过程简单,高效,通常可以较好地避免更新迭代收敛到局部最优解。其迭代形式为

mark

每次只使用一个样本迭代,若遇上噪声则容易陷入局部最优解。

其中,x(i)表示一条训练样本的特征值,y(i)表示一条训练样本的标签值

但是由于,SG每次只使用一个样本迭代,若遇上噪声则容易陷入局部最优解。

3 小批量梯度下降算法(mini-bantch)

小批量梯度下降算法是FG和SG的折中方案,在一定程度上兼顾了以上两种方法的优点。

每次从训练样本集上随机抽取一个小样本集,在抽出来的小样本集上采用FG迭代更新权重。

被抽出的小样本集所含样本点的个数称为batch_size,通常设置为2的幂次方,更有利于GPU加速处理。

特别的,若batch_size=1,则变成了SG;若batch_size=n,则变成了FG.其迭代形式为

mark

4 随机平均梯度下降算法(SAG)

在SG方法中,虽然避开了运算成本大的问题,但对于大数据训练而言,SG效果常不尽如人意,因为每一轮梯度更新都完全与上一轮的数据和梯度无关。

随机平均梯度算法克服了这个问题,在内存中为每一个样本都维护一个旧的梯度,随机选择第i个样本来更新此样本的梯度,其他样本的梯度保持不变,然后求得所有梯度的平均值,进而更新了参数。

如此,每一轮更新仅需计算一个样本的梯度,计算成本等同于SG,但收敛速度快得多。

在一般情况下

(1) FG方法由于它每轮更新都要使用全体数据集,故花费的时间成本最多,内存存储最大。

(2)SAG在训练初期表现不佳,优化速度较慢。这是因为我们常将初始梯度设为0,而SAG每轮梯度更新都结合了上一轮梯度值。

(3)综合考虑迭代次数和运行时间,SG表现性能都很好,能在训练初期快速摆脱初始梯度值,快速将平均损失函数降到很低。但要注意,在使用SG方法时要慎重选择步长,否则容易错过最优解。

(4)mini-batch结合了SG的“胆大”和FG的“心细”,从6幅图像来看,它的表现也正好居于SG和FG二者之间。在目前的机器学习领域,mini-batch是使用最多的梯度下降算法,正是因为它避开了FG运算效率低成本大和SG收敛效果不稳定的缺点。

API扩展

1.,sklearn.linear_model.LinearRegression(fit_intercept=True)

  • 通过正规方程优化
  • fit_intercept:是否计算偏置
  • LinearRegression.coef_:回归系数
  • LinearRegression.intercept_:偏置

2.sklearn.linear_model.SGDRegressor(loss=“squared_loss”, fit_intercept=True, learning_rate =‘invscaling’, eta0=0.01)

  • SGDRegressor类实现了随机梯度下降学习,它支持不同的loss函数和正则化惩罚项来拟合线性回归模型。
  • loss:损失类型
    • loss=”squared_loss”: 普通最小二乘法
  • fit_intercept:是否计算偏置
  • learning_rate : string, optional
    • 学习率填充
    • ‘constant’: eta = eta0
    • ‘optimal’: eta = 1.0 / (alpha * (t + t0)) [default]
    • ‘invscaling’: eta = eta0 / pow(t, power_t)
      • power_t=0.25:存在父类当中
    • 对于一个常数值的学习率来说,可以使用learning_rate=’constant’ ,并使用eta0来指定学习率。
  • SGDRegressor.coef_:回归系数
  • SGDRegressor.intercept_:偏置

这些api我们使用波士顿房价预测案例来体现其作用

波士顿房价预测

数据集介绍

mark

mark

回归性能评估

均方误差(Mean Squared Error)MSE)评价机制:

mark

注:yi为预测值,¯y为真实值

其api如下:

  • sklearn.metrics.mean_squared_error(y_true, y_pred)
    • 均方误差回归损失
    • y_true:真实值
    • y_pred:预测值
    • return:浮点数结果
正则预测

使用正规方程的线性回归来预测波士顿房价

代码如下:

from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_boston
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split

# 加载数据集
data = load_boston()
# 数据分割
x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.2, random_state=22)
# 标准化数据
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)

estimator=LinearRegression()
estimator.fit(x_train,y_train)
y_pre=estimator.predict(x_test)

print("预测值 \n",y_pre)
print("系数 \n",estimator.coef_)
print("偏置 \n",estimator.intercept_)
print("准确率\n",estimator.score(x_test,y_test))
error=mean_squared_error(y_test,y_pre)
print("回归误差 \n",error)

运行结果:

预测值 
[27.79728567 30.90056436 20.70927059 31.59515005 18.71926707 18.46483447
20.7090385 18.01249201 18.18443754 32.26228416 20.45969144 27.30025768
15.04218041 19.25382799 36.18076812 18.45209512 7.73077544 17.33936848
29.40094704 23.32172471 18.43837789 33.31097321 28.38611788 17.43787678
34.25179785 26.06150404 34.65387545 26.07481562 19.13116067 12.66351087
30.00302966 14.70773445 36.82392563 9.08197058 15.06703028 16.68218611
7.99793409 19.41266159 39.15193917 27.42584071 24.24171273 16.93863931
38.03318373 6.63678428 21.51394405 24.41042009 18.86273557 19.87843319
15.71796503 26.48901546 8.09589057 26.90160249 29.19481155 16.86472843
8.47361081 34.87951213 32.41546229 20.50741461 16.27779646 20.32570308
22.82622646 23.45866662 19.01451735 37.50382701 23.61872796 19.43409925
12.98316226 6.99153964 40.99988893 20.87265869 16.74869905 20.79222071
39.90859398 20.20645238 36.15225857 26.80056368 19.20376894 19.60725424
24.04458577 20.45114082 30.47485108 19.09694834 22.55307626 30.77038574
26.2119968 20.48073193 28.53910224 20.16485961 25.94461242 19.13440772
24.98211795 22.84782867 19.18212763 18.88071352 14.49151931 17.78587168
24.00230395 16.01304321 20.51185516 26.1867442 20.64288449 17.35297955]
系数
[-0.73088157 1.13214851 -0.14177415 0.86273811 -2.02555721 2.72118285
-0.1604136 -3.36678479 2.5618082 -1.68047903 -1.67613468 0.91214657
-3.79458347]
偏置
22.57970297029704
准确率
0.7636568232153278
回归误差
20.955979753963458

这里我们主要观察回归误差这个值,在模型训练过程中,这个值越小越好

梯度预测

代码如下:

from sklearn.model_selection import train_test_split
from sklearn.linear_model import SGDRegressor
from sklearn.datasets import load_boston
from sklearn.metrics import mean_squared_error
from sklearn.preprocessing import StandardScaler

data=load_boston()

x_train,x_test,y_train,y_test=train_test_split(data.data,data.target,random_state=22,test_size=0.2)

transfer=StandardScaler()
x_train=transfer.fit_transform(x_train)
x_test=transfer.fit_transform(x_test)

estimator=SGDRegressor(max_iter=1000,learning_rate="constant",eta0=0.01)
estimator.fit(x_train,y_train)
y_pre=estimator.predict(x_test)
score=estimator.score(x_test,y_test)
print("预测值\n",y_pre)
print("系数\n",estimator.coef_)
print("偏置\n",estimator.intercept_)
print("准确率\n",score)
error=mean_squared_error(y_test,y_pre)
print("回归误差\n",error)

运行结果:

预测值
[27.36719257 31.33694272 20.39652597 31.2642945 18.27631495 17.35896989
20.42038115 18.00804627 18.18083138 32.3539295 20.32798339 26.60529586
13.84582627 18.14088032 36.32691155 18.20789627 6.85183152 16.82434635
29.90408999 23.53042762 17.19360224 34.13573484 27.96540055 16.25344074
34.56965042 26.41830822 36.17049277 27.25080413 17.71914452 12.96564036
30.71831284 13.48666899 38.98846777 6.31462601 14.44508939 15.27621744
6.16551956 18.46036504 39.89694285 28.06541447 24.33368188 15.43095059
36.5669055 4.85383286 20.68791211 24.55915422 17.96164714 18.84374366
14.77490125 25.27813636 6.54982031 27.4838803 28.92770806 15.33312427
5.75934978 35.78037441 33.69606205 21.10455912 15.99242483 20.96558379
22.80790238 23.4584577 18.8152664 38.68353765 24.27666609 18.12097137
10.69732721 5.28906073 40.73744281 20.98723697 14.63014713 21.01691731
40.89724654 20.79134222 37.09801298 26.87709846 20.25837342 18.23448267
24.62156463 21.25203017 30.91116372 19.36856758 21.9269753 32.83897751
26.15869108 19.51621705 28.88643169 20.35589199 25.63005576 18.17727344
26.65964896 22.14369478 17.82324386 17.22939964 12.076978 16.67909979
24.18916375 13.95613481 19.33196469 25.73845399 19.2471648 15.96818495]
系数
[-0.79344666 1.3223361 -0.31878148 0.71698376 -2.11150648 2.72257253
-0.21677836 -3.25599272 2.47259084 -1.69316215 -1.98929845 1.15879732
-3.99708267]
偏置
[22.22781349]
准确率
0.7863188066133949
回归误差
18.94659631529018

在使用梯度下降时,我们可以通过调整学习率来观察模型的变化

在上文的梯度下降api中,写到了SGDRegressor这个api,而api的参数可以有很多可以调整的值,我们可以多次实验得到我们认为最好的结果

这里使用的

learning_rate=“constant”,eta0=0.01这个学习率,我们可以自己调整其参数获得自己能接受的模型结果

本文就到这里结束了,下篇文章写欠拟合和过拟合