原文:An overview of gradient descent optimization algorithms
梯度下降算法
梯度下降算法(Gradient Descent Optimization)是神经网络模型训练最常用的优化算法。详见:梯度下降
梯度下降算法的原理:
-
目标函数 关于参数 的梯度将是损失函数(loss function)上升最快的方向。
-
要最小化 loss,只需要将参数沿着梯度相反的方向前进一个步长,就可以实现目标函数(loss function)的下降。这个步长 又称为学习速率。
-
参数更新公式如下:
-
其中 是参数的梯度。
根据计算目标函数采用数据量的不同,梯度下降算法又可以分为:
-
批量梯度下降算法(Batch Gradient Descent,BGD)
其 是在整个训练集上计算的,如果数据集比较大,可能会面临内存不足问题,而且收敛速度一般比较慢。
-
随机梯度下降算法(Stochastic Gradient Descent,SGD)
又称为在线学习,即得到了一个样本,就可以执行一次参数更新。所以其收敛速度会快一些,但是有可能出现目标函数值震荡现象,因为高频率的参数更新导致了高方差。
-
小批量梯度下降算法(Mini-batch Gradient Descent,MBGD)。
是折中方案,选取训练集中一个小批量样本(一般是2的倍数,如32,64,128等)计算,这样可以保证训练过程更稳定,而且采用批量训练方法也可以利用矩阵计算的优势,是目前最常用的梯度下降算法。
问题与挑战:
-
选择一个合适的学习率可能是困难的。学习率太小会导致收敛的速度很慢,学习率太大会妨碍收敛,导致损失函数在最小值附近震荡甚至发散。
-
虽然可以通过退火等方法调整学习率,但策略和阈值需要预先设定好,因此无法适应数据集的特点。
-
另一方面,SGD 不易处理鞍点处的梯度。由于鞍点周围的误差相同,梯度在所有方向都接近于0,导致 SGD 很难脱离鞍点。
Momentum
-
SGD(指上面的三种方法)的参数更新完全依赖于当前的 batch,容易出现震荡现象
-
动量(Momentum optimization) 通过将当前时刻的梯度 ,与前一时刻的梯度 按照动量的系数 进行加权,使得当前的更新方向包括当前梯度的方向与之前时刻梯度的方向,来增加更新的稳定性,同时抑制 SGD 的震荡现象。
-
动量的系数 表示保留原来方向的程度,通常设置为 0.9 左右。
-
当梯度指向收敛方向时,动量加快更新速度;当梯度改变方向时,动量降低更新速度。从而在保证收敛更快的同时,减弱震荡现象。
NAG
-
NAG 即 Nesterov accelerated gradient 涅斯捷罗夫梯度加速。相比于momentum,NAG 增加了一个将要去哪里的指示,因而在曲面上升时,能够降低更新速度。
-
NAG 在计算参数的梯度时,在损失函数中减去了动量项,即计算 ,这种方式预估了下一次参数所在的近似位置。即:
-
动量系数 通常设置为 0.9 左右。
-
在 Momentum 中,首先计算当前梯度项(小蓝色向量),然后加上动量项,这样便得到了大的跳跃(大蓝色的向量)。
-
NAG 首先进行一个大的跳跃(动量项)(棕色向量),然后加上一个小的使用了动量计算的当前梯度(红色向量)进行修正得到绿色的向量,避免更新过猛。
Adagrad
-
Adagrad 即 Adaptive Gradient Algorithm 自适应梯度算法。
-
上面的方法在参数更新过程中,使用了固定的学习率。Adagrad 则是让学习率适应参数。
-
对于出现次数较少的特征,对其采用更大的学习率,对于出现次数较多的特征,对其采用较小的学习率。因而适用于处理稀疏数据。
-
令 为在 时刻目标函数关于参数 的梯度:
-
通常,在 时刻,对参数 的更新过程为:
-
使用 Adagrad 时,在 时刻,基于对 计算过的历史梯度,对每一个参数 的学习率进行了修正:
-
其中, 是一个对角矩阵。
-
第 行的对角元素 为第 个参数 的历史梯度的平方和。
-
是一个平滑参数,为了使得分母不为 0 (通常 取 )。
-
另外如果分母不开根号,算法性能会很糟糕。
-
再进一步,将所有 的元素写成向量 , Adagrad 算法参数更新的矩阵形式如下:
-
其中 ⊙ 为点乘,即矩阵对应元素相乘。
-
Adagrad 的优点是无需手动调整学习率。在大多数的应用场景中,通常采用常数0.01。
-
Adagrad的缺点是它在分母中累加梯度的平方,在整个训练过程中,累加的和会持续增长,导致学习率最终变得无限小,无法学习到新的特征。
Adadelta
-
Adadelta 是 Adagrad 的一种扩展算法,以处理 Adagrad 学习速率单调递减的问题。
-
Adadelta 只计算窗口大小为 的最近历史梯度,同时,并不存储历史平方梯度值,而是将梯度的平方递归地表示成所有历史梯度平方的均值。
-
在 时刻的均值 只取决于先前的均值和当前的梯度(分量 类似于动量项):
-
在 Adagrad 中梯度更新值为:
-
在 Adadelta 中梯度更新值为:
-
由于分母仅仅是梯度的均方根(root mean squared,RMS)误差,可以简写为:
-
将上面公式改成关于 的:
-
参数更新的均方根误差为:
-
由于 未知,使用之前时刻的 RMS 值 替换先前的更新规则中的学习率 。最终的 Adadelta 更新公式为:
-
使用 Adadelta 算法,无需设置默认的学习率,因为更新规则中已经移除了学习率。
RMSprop
-
RMSprop 未发表,但是也是自适应学习率的算法,由Geoff Hinton提出。
-
RMSprop 和 Adadelta 在相同的时间里被独立的提出,都起源于对Adagrad 的极速递减的学习率问题的求解。
-
实际上,RMSprop 是 Adadelta 的第一个更新向量的特例:
-
同样,RMSprop 将学习率分解成一个平方梯度的指数衰减的平均。Hinton 建议将 设置为 0.9,对于学习率 ,一个好的固定值为0.001。
Adam
-
Adam 即 Adaptive Moment Estimation 自适应矩估计,是另一种自适应学习率的算法,Adam对每一个参数都计算自适应的学习率。
-
除了像 Adadelta 和 RMSprop一样存储一个指数衰减的历史平方梯度的平均 ,Adam 同时还保存一个历史梯度的指数衰减均值 ,类似于动量:
-
和 分别是对梯度的一阶矩(均值)和二阶矩(非确定的方差)的估计,正如该算法的名称。
-
Adam 的作者发现当衰减率(decay rate)很小时(和 接近于 1), 和 最终都趋于0,因而Adam算法最终对一阶矩和二阶矩进行校正(和 的上标 代表 次方):
-
最终 Adam 的更新规则为:
-
作者建议 $β_1 取默认值为 0.9, 为0.999, 为 。
算法的选择
-
如果输入数据是稀疏的,选择任一自适应学习率算法可能会得到最好的结果。选用这类算法的另一个好处是无需调整学习率,选用默认值就可能达到最好的结果。
-
RMSprop 是 Adagrad 的扩展形式,用于处理在 Adagrad 中急速递减的学习率。
-
RMSprop 与 Adadelta 相同,所不同的是 Adadelta 在更新规则中使用参数的均方根进行更新。
-
Adam 是将偏差校正和动量加入到 RMSprop 中。
-
在这样的情况下,RMSprop、Adadelta 和 Adam 是很相似的算法并且在相似的环境中性能都不错。在优化后期由于梯度变得越来越稀疏,偏差校正能够帮助Adam微弱地胜过 RMSprop。
-
综合看来,Adam可能是最佳的选择。
-
有趣的是,最近许多论文中采用不带动量的 SGD 和一种简单的学习率的退火策略。通常 SGD 能够找到最小值点,但是比其他优化的 SGD 花费更多的时间,与其他算法相比,SGD 更加依赖鲁棒的初始化和退火策略,同时,SGD 可能会陷入鞍点,而不是局部极小值点。
-
因此,如果想要快速收敛和训练一个深层的或者复杂的神经网络,可以选择一个自适应学习率的方法。