这篇文章介绍了三种梯度下降方法的原理与优缺点,详细地讲解了Momentum、RMSprop和Adam优化算法,给出了使用建议。
1.Batch Gradient Descent,全部样本梯度下降一次,训练样本很大时,单次迭代需要时间太长。
2.Stochastic Gradient Descent,单个样本梯度下降一次,没有了向量化加速,效率比Batch Gradient Descent低,到达loss最低区域后还可能会跳出来,当然这也可以使它从局部最小值区域跳出来,可以使用学习率衰减来缓解这个问题。
3.Mini-batch Gradient Descent,部分样本梯度下降一次,上两个方法的折中,它可能不会收敛也可能不会在很小的范围内波动(同样可以用学习率衰减的方法来缓解这个问题)。
下面是loss的梯度图,三条线是三种梯度下降方法每下降一次的路线,蓝色是Batch Gradient Descent,紫色是Stochastic Gradient Descent,绿色是Mini-batch Gradient Descent。
进阶理解:
相对于GD,SGD能更有效的利用信息,特别是信息比较冗余的时候。举个例子,比如所有样本都需要向一个方向优化,GD优化一次需要对整个样本集迭代一次,而SGD只对一个样本优化就可以达到同样的效果。SGD相对于GD的另外一个优点是可以跳出局部最小值区域。
而mini-batch GD综合了两者的优点,既有了GD的向量化加速,还能像SGD更有效利用样本信息、可以跳出局部最小值区域的优点。另外,使用mini-batch,你还会发现不需要等待整个训练集被处理完就可以开始进行后续工作。
下面总结一下mini-batch的优点:
1.有向量化加速,加快了训练速度。
2.能有效利用样本信息,特别是信息比较冗余的时候。
3.有随机性,可以跳出局部最小值区域。
4.不需要等待整个训练集被处理完就可以开始进行后续工作。
下面是mini-batch的伪代码,中括号上标代表层数:
将 样 本 分 为 n 个 m i n i b a t c h f o r t = 1 , . . . n : 前 向 传 播 : { a [ 1 ] = g ( W [ 1 ] X t + b [ 1 ] ) a [ 2 ] = g ( W [ 2 ] X t + b [ 2 ] ) . . . a [ l ] = g ( W [ l ] X t + b [ l ] ) 计 算 l o s s : L 总 = 1 n ∑ i = 1 l L ( y ^ [ i ] , y [ i ] ) 反 向 传 播 : { 计 算 各 层 梯 度 d w 和 d b W [ l ] = W [ l ] − α d W [ l ] b [ l ] = b [ l ] − α d b [ l ] \begin{aligned} 将样本分为n个mini \ batch\\ for \ \ \ t=1,...n:\\ &前向传播:\\ &\begin{cases} a^{[1]} = g(W^{[1]}X_t+b^{[1]})\\ a^{[2]} = g(W^{[2]}X_t+b^{[2]})\\ \ \ \ \ \ \ \ \ \ \ \ \ ...\\ a^{[l]} = g(W^{[l]}X_t+b^{[l]})\\ \end{cases}\\ &计算loss: L_总 = \frac{1}{n} \sum^l_{i=1}L(\hat{y}^{[i]},y^{[i]}) \\ &反向传播:\\ &\begin{cases} 计算各层梯度 dw和db \\ W^{[l]}=W^{[l]}-\alpha dW^{[l]} \\ b^{[l]}=b^{[l]}-\alpha db^{[l]} \\ \end{cases}\\ \end{aligned} 将样本分为n个mini batchfor t=1,...n:前向传播:⎩⎪⎪⎪⎨⎪⎪⎪⎧a[1]=g(W[1]Xt+b[1])a[2]=g(W[2]Xt+b[2]) ...a[l]=g(W[l]Xt+b[l])计算loss:L总=n1i=1∑lL(y^[i],y[i])反向传播:⎩⎪⎨⎪⎧计算各层梯度dw和dbW[l]=W[l]−αdW[l]b[l]=b[l]−αdb[l]
首先,如果训练集较小,直接使用Batch Gradient Descent梯度下降法,样本集较小就没必要使用mini-batch梯度下降法,这里的少是说小于差不多2000个样本,这样比较适合使用Batch Gradient Descent梯度下降法。
样本数目较大的话,一般的mini-batch大小为64到512,考虑到电脑内存设置和使用的方式,如果mini-batch大小是2的次方,代码会运行地快一些。64到512的mini-batch比较常见。
下面讲几种常见的梯度下降优化算法:
Gradient descent with Momentum,这个梯度下降方法,基本的想法就是计算梯度的指数加权平均数,并利用它更新权重。直观来讲,就是给普通的梯度下降加了个“惯性”,就像开车,你不能开着开着想往右拐就瞬间拐到右边,它有个向前再往右的过程,换言之,你想改变行驶方向,是需要从之前的行驶方向慢慢改变的,并不能瞬间改变。同理,Momentum梯度下降也一样,比如这次迭代算出来你需要向a方向优化,但你并不能直接将你的方向改成a,需要综合考虑之前的方向。
下图左边是普通随机梯度下降,右边是Momentum随机梯度下降,可以看出后者加快了优化速度,抑制了震荡。
因为mini-batch相比标准的梯度下降来说,更新参数更快,所以收敛过程会有浮动(loss下降曲线),使用动量梯度下降法可以减小该浮动,还能加速训练。
看下mini-batch GD with Momentum的公式:
初 始 化 每 层 的 v d W 、 v d b , 形 状 和 d W 、 d b 一 致 , 元 素 全 为 0 将 样 本 分 为 n 个 m i n i b a t c h f o r t = 1 , . . . n : 前 向 传 播 : { a [ 1 ] = g ( W [ 1 ] X t + b [ 1 ] ) a [ 2 ] = g ( W [ 2 ] X t + b [ 2 ] ) . . . a [ l ] = g ( W [ l ] X t + b [ l ] ) 计 算 l o s s : L 总 = 1 n ∑ i = 1 l L ( y ^ [ i ] , y [ i ] ) 反 向 传 播 : { 计 算 各 层 梯 度 d w 和 d b v d W [ l ] = β v d W [ l − 1 ] + ( 1 − β ) d W [ l ] v d b [ l ] = β v d b [ l − 1 ] + ( 1 − β ) d b [ l ] W [ l ] = W [ l ] − α v d W [ l ] W [ l ] = b [ l ] − α v d b [ l ] \begin{aligned} {\color{Red}{初始化每层的v_{dW}、v_{db},}}&{\color{Red}{形状和dW、db一致,元素全为0}}\\ 将样本分为n个mini \ batch\\ for \ \ \ t=1,...n:\\ &前向传播:\\ &\begin{cases} a^{[1]} = g(W^{[1]}X_t+b^{[1]})\\ a^{[2]} = g(W^{[2]}X_t+b^{[2]})\\ \ \ \ \ \ \ \ \ \ \ \ \ ...\\ a^{[l]} = g(W^{[l]}X_t+b^{[l]})\\ \end{cases}\\ &计算loss: L_总 = \frac{1}{n} \sum^l_{i=1}L(\hat{y}^{[i]},y^{[i]}) \\ &反向传播:\\ &\begin{cases} 计算各层梯度 dw和db \\ {\color{Red}{v_{dW^{[l]}} = \beta v_{dW^{[l-1]}} + (1 - \beta) dW^{[l]}}} \\ \\ {\color{Red}{v_{db^{[l]}} = \beta v_{db^{[l-1]}} + (1 - \beta) db^{[l]}}} \\ \\ W^{[l]} = W^{[l]} - \alpha {\color{Red}{v_{dW^{[l]}}}} \\ \\ W^{[l]} = b^{[l]} - \alpha {\color{Red}{v_{db^{[l]}}}} \\ \end{cases}\\ \end{aligned} 初始化每层的vdW、vdb,将样本分为n个mini batchfor t=1,...n:形状和dW、db一致,元素全为0前向传播:⎩⎪⎪⎪⎨⎪⎪⎪⎧a[1]=g(W[1]Xt+b[1])a[2]=g(W[2]Xt+b[2]) ...a[l]=g(W[l]Xt+b[l])计算loss:L总=n1i=1∑lL(y^[i],y[i])反向传播:⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧计算各层梯度dw和dbvdW[l]=βvdW[l−1]+(1−β)dW[l]vdb[l]=βvdb[l−1]+(1−β)db[l]W[l]=W[l]−αvdW[l]W[l]=b[l]−αvdb[l]
β \beta β越大,收敛过程越平滑,一般取值为0.8~0.999,0.9会是一个不错的选择。
RMSprop的算法,全称是root mean square prop算法,它也可以加速收敛,我们来看看它是如何运作的。
初 始 化 每 层 的 s d W 、 s d b , 形 状 和 d W 、 d b 一 致 , 元 素 全 为 0 将 样 本 分 为 n 个 m i n i b a t c h f o r t = 1 , . . . , n : 前 向 传 播 : { a [ 1 ] = g ( W [ 1 ] X t + b [ 1 ] ) a [ 2 ] = g ( W [ 2 ] X t + b [ 2 ] ) . . . a [ l ] = g ( W [ l ] X t + b [ l ] ) 计 算 总 l o s s : L 总 = 1 n ∑ i = 1 l L ( y ^ [ i ] , y [ i ] ) 反 向 传 播 : { 计 算 各 层 梯 度 d w 和 d b s d W [ l ] = β s d W [ l − 1 ] + ( 1 − β ) ( d W [ l ] ) 2 s d b [ l ] = β s d b [ l − 1 ] + ( 1 − β ) ( d b [ l ] ) 2 W [ l ] = W [ l ] − α s d W + ε d W [ l ] b [ l ] = b [ l ] − α s d b + ε d b [ l ] \begin{aligned} {\color{Red}{初始化每层的s_{dW}、s_{db},}}&{\color{Red}{形状和dW、db一致,元素全为0}}\\ 将样本分为n个mini \ batch\\ for \ \ \ t=1,...,n:\\ &前向传播:\\ &\begin{cases} a^{[1]} = g(W^{[1]}X_t+b^{[1]})\\ a^{[2]} = g(W^{[2]}X_t+b^{[2]})\\ \ \ \ \ \ \ \ \ \ \ \ \ ...\\ a^{[l]} = g(W^{[l]}X_t+b^{[l]})\\ \end{cases}\\ &计算总loss: L_总 = \frac{1}{n} \sum^l_{i=1}L(\hat{y}^{[i]},y^{[i]}) \\ &反向传播:\\ &\begin{cases} 计算各层梯度 dw和db \\ {\color{Red}{s_{dW^{[l]}} = \beta s_{dW^{[l-1]}} + (1 - \beta) (dW^{[l]})^2}} \\ \\ {\color{Red}{s_{db^{[l]}} = \beta s_{db^{[l-1]}} + (1 - \beta) (db^{[l]})^2}} \\ \\ W^{[l]} = W^{[l]} - {\color{Red}{\frac{\alpha}{\sqrt{s_{dW} +\varepsilon}}}}dW^{[l]} \\ \\ b^{[l]} = b^{[l]} - {\color{Red}{\frac{\alpha}{\sqrt{s_{db} +\varepsilon}}}}db^{[l]} \\ \end{cases}\\ \end{aligned} 初始化每层的sdW、sdb,将样本分为n个mini batchfor t=1,...,n:形状和dW、db一致,元素全为0前向传播:⎩⎪⎪⎪⎨⎪⎪⎪⎧a[1]=g(W[1]Xt+b[1])a[2]=g(W[2]Xt+b[2]) ...a[l]=g(W[l]Xt+b[l])计算总loss:L总=n1i=1∑lL(y^[i],y[i])反向传播:⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧计算各层梯度dw和dbsdW[l]=βsdW[l−1]+(1−β)(dW[l])2sdb[l]=βsdb[l−1]+(1−β)(db[l])2W[l]=W[l]−sdW+εαdW[l]b[l]=b[l]−sdb+εαdb[l]
ε \varepsilon ε是一个很小的数,使后两个式子无论如何都不会除以一个接近于零的数,一般 ε = 1 0 − 8 \varepsilon = 10^{-8} ε=10−8
原理:参数更新时 α s d W + ε {\color{Red}{\frac{\alpha}{\sqrt{s_{dW} +\varepsilon}}}} sdW+εα 的作用是使梯度大的参数不要更新地太猛。因为梯度 d W dW dW越大, s d W s_{dW} sdW就越大,而 α s d W + ε {\color{Red}{\frac{\alpha}{\sqrt{s_{dW} +\varepsilon}}}} sdW+εα就越小,参数更新的幅度就越小。至于为什么使用平方指数加权平均,可能是因为想要先平方再开方来取绝对值?有懂的大佬请不吝赐教。
总而言之,RMSprop使得梯度大的参数更新幅度不那么大,很大程度上缓解了梯度下降震荡的问题,如下图所示,蓝线代表普通梯度下降,绿线代表RMSprop。
为何不把Momentum和RMSprop结合在一起用呢?那就有了Adam。
Adam 优化算法(Adam optimization algorithm),基本上就是将Momentum和RMSprop结合在一起,那么来看看如何使用Adam算法。
初 始 化 每 层 的 v d W 、 v d b 、 s d W 、 s d b , 形 状 和 d W 、 d b 一 致 , 元 素 全 为 0 将 样 本 分 为 n 个 m i n i b a t c h f o r t = 1 , . . . , n : 前 向 传 播 : { a [ 1 ] = g ( W [ 1 ] X t + b [ 1 ] ) a [ 2 ] = g ( W [ 2 ] X t + b [ 2 ] ) . . . a [ l ] = g ( W [ l ] X t + b [ l ] ) 计 算 总 l o s s : L 总 = 1 n ∑ i = 1 l L ( y ^ [ i ] , y [ i ] ) 反 向 传 播 : { 计 算 各 层 梯 度 d w ( d b 同 理 ) v ^ d W [ l ] = β 1 v ^ d W [ l − 1 ] + ( 1 − β 1 ) d W [ l ] s ^ d W [ l ] = β 2 s ^ d W [ l − 1 ] + ( 1 − β 2 ) ( d W [ l ] ) 2 v d W [ l ] = v ^ d W [ l ] 1 − ( β 1 ) t s d W [ l ] = s ^ d W [ l ] 1 − ( β 2 ) t W [ l ] = W [ l ] − α v d W [ l ] s d W [ l ] + ε \begin{aligned} {\color{Red}{初始化每层的v_{dW}、v_{db}、s_{dW}、s_{db},}}&{\color{Red}{形状和dW、db一致,元素全为0}}\\ 将样本分为n个mini \ batch\\ for \ \ \ t=1,...,n:\\ &前向传播:\\ &\begin{cases} a^{[1]} = g(W^{[1]}X_t+b^{[1]})\\ a^{[2]} = g(W^{[2]}X_t+b^{[2]})\\ \ \ \ \ \ \ \ \ \ \ \ \ ...\\ a^{[l]} = g(W^{[l]}X_t+b^{[l]})\\ \end{cases}\\ &计算总loss: L_总 = \frac{1}{n} \sum^l_{i=1}L(\hat{y}^{[i]},y^{[i]}) \\ &反向传播:\\ &\begin{cases} 计算各层梯度 dw (db同理) \\ {\color{Red}{\hat{v}_{dW^{[l]}} = \beta_1 \hat{v}_{dW^{[l-1]}} + (1 - \beta_1) dW^{[l]}}} \\ \\ {\color{Red}{\hat{s}_{dW^{[l]}} = \beta_2 \hat{s}_{dW^{[l-1]}} + (1 - \beta_2) (dW^{[l]})^2}} \\ \\ {\color{Red}{v_{dW^{[l]}} = \frac{\hat{v}_{dW^{[l]}}}{1 - (\beta_1)^t}}} \\ \\ {\color{Red}{s_{dW^{[l]}} = \frac{\hat{s}_{dW^{[l]}}}{1 - (\beta_2)^t}}} \\ \\ W^{[l]} = W^{[l]} - \alpha {\color{Red}{\frac{v_{dW^{[l]}}}{\sqrt{s_{dW^{[l]}}} + \varepsilon}}} \\ \end{cases}\\ \end{aligned} 初始化每层的vdW、vdb、sdW、sdb,将样本分为n个mini batchfor t=1,...,n:形状和dW、db一致,元素全为0前向传播:⎩⎪⎪⎪⎨⎪⎪⎪⎧a[1]=g(W[1]Xt+b[1])a[2]=g(W[2]Xt+b[2]) ...a[l]=g(W[l]Xt+b[l])计算总loss:L总=n1i=1∑lL(y^[i],y[i])反向传播:⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧计算各层梯度dw(db同理)v^dW[l]=β1v^dW[l−1]+(1−β1)dW[l]s^dW[l]=β2s^dW[l−1]+(1−β2)(dW[l])2vdW[l]=1−(β1)tv^dW[l]sdW[l]=1−(β2)ts^dW[l]W[l]=W[l]−αsdW[l]+εvdW[l]
看一下反向传播中红色公式,前两个式子分别是Momentum和RMSprop。
至于第三和第四个式子,是为了使各个梯度的权值之和为1。以Momentum的式子为例,设定 β 1 = 0.9 \beta_1=0.9 β1=0.9:
t=1和t=2时:
v ^ d W [ 1 ] = 0.1 d W [ 1 ] v d W [ 1 ] = 0.1 d W [ 1 ] 1 − 0. 9 1 = d W [ 1 ] v ^ d W [ 2 ] = 0.09 d W [ 1 ] + 0.1 d W [ 2 ] v d W [ 2 ] = 0.09 d W [ 1 ] + 0.1 d W [ 2 ] 1 − 0. 9 2 = 0.47 d W [ 1 ] + 0.53 d W [ 2 ] \begin{aligned} \hat{v}_{dW^{[1]}} &= 0.1dW^{[1]}\\ v_{dW^{[1]}} &= \frac{0.1dW^{[1]}}{1-0.9^1}= {\color{Red}{dW^{[1]}}} \\ \hat{v}_{dW^{[2]}} &= 0.09dW^{[1]}+0.1dW^{[2]}\\ v_{dW^{[2]}} &= \frac{0.09dW^{[1]}+0.1dW^{[2]}}{1-0.9^2} = {\color{Red}{0.47dW^{[1]}+0.53dW^{[2]}}} \\ \end{aligned} v^dW[1]vdW[1]v^dW[2]vdW[2]=0.1dW[1]=1−0.910.1dW[1]=dW[1]=0.09dW[1]+0.1dW[2]=1−0.920.09dW[1]+0.1dW[2]=0.47dW[1]+0.53dW[2]
可以看到每一步中所有梯度的权值和都会变成1。
梯度下降除非样本很少,一般来说都用mini-batch了,梯度下降的优化算法我推荐Adam,不需要花费太多时间来选择优化算法,效果都差不多,不如花时间去优化模型里别的超参。
下面贴了两张比较各个优化算法的动图,很直观。动图来自这篇博客:An overview of gradient descent optimization algorithms
[1] Ruder (2017) An overview of gradient descent optimization algorithms
[2] Bottou et.al(2018) Optimization Methods for Large-Scale Machine Learning
[3] D. Lee et.al (2016) Gradient Descent Only Converges to Minimizers
[4] http://zh.gluon.ai/chapter_optimization/adam.html