机器学习(三)梯度下降法
综述
这一篇博文我们主要来讨论更一般的让模型参数趋于最优参数的方法。这就类似于求解高中学过的求函数最大值的问题,在数学上,这类问题被称为优化问题,但与高中接触的最大值问题不同的是,机器学习的优化问题往往是求不出解析解的,所以我们一般需要采用一些通用的迭代优化算法来不断逼近这个最优解,梯度下降算法(Gradient Descent Algorithm)和由它演化而来的随机梯度下降算法(Stochastic Gradient Descent Algorithm)就是最常用的两种算法。
梯度下降法
首先让我们来看一张图。
想象有一个小球正在上图所示的这个样子的容器壁上,当我们松开手,球一定会沿着最“陡峭”的方向滚下来,如果滚过了最低点,它又会折返,如此循环往复,直到球滚到最低点为止。
对于最小化机器学习的损失函数而言,其实也是类似的一个过程,对于我们以前讲过的线性回归而言,它的损失函数图像其实就是上图的样子。我们要让损失函数的值最小,我们可以循环往复执行下面的过程:
- 首先随机生成一组参数。(随机把小球摆在容器中的一个位置上)
- 找到下降速度最快的方向,“向前迈出一步”(参数做出改变)
- 如果在进行一次操作后,损失函数的值没有变化或者变化非常小,我们可以认为它近似已经达到了最低点,退出循环,否则继续第二步。
对于绝大多数可导的损失函数,我们基本都可以使用上述流程来求解它的最优参数。但是也有了两个问题:
- 我们如何确定我们要向哪个方向下降?
- 我们需要“迈出一步”,这一步需要迈多少?
- 我们如何判断自己是否已经到达最低点了呢?
这两个问题,就对应了梯度下降法中最重要的两个概念和参数——梯度和学习率。
梯度和学习率
什么是梯度(gradient)?我想学习过高等数学的同学应该都不陌生,对于函数
f
(
θ
1
,
θ
2
.
.
.
θ
n
)
f(\theta_1,\theta_2...\theta_n)
f(θ1,θ2...θn),它的梯度就是
g
r
a
d
f
=
(
∂
f
∂
θ
1
,
∂
f
∂
θ
2
.
.
.
∂
f
∂
θ
n
)
gradf=(\frac{\partial f}{\partial\theta_1},\frac{\partial f}{\partial\theta_2}...\frac{\partial f}{\partial\theta_n})
gradf=(∂θ1∂f,∂θ2∂f...∂θn∂f)
接下来我们来从数学上推导为什么要使用梯度,为了便于说明,我们以含有两个参数的损失函数为例,假设我们有损失函数
L
(
a
,
b
)
L(a,b)
L(a,b),按照上面的步骤,我们需要先初始化一组参数,设为
(
a
0
,
b
0
)
(a_0,b_0)
(a0,b0),我们做出一步下降得到
L
(
a
1
,
b
1
)
L(a_1,b_1)
L(a1,b1),根据泰勒级数,只考虑一阶导数可以得到:
Δ
L
=
L
(
a
1
,
b
1
)
−
L
(
a
0
,
b
0
)
≈
∂
L
∂
a
(
a
1
−
a
0
)
+
∂
L
∂
b
(
b
1
−
b
0
)
\Delta L=L(a_1,b_1)-L(a_0,b_0)\approx\frac{\partial L}{\partial a}(a_1-a_0)+\frac{\partial L}{\partial b}(b_1-b_0)
ΔL=L(a1,b1)−L(a0,b0)≈∂a∂L(a1−a0)+∂b∂L(b1−b0)
令
Δ
a
=
(
a
1
−
a
0
)
,
Δ
b
=
(
b
1
−
b
0
)
,
\Delta a=(a_1-a_0),\Delta b=(b_1-b_0),
Δa=(a1−a0),Δb=(b1−b0),再令:
(
Δ
a
,
Δ
b
)
=
−
η
(
∂
L
∂
a
,
∂
L
∂
b
)
(
η
是
参
数
)
(\Delta a,\Delta b)=-\eta(\frac{\partial L}{\partial a},\frac{\partial L}{\partial b})(\eta是参数)
(Δa,Δb)=−η(∂a∂L,∂b∂L)(η是参数)
这里我们将参数的变化量和梯度挂上钩,就确定了
Δ
a
和
Δ
b
\Delta a和\Delta b
Δa和Δb作为参数的变化量,我们来看看效果如何,将这个式子代入
Δ
L
\Delta L
ΔL得到:
Δ
L
=
−
η
(
(
∂
L
∂
a
)
2
+
[
∂
L
∂
b
)
2
]
≤
0
\Delta L=-\eta((\frac{\partial L}{\partial a})^2+[\frac{\partial L}{\partial b})^2] \leq 0
ΔL=−η((∂a∂L)2+[∂b∂L)2]≤0
我们可以看到,损失函数
L
(
a
,
b
)
L(a,b)
L(a,b)的变化量始终是小于0的,也就是说,不管情况如何,我们使用这种方法进行一次参数变换,损失函数必然减少;不断地进行这个过程,损失函数最终一定会趋向于最小值。分析到这里,我们可以得到每一次迭代参数变换的递推公式:
a
n
+
1
=
a
n
−
η
∂
L
∂
a
a_{n+1}=a_n-\eta\frac{\partial L}{\partial a}
an+1=an−η∂a∂L
b
n
+
1
=
b
n
−
η
∂
L
∂
b
b_ {n+1}=b_n-\eta\frac{\partial L}{\partial b}
bn+1=bn−η∂b∂L
上面两个公式就是梯度下降法的迭代核心公式,也可以进一步推广到
n
n
n个参数的情况。
看到这里,你可能会好奇这个 η \eta η是什么,其实我们不难发现,这个 η \eta η其实就对应着我们“步伐”的长度,在学术上被称为学习率(learning rate),这也是一个超参数,很大程度上需要我们通过经验和实际情况来进行选择,我们可以定性的描述这个超参数:
- 如果 η \eta η取的比较小,我们往往能得到更加精确的最优解,但相应的,我们得到最优解就需要更多次的迭代,从而导致训练速度的减慢。
- 如果 η \eta η取的比较大,相反的,我们得到最优解不那么精确但可以加快训练速度。
最后一个问题,我们如何控制梯度下降法的终止呢?工程上,我们有两种解决方案,一种是我们引入一个超参数最大迭代次数(max iterations),当我们达到这个迭代次数时就停止;另一种方法是我们定义一个可容忍的误差,当一次迭代后损失函数下降的幅度小于这个可容忍的误差时,我们就停止迭代。
另外,对于泰勒级数,我们一样也可以采用二阶导数(共轭梯度法)、三阶导数等高阶形式,但由于对损失函数要求更高(需要存在高阶导数),而且收敛速度更慢,所以我们一般不会使用这些方法。
梯度下降法的局限
首先很明确的一点是,梯度下降法对于损失函数有一定的要求:它必须要可导。对于像前面提到过的Lasso回归,我们就无法使用梯度下降法对它进行处理。
其次,当损失函数存在局部最低点时,我们有可能收敛不到最优解,举个例子,假设我们有这样的一个损失函数:
我们对它随机确定一个起点,然后进行梯度下降,最终下降的路径可能是这样的:
我们最终确实下降到了最低点,但如果我们选取不同的起点时,我们也可能得到完全不一样的情况:
我们下降到了一个完全不一样的点,在这样的点上虽然梯度为0,但是它却不是损失函数最低的点,和函数极值类似。我们把这样的点称为局部最优解,它在一小段范围内的确是最优的,但是却不是我们需要的全局最优解。
对于这个问题,我们没有特别有效的方法解决这个问题,我们只能采用生成多组初始点的方式,每一组都进行梯度下降,然后选出损失函数最小的一组作为最终的参数。
随机梯度下降法
随机梯度下降法是梯度下降法的一个变种。可能有的书籍认为随机梯度下降法是对梯度下降法的一种优化,但笔者认为两种方法各有各的长处,我们应该辩证地看待这个问题。
首先我们来谈谈我们为什么需要随机梯度下降法,我们先回顾以下前面的内容,假定对于一组数据我们的假设函数为
H
(
X
;
θ
)
H(X;\theta)
H(X;θ),我们可以得到最小二乘形式的损失函数为:
L
(
θ
)
=
∑
(
Y
i
−
H
(
X
;
θ
)
)
2
L(\theta)=\sum{(Y_i-H(X;\theta))}^2
L(θ)=∑(Yi−H(X;θ))2
可以看到,我们计算损失函数时,是采用了一种求和的方式。在梯度下降法中,我们也需要每次都对每一个参数求偏导数。当我们的数据量很大时,梯度下降法的计算速度就会变得非常慢。随机梯度下降法就是来解决这个问题的。
实际上,随机梯度下降法的思路很简单:从数据集中随机选取一些数据点,然后利用这些点的梯度平均值来估算损失函数的梯度。
这在数学上其实就是一种抽样的方法,从统计的角度来说,用所有数据点求平均值,与选取部分点求平均值得到的效果其实是差不多的,它们本身都是总体的样本,都以真实的梯度为数学期望,只是前者的方差更小、置信区间更小罢了。
我们将算法的细节写得更精确一些,我们需要引入一个超参数——批量大小(batch size),对应的其实就是抽取数据点的样本容量,我们把它记作
m
m
m。从中抽取
m
m
m个数据点,记作
S
1
,
S
2
.
.
.
S
m
S_1,S_2...S_m
S1,S2...Sm。用这些数据的梯度平均值来代替损失函数的梯度:
g
r
a
d
L
≈
1
m
∑
k
=
1
m
g
r
a
d
L
S
k
gradL\approx \frac{1}{m}\sum^m_{k=1}{gradL_{S_k}}
gradL≈m1k=1∑mgradLSk
我们同样可以得到新的迭代递推公式:
a
n
+
1
=
a
n
−
η
m
∑
k
=
1
m
∂
L
S
k
∂
a
a_{n+1}=a_n-\frac{\eta}{m}\sum^m_{k=1}{\frac{\partial L_{S_k}}{\partial a}}
an+1=an−mηk=1∑m∂a∂LSk
在随机梯度下降法中,如果所有数据都被使用了一轮,我们称为模型训练了一轮。类似梯度下降法中的最大迭代次数,我们引入另一个超参数——训练轮次(epoch),这个超参数用来控制随机梯度下降法的循环迭代次数。
与梯度下降法相比,随机梯度下降法的速度更快。而且由于我们本身就是随机抽样,在一定程度上可以减小损失函数收敛到局部最低点的可能性。(但并不能完全保证收敛到全局最低点,解决方法和梯度下降法相同)
小结
本文主要介绍了工程上求解最优解的两种方法:梯度下降法和随机梯度下降法。这两种算法的应用极广,在人工神经网络、深度学习、分布式机器学习等领域都常常能见到它们的身影。
当然,求解最优化问题的算法远不止这么几种,后续我会继续更新这方面的内容。下一篇博文中,我们将会介绍一种非常经典的分类算法——逻辑回归(Logistic Regression)。