Caffe 现在提供了六种优化算法:
- Stochastic Gradient Descent (type: SGD)
- AdaDelta (type: AdaDelta)
- Adaptive Gradient (type: AdaGrad)
- Adam (type: Adam)
- Nesterov's Accelerated Gradient (type: Nesterov)
- RMSprop (type: RMSPorp)
Solver 求解器是 Caffe 的核心。它的作用就是交替进行前向计算求得 loss 和后向计算更新参数,从而最小化 loss. 是一种迭代优化算法.
假设一个数据集,其数据总量为 D, 那么这整个数据集的 loss 的平均值是:
其中,前面第一部分就是求所有数据损失值的平均值,第二部分是正则项,lamda 是正则项系数,用于防止过拟合.
如果数据量很小的话,用上面的公式还可以计算。但是如果数据量 D 非常大,那么计算一次 Loss 将耗费很长的时间.
所以这时候提出了 batch (批) 这个概念,将所有数据集 D 分割成很多个小的 batch, 记为 N.
在一次前向计算和后向计算中,我们只提取一个 batch 数量的数据,然后只更新这一 batch 数据的 loss,
然后我们可以重复的,多次的提取一个 batch 数据来进行计算.
** 在 caffe 中,默认的优化算法是 SGD, 也就是随机梯度下降算法. **
一. Stochastic Gradient Descent (SGD)#
随机梯度下降算法是在梯度下降算法的基础上发展起来的,梯度下降算法也叫最速下降算法.
简要一句话说明 SGD 的原理就是当前参数 W (t+1) 等于 上一次更新后的参数 Wt 和 当前权重更新值 的线性组合.
而我们实际在 caffe 中使用的时候都是加上冲量法的.
其中,α 是学习率 (base_lr), μ 是上一次梯度值的权重,就是冲量 (momentum).
学习率是要不断下降才能让模型不断优化的。学习率可以理解为步长,优化模型就是翻山越岭的从最陡方向出发找最低谷。如果步子太大了,容易跨过最低谷,
如果步子太小,找的太慢,而且容易陷入其他非最低谷出不来了。在 solver 文件中,学习率下降策略 lr_policy 有很多,以后我会详细讲的,
知道有这么回事就好.
上面说的最陡方向,其实就是负的梯度方向.
冲量就是在保证 loss 稳定的情况下,尽量加速其下降. ** 对于 SGD, 这个一般默认设置为 0.9, 在某些特殊情况,当学习率下降到很小的时候,
可以将冲量设置为 0.99, 提高训练效果. **
二. AdaDelta#
Paper 地址: https://arxiv.org/pdf/1212.5701.pdf
AdaDelta 是一种具有适应性的学习率方法,也是基于梯度下降发展出来的。这个算法不需要手动调优学习率,并且对噪音有很好的鲁棒性.
下面是几点这个方法的优点:
-
不用手动设置学习率.
-
对超参数初始化不敏感.
-
对于每一维度,分别有一个动态的学习率.
-
对大梯度,噪音,和结构选择有很好的鲁棒性.
-
对本地和分布式环境的适应性都很好.
原作者一开始想对梯度下降法做很多改动,最大的想法就是应用牛顿法,使用二阶导的代价函数,即 Hessian 海森矩阵:
其中 Δxt 是参数变化量,Ht 是 Hessian 海森矩阵,相当于学习率,即步长. gt 就是梯度,决定下降方向。这时候学习率是由海森矩阵决定的,
所以我们就不用手动的设置学习率了.
但是,海森矩阵在计算上是非常复杂和麻烦的,所以作者借着海森矩阵这个思路,想到加强对一阶导数使用或者用估算海森矩阵结果的方法.
最终是选择了加强一阶导数使用的方法,近似模拟二阶牛顿法
基本思路还是跟 SGD 一样,实际的变化量是 冲量和上一次变化量的乘积减去基础学习率乘以当前梯度值 (这里基础学习率是 1.0, 而且保持不变.)
AdaDelta 冲量一般设置成 0.95
solver 中 delta 一般设置成 1e-6
** base_lr 必须设置为 1.0 **
** lr_policy 必须设置为 fixed.
**
------------------------- 下面是具体算法实现步骤 --------------------------------------------------------------------------------------------------------------
paper 中作者跟 AdaGrad 方法做了大量的对比,作者提出 AdaDelta 方法主要解决了 AdaGrad 的两个缺点。一是解决了随着训练的进行,
学习率会持续衰减的问题。我认为作者想表达的意思就是随着训练的进行,如果学习率持续降低,到后期对优化的影响会降到很低导致优化不完全.
二就是解决的需要手动设置初始学习率的问题.
2012 年 Schaul&S. Zhang&LeCun 提出了 AdaGrad-like 算法,我这里提到这个算法是因为和 AdaDelta 算法有相似的地方.
其中,diag (Ht) 是海森矩阵的对角矩阵,E [gt-w] 是从当前 t 算起前 w 次迭代梯度的期望值,分母就是从当前 t 算起前 w 次迭代梯度平方的期望值
这样取前 w 次梯度的好处是不会让梯度消失
好了回到 AdaDelta, 这个方法没有只是取前 w 次迭代梯度,而是取所有迭代的梯度.
其中,** ρ 是衰减常量,在 caffe 中通过设置 momentum 来设置这个参数 ** . 通过这个公式,我们算出当前 iteration
所有梯度平方的期望值.
我们需要上面结果的平方跟用于参数更新,这里用 RMS (root mean square 均方根) 表示:
其中,RMS [g] t 表示当前 iteration 下,梯度 g 的均方根值,** ε 是一个常数 (就是 solver 中参数 delta) ** , 平滑项,
为了保证输出结果不为零,因为后面这个结果是要做分母的.
最后参数的变化量公式:
上面的方法就是 Tieleman&Hinton 的 RMSProp.
后来的 Zeiler 考虑到 units 的问题,Δx 是用来更新参数 x 的,所以他们的 units 必须要一致.
说说我的理解,上面的公式中,gt 的 units 应该是跟 x 正相关的. RMS [g] t 的 units 也是跟 x 正相关的.
但是一相除,就变成了 unitless 这种情况了.
所以在看下面公式,在分子上加上了上一次迭代的参数变化量的 RMS, 将 units 又找了回来.
** 这个 units 到底怎么理解我还有困惑,我觉得应该可以理解为 "单位" **
并且加入上一次迭代,会增加最终结果的鲁棒性,不会发生突变.
分子分母 RMS 中的 ε 取相同的值
实际步长,也可以认为是学习率,跟当前梯度和上一次参数变化量相关
所以不同层,不同维度的参数的学习率也是不同的。可以用 "因人而异" 来形容.
而不是 SGD 那样所有参数的学习率是相同的.
AdaDelta 在训练初期和中期,速度很快。但是到后期容易陷入局部最优。这一点没有 SGD 效果好.
三. AdaGrad#
Adaptive Gradient 自适应梯度算法,借鉴了 L2 Regularizer
其中,分母是从 1 开始到 t 的所有梯度和的平方根,η 是基础学习率.
权值初始化对 AdaGrad 影响敏感,如果权值初始化过大,梯度很大,调节幅度会很小.
训练中后期,梯度很容易逼近 0 , 提前结束训练.
适合处理稀疏梯度
实际使用公式是:
** solver 中 base_lr 一般设置不大,可参考使用 0.01 **
** lr_policy 必须设置为 "fixed" **
momentum 对应公式 ** 中 ε **
四. Adam#
Adaptive Moment Estimation
同样也是基于梯度的优化方法.
只需要一阶梯度信息,并且占用很少的内存.
通过估计梯度的一阶矩 和 二阶矩 去动态的调整每个参数的学习率.
其中,mt 是对梯度的一阶矩估计,nt 是对梯度的二阶矩估计。上面带拐的是对其自身的校正.
u 一般取 0.9
v 一般取 0.999
ε 一般取 1e-8.
五. NAG#
Nesterov's Accelerated Gradient
Nesterov 的改进是让之前的动量直接影响到当前的动量
其中,η 是基础学习率,μ 是动量 (冲量)
momentum 首先计算一个梯度,短的蓝色向量。然后在加速更新梯度的方向进行一个大的跳跃,长的蓝色向量.
nesterov 项先在以前的加速梯度方向进行一个大的跳跃,棕色向量
最后计算梯度,进行校正,绿色向量.
** solver 中 base_lr 一般为 0.01, gamma 为 0.1 **
** lr_policy 一般为 "step", stepsize 视情况而定. **
** momentum 一般为 0.95 **
**
**
六. RMSprop#
这个算法公式在上面 AdaDelta 中已经写出来了,RMSprop 是 AdaDelta 的中间形式.
** solver 中 base_lr 看情况为 1.0 或者 0.001 **
** ** lr_policy 一般为 "fixed" ** **
** ** rms_decay 一般为 0.98 ** **
** ** momentum 一般为 0.95 ** **
七。选择优化方法和优化策略#
-
RMSprop 解决了 AdaGrad 训练中后期梯度消失的问题.
-
AdaDelta 中参数的学习率与初始学习率无关。而 RMSprop 中参数学习率与初始学习率有关.
-
Adam 比 RMSprop 增加了偏差校正和动量 (注意 RMSprop 中参数 momentum 的数值是作用在求期望的过程中,不算动量.)
-
如果输入数据是 稀疏的,最好使用自适应学习速率的优化方法 (AdaGrad, AdaDelta, RMSprop 和 Adam). 因为在优化过程中它们会自动调整学习率.
-
如果关心优化速度,那么自适应学习速率方法会比较快. ** Adam 可能是当前最好的优化方法。但很多大牛还是使用原始的 SGD 并且不用动量项. **
-
Shuffle: 每次迭代时随机打乱数据样本顺序
-
Curriculum Learn: 把训练样本按某种有意义的方式排序,对逐步解决困难问题有帮助.
-
归一化参数初始值.
-
Early Stopping, 这个结合可视化技术来看。取过拟合前的模型来用.
-
在损失函数中添加正则化项.
-
Dropout, 测试阶段不要用 Dropout
-
并行与分布式优化方法: Hogwild, Downpour SGD, Delay-tolerant Algorithms for SGD, Elastic Averaging SGD, 工具使用 Tensor Flow.