神经网络优化算法:BGD&SGD、Momentum、Adam ...
BGD&SGD名词解释
[*]BGD:最原始的梯度下降算法,为了计算在整个训练集的loss上的梯度,需要使用训练集全部数据
[*]SGD(随机梯度下降):只使用一个mini batch的数据来计算,相当于用minibatch的loss上的梯度去近似计算整个训练集的loss梯度
优化效率
[*]BGD:由于DL的数据集都挺大,每计算一次就要遍历整个数据集,计算量太大了,不现实
[*]SGD:随机选择mini-batch来近似计算梯度,每次计算只需遍历很少的数据,计算量小得多
SGD优点
BGD容易陷入奇点,而SGD则不容易。整个训练集的loss上存在很多奇点,因此BGD很有可能呆在某个奇点就不动了,无法到达全局最小或者较优的全局最小,SGD则可以一定程度上避免这种情况,原因如下:
[*]从引入随机性角度来看,SGD中是近似计算全局梯度的,相当于加入了随机性。即便走到了全局的某个奇点,由于随机性,梯度也不会变为0,容易跳出来
[*]全局数据和mini-batch数据的形状不同,奇点分布也不同,且每次迭代都使用不同的mini-batch,就算陷入了当前mini-batch的奇点,也可以很容易地在下个mini-batch跳出来。
SGD缺点
在batch取得比较小的情况下,SGD的优化路径比较震荡。BGD每次更新的方向是全局loss在当前点的最速下降方向,SGD则是mini-batch上loss的负梯度方向,如果随机采样的数据分布与全局差距较大,则可能会出现上升的操作,因此会有震荡的现象。为了减缓震荡,一个方法是增大batch size,这样会减小mini-batch数据的variance,但要选择合适的大小,否则一味增大size,就会退化成BGD了。
SGD在一定程度上虽然可以避免像BGD一样,陷入局部最小和鞍点,但是存在容易震荡、收敛速度慢等缺点,比如容易在最优点附近徘徊;此外,对学习率的挑选要求较高,如果选择一个较小的学习率,会导致收敛过慢,如果选择一个较大的学习率,则容易跳过最优点。
因此下面介绍几个对SGD进行改进的优化方法。
Momentum
用法
首先计算动量(每一步负梯度的移动指数平均值),然后直接用动量去更新参数。使用移动指数平均而不是其他平均方法,是因为更新参数的时候,希望离当前步越近的梯度的权重越高,越久的梯度的权重越低。
在随机梯度的学习算法中,每一步的步幅都是固定的,而在动量学习算法中,每一步走多远不仅依赖于本次的梯度的大小还取决于过去的速度。速度v是累积各轮训练参的梯度,其中β越大,依赖以前的梯度越大。假如每轮训练的梯度方向都是相同的,和小球从斜坡滚落,由于但衰减因子β的存在,小球并不会一直加速,而是达到最大速度后开始匀速行驶。
作用
病态曲率
[*]SGD在移动的过程中,因为(batch较小带来的)随机性、病态曲率等原因,可能会出现震荡现象,降低收敛速度,而动量可以抑制震荡。举例来说,如果某个维度,比如W1,在最近的若干次迭代中,总是震荡(一会往正一会往负),动量是历史梯度的加权平均,基于动量法的更新,积累了W2方向上的分量,清空了W1方向上的分量,因此会让这个维度的变化接近0,从而抑制动荡。
[*]提高速度。这是因为动量会对历史梯度做加权平均,如果某个维度,比如w2,在最近的若干次迭代中,始终往正/负向变化,那么这种加权平均会增强这种变化,从而提高收敛速度。
Adagrad
前面的随机梯度和动量随机梯度算法都是使用全局的学习率,所有的参数都是统一步伐的进行更新的,上面的例子中我们是在二维权值的情况,如果扩展到高维,大家可想而知,优化环境将很复杂,比如你走在崎岖额深山老林林,到处都是坑坑洼洼,如果只是走一步看一步(梯度下降),或者快速奔跑向前(动量学习),那我们可能会摔的头破血流。如果可以针对每个参数设置学习率可能会更好,让他根据情况进行调整,这里就先引出自适应梯度下降?AdaGrad其实很简单,就是将每一维各自的历史梯度的平方叠加起来,然后更新的时候除以该历史梯度值即可。
定义首先一个量θ用于累加梯度的平方,如下:
平方的原因是去除梯度符号的干扰,防止抵消,更新时:
其中δ=1e-7,防止数值溢出。
AdaGrad使的参数在累积的梯度较小时(θ<1)就会放大学习率,使网络训练更加快速。在梯度的累积量较大时(θ>1)就会缩小学习率,延缓网络的训练,简单的来说,网络刚开始时学习率很大,当走完一段距离后小心翼翼,这正是我们需要的。但是这里存在一个致命的问题就是AdaGrad容易受到过去梯度的影响,陷入“过去“无法自拔,因为梯度很容易就会累积到一个很大的值,此时学习率就会被降低的很厉害,因此AdaGrad很容易过分的降低学习率率使其提前停止,怎么解决这个问题呢?RMSProp算法可以很好的解决该问题。
RMSProp
用法
首先计算每一步的梯度平方的移动指数平均值st,然后将当前学习率调整为:初始学习率/根号st,然后和当前的负梯度做点乘(两个向量/矩阵对应元素做乘法)。
RMSProp也可以自动调整学习率,还可以额外为每个参数选定不同的学习率。
虽然AdaGrad在理论上有些较好的性质,但是在实践中表现的并不是很好,其根本原因就是随着训练周期的增长,学习率降低的很快。而RMSProp算法就在AdaGrad基础上引入了衰减因子,RMSProp在梯度累积的时候,会对“过去”与“现在”做一个平衡,通过超参数进行调节衰减量。
实践中,RMSProp更新方式对深度学习网络十分有效,是深度学习的最有效的更新方式之一。
作用
[*]主要作用是对不同参数动态计算对应的学习率,对于参数比较稀疏的模型作用比较大,比如带词向量的模型。某些词很高频,其词向量经常会被更新,那么它的学习率就会被调整的比较低,有防止个别example对该词向量参数的影响过大的作用;而有些词比较低频,偶尔出现一次,这种情况就需要充分利用当前的梯度信息进行较大的调整/学习。
[*]也有模拟退火的作用,如果step size过大,算法会自动降低学习率,从而避免错过最优点。
[*]抑制震荡(这个不太确定,如果是病态曲率导致的震荡,因为震荡方向的梯度分量明显比理想方向的梯度分量大,所以一定程度上也许可以抑制震荡)。
和Momentum相比,Momentum主要是加速minimal方向的搜索,减少(抵消)震荡方向的搜索;而RMSProp则是较小地抑制minimal方向的搜索,较大的抑制震荡方向的搜索。
Adam
用法
结合Momentum和RMSProp。虽然动量加速了我们对最小值方向的搜索,但RMSProp阻碍了我们在振荡方向上的搜索。Adam通过名字我们就可以看出他是基于动量和RMSProp的微调版本,该方法是目前深度学习中最流行的优化方法,在默认情况尽量使用Adam作为参数的更新方式。
首先计算当前最小批量数据梯度。
和动量学习法一样,计算衰减梯度V:
和RMSProp算法类似,计算衰减学习率R:
最后更新参数:
上面就是RMSProp和动量的有机集合,使他们的优点集于一身,但还是有一个问题就是开始时梯度会很小,R和V经常会接近0,因此我们需要初始给他一个合适的值,如下面的公式:
其中t表示训练次数,刚开始Vb,Rb很大,随着训练次数r的增加Vb,Rb逐渐趋向于V,R。
作用
[*]Adam和Momentum方法都能收敛到具有相同loss的局部最小;
[*]Adam比Momentum方法收敛更快;
[*]也许动量法用得更普遍,尽管从论文上看Adam更吸引人。经验表明这三种算法都能收敛到给定损失曲面的不同的最优局部极小值。然而,动量法看起来要比Adam更容易找到比较平坦的最小值,而自适应方法(自动调整学习率)倾向于迅速地收敛于较尖的最小值。比较平坦的最小值概括性更好。
[*]Momentum方法更容易收敛到flat minimal,而Adam更容易收敛到narrow minimal。所以一个实践上的方法是,先用Adam快速收敛,然后再用动量方法。先收敛到不容易收敛的narrow minimal,再收敛到泛化性更好的flat minimal。
页:
[1]