【深度学习】常见的优化算法与batch size的选择

一、梯度下降算法

【深度学习】常见的优化算法与batch size的选择
(这个图是课件里的,可能对SGD的理解不太一样,其实指的是下面说的小批量梯度下降)

三个类型

梯度下降具体的公式和推导网上比较多这里就不再赘述了。
梯度下降有三种不同的形式,即批量梯度下降、小批量梯度下降随机梯度下降(SGD)。区别主要在于读入的数据数量不同,依次减小。批量梯度下降是对全部数据求导取平均,小批量则是取一部分,一般都是8的幂,而随机梯度下降取的是一个样本,对内存的压力最低。
其实说白了就是batch size不同,核心都是梯度下降算法。那batch size的大小该怎么控制比较好呢?
首先batch size其实影响了下降的方向,如果很小那么总的loss抖动会很大,而如果是全部数据,那么相对会稳定一些,而min batch就介于两者之间。
批量梯度下降虽然能很好的反映数据总体的下降趋势,可以当数据量过大的时候难以进行训练,而且对于一些数据集可能因为数据间的差异造成一部分梯度抵消。而随机梯度下降却很容易造成“各自为政”的现象。所以选择一个中间值便能够一定程度上解决这些问题。

batch size选择

【深度学习】常见的优化算法与batch size的选择
(来源:知乎用户 程引)
从这张图上我们可以看到,随着batch size增大处理相同数据所用的时间越来越短,当然对内存的要求也越来越高。而过小的时候甚至在一定的epoch下无法收敛。但batch size增大后达到相同精度需要的时间也更长了,这就产生了一个矛盾,所以我们选择一个居中的值能够在一定程度上规避两者的缺陷。
可以说,大的batch size训练的会更平滑更稳定,训练完一个epoch的时间也会更短。
但是也会造成模型泛化能力下降,也就是上面出现的达到相同精度时间变长,太大的batch size 容易陷入sharp minima,泛化性不好。
网上的说法很多,这里我自己跑了一下试试,确实大的batch size明显的变化是到指定精度的时间变长了,但总体平稳了很多,训练时间确实也是减少的。但具体的表现我决定还是根据数据本身的特性来看,所以我的小测试不一定具备一般规律。
但还是可以总结一下,batch size变大会有几点影响

  • 收敛更加平稳,避免过小而反复抖动,因此可以考虑适当增大学习率以提高收敛速度
  • 训练完一个epoch速度的速度更快,需要更大的内存支持
  • 变大到一定程度会降低泛化能力
  • 收敛到指定精度速度可能会变慢

所以一般训练的时候不要太大也不要太小,一般对精度的影响是很低的。

普通的梯度下降存在很多问题,因此也衍生出了很多改进算法,大体发展可以参考下图:
【深度学习】常见的优化算法与batch size的选择

二、动量梯度下降算法(Momentum)

【深度学习】常见的优化算法与batch size的选择
动量梯度下降(Gradient Descent With Momentum),简称为动量方法(Momentum),运行速度几乎总是快于标准的梯度下降算法,并且能够解决随机梯度下降所遇到的山谷震荡以及鞍部停滞问题。
简单来说,如果一味地依赖本次梯度,那么可能会因为“等高线”并非规则的圆而造成上下抖动,徘徊地向前。而动量方法就是考虑了当前的速度,取两者的一个加权和,这样尤其在快接近最优的时候趋近的会更快,直观地来看像是之前方向与目前方向的和。
标准梯度下降算法在每次行动时,都忽略前一时刻的速度,而重新根据当前时刻的加速度和时间来行走,因此当加速度趋于零时就很难继续移动。而动量方法则考虑前一时刻速度和当前加速度的共同作用。

Nesterov 动量

【深度学习】常见的优化算法与batch size的选择
动量存在的问题,即使当前的梯度为0,由于动量的存在,更新梯度依然会存在并继续更新w。
而继续当前点w的梯度是不太有意义的,有意义的是,假设下一个点w(仅靠动量滚到下一个点的w)的梯度方向才是决定当前梯度的重要因素。
举个通俗的例子就是,你在下坡时,如果在下坡快到底,但又未到底时,动量梯度下降会让你冲到坡的对面去。Nesterov梯度下降会预知你的下一步将会时到坡的对面去,所以会提示你提前刹车,避免过度冲到坡的对面去。这包含了一种提前计算下一步的梯度,来指导当前梯度的想法。
(参考:https://blog.****.net/legalhighhigh/article/details/81348879)
简单的说,如果我们求参数θ处的梯度,很容易出现上面那种问题,而如果求的是θ + αv的梯度,实际上是θ变换前后的中间的一个值,这个梯度其实更有参考性,也能帮助我们更高地接近最优值。

三、自适应梯度算法(AdaGrad)

【深度学习】常见的优化算法与batch size的选择
可以看到,相比于一般的梯度下降,自适应梯度下降实际上针对不同的参数对学习率进行了控制。在学习率除以了梯度平方的累加和,当然为了防止分母过小还加了个常数。如果某个参数变化较为平缓,那么其梯度会较小,学习率较大,可以更快地趋近于最优值。而如果某个参数变换较大或者曾经变化较大,如果学习率过大肯定容易抖动,所以学习率会小一些。
总结一下

  • 凸优化情况下有较好的理论性质,但对于深度神 经网络一般不成立
  • 对于训练深度神经网络模型,从训练开始时积累梯度平方会导致有效学习率在达到这样的凸结构前过早和过量的减小 。
  • 在某些深度学习模型上效果不错,但不是全部

这种方法可能会导致学习率过早减小,效果也只是对一部分模型比较好。

四、AdaDelta算法

【深度学习】常见的优化算法与batch size的选择
(来源:https://blog.****.net/u012328159/article/details/80311892)
AdaGrad算法还是需要自己手动指定初始学习率,而且由于分母中对历史梯度一直累加,学习率将逐渐下降至0,并且如果初始梯度很大的话,会导致整个训练过程的学习率一直很小,从而导致学习时间变长。
为了解决学习率衰减的问题,Adadelta只依赖本次上上次的梯度,其实就是利用指数加权平均。然后Adadelta最终的公式不需要学习率,用RMS[Δθ]进行了代替。

五、均方根传播算法(RMSProp)

【深度学习】常见的优化算法与batch size的选择
AdaGrad算法在迭代后期由于学习率过小,可能较难找到一个有用的解。为了解决这一问题,RMSprop算法对Adagrad算法做了一点小小的修改,RMSprop使用指数衰减只保留过去给定窗口大小的梯度,使其能够在找到凸碗状结构后快速收敛。这里采取的是类似于梯度那种移动平均的感觉,上一次的均方和本次取加权和,然后除学习率。
【深度学习】常见的优化算法与batch size的选择
使用Nesterov动量的RMSProp算法是这样的

六、Adam

【深度学习】常见的优化算法与batch size的选择
直观的来看,相比于RMSprop,Adam加入了分子,即梯度的一阶形式。它实际上是把momentum和RMSprop结合起来的一种算法。RMSprop自适应算法是对学习率做一个控制,而momentum是对梯度方向做一个移动平均的控制,两者结合便有了Adam。
【深度学习】常见的优化算法与batch size的选择
(来源:https://www.cnblogs.com/itmorn/p/11123789.html)
这个公式中的符号可能更普遍一些,pytorch的Adam的参数。
在①式中,注意m(n)是反向的动量与梯度的和(而在Momentum中是正向动量与负梯度的和,因此⑤式对应的是减号)
在②式中,借鉴的是RMSprop的指数衰减
③和④式目的是纠正偏差
⑤式进行梯度更新
另外是我自己的一点小看法,自适应的学习率经常要除以一个类均方根,相比于一般的sgd,所以学习率要适当的调整一下。我再MNIST上测试的时候感觉调小,从0.01到0.01,收敛的速度就很快了,否则一直在抖动,也侧面说明了对于这个问题的均方根是小于1的。

小结

【深度学习】常见的优化算法与batch size的选择
本文主要介绍了一些经典的优化算法,当然现在也有很多新的方法,但是就这几种方法而言,Adam的效果一般会好一些,因为它相当于不断的改进了原始的梯度下降。经典的梯度下降出现了动量与自适应两种改进方向, 而Adam将两者做了合并。但效果好也不是一定的,还是要具体效果也要具体情况具体分析的。
另外优化算法还有牛顿法、共轭梯度、BFGS等,但是比较主流的还是梯度下降算法。