深度学习优化器应该是面试都会常考的东西,很惭愧到现在才搞清楚,基于这个blog:https://blog.csdn.net/BVL10101111/article/details/72614711总结一下。
优化算法是什么东西呢,就是通过调整目标函数的参数,使得目标函数越来越小;如何做到这一点呢,就要基于最基本的梯度下降算法了,也就是参数要朝着梯度下降的方向变化,才能使目标函数越来越小,当然梯度下降也有一些弊端,所以基于梯度下降就有了一些改进的优化算法。主要分为两方面改进,一个是梯度,另一个是学习率。
原blog的分法将是优化算法分为三类:1.最基本的优化算法 2.自适应参数的优化算法 3.二阶近似的优化算法(很少用,因为耗时过大),我们这改一下,先说明梯度下降,然后本文主要讲一下改进梯度的算法。
1.最基本的优化算法 —— SGD
SGD,也就是上面讲的梯度下降;这里一般是取一个batch的数据(比如我们常用的batch_size=1024,也就是一个batch里有1024条数据)去作为计算梯度的样本

从公式可以看到这里是根据每个样本对参数θ求了偏导,再平均每个样本的偏导作为θ的梯度,去进行更新;
这个算法有两个方面的问题:一个是梯度,没能克服局部最优解的问题(两个极端,如果是全量数据就陷在鞍点了,如果是一条数据就可能会跳动,有可能跳出去,但是并没有完全克服这个问题);另一个是学习率,如果太小就收敛得慢,如果太大就会在极小值的地方震荡,当然也有一种做法是这样的:

在设定一个较大的E0和一个较小的Er,然后中间α=k/r,也就是第0次到第r次之间的学习率是一个线性衰减,大于r之后就不变了,但是这样阈值就需要预先拍一个,不一定能适应数据集的特点;而且我们可能还会想对频率低的特征进行大一点的更新这种需求,所以SGD还是一个需要改进的方法。
2. 对梯度进行改进的算法 —— Momentum
Momentum 原blog里将是为了解决黑塞矩阵病态的问题,但我其实没太看懂这里,我看了另一篇公众号的文章《最全机器学习优化器Optimizer汇总》里说是为了解决梯度的问题,先看下算法的具体公式吧:

这里梯度计算完之后没有直接给到参数更新,而是加到了原来的梯度上,再用以更新参数,原梯度就相当于是一个动量(有个惯性)。
如果当前梯度和累积梯度方向一致的话,下降的速度就会更快,如果当前梯度和累积梯度方向不一致的话,当前梯度的方向会要减弱,这就会有利于通过惯性冲过局部最优点;α是一个超参,表示之前的梯度多大程度上影响当前的参数更新,如果取0.9的话就是基本取决于之前的梯度,把公式变形一下可以看到最大速度约等于梯度下降的10倍。
黑塞矩阵的问题公众号文章说可以理解为SGD在收敛过程中和正确梯度相比来回摆动比较大的问题,那么Momentum就因为有累积梯度可以更快地向最低点靠近了。
3.对梯度进行改进的算法2 —— Nesterov(牛顿动量)
Nesterov是Momentum上的一个小改进,还是先看公式:

Momentum是在原来的点计算梯度,Nesterov是先根据之前的梯度到一个临时点计算梯度再用临时点的梯度+之前的梯度来更新参数;图示一下:

蓝色是momentum,先在当前梯度下降,再在原梯度下降;棕色是牛顿动量,先通过原梯度去到临时点,然后在临时点计算红色梯度下降,合起来就相当于第一条绿色;下一次也是如此就是后面那个三角形了。
这么做的目的是,据blog里说在GD下,Nesterov可以将误差收敛从O(1/k),改进到O(1/k^2),然而在SGD下,Nesterov并没有任何改进。
这两种方法是对梯度的改进,但是人工设定学习率epsilon还是有点尴,下一篇会说一下自适应学习率算法,以及和梯度改进算法的结合。
附微信文章链接:https://mp.weixin.qq.com/s?src=11×tamp=1635144470&ver=3395&signature=zBqcNIKAzmjUNo*Da3d1gh5tJdMDNf9TlxbFItUA2bv3KWP07223-XkWSJGVmV*4sxmsrFCTBYCcdykyEgCCsPJJr0fVi2NOTYc65ILJIl0tZS72tbikN2hag0LbvoMm&new=1