今天学习tensorflow的过程中看到了tf.train.GradientDescentOptimizer 、tf.train.AdamOptimizer Adam、tf.train.MomentumOptimizer 这些,发现自己对优化器的认识还仅仅停留在随机梯度下降的水平,遂找了几个博客,看了一下,现总结如下:
1.如何选择优化器 optimizer,这篇文章介绍了9种优化器,从最基本的批量梯度下降算法,到效果很好的Adam,建议一读。
2.梯度下降优化算法综述,这篇博客翻译的是An overview of gradient descent optimization algorithms,英文好的建议看英文论文,如果想快速阅读了解建议读中文。
3.花书中也有相关的章节,例如8.3
4.对于这些优化的一个其他的总结也有一个Adam算法那么好为什么还对SGD念念不忘
5.知乎上的介绍
下面是几个实例:
1. tensorflow的优化器(一直进不去)
2.keras的优化器
‘************************** 我是分割线 ***********************’
无动量优化算法 (固定学习率的优化算法)
首先来看一下梯度下降最常见的三种变形 BGD,SGD,MBGD, 这三种形式的区别就是取决于我们用多少数据来计算目标函数的梯度, 这样的话自然就涉及到一个 trade-off,即参数更新的准确率和运行时间。
几种优化器效果图点这里,批量梯度下降因为需要先遍历一遍数据才做更新,所以对于数据量较大的不合适,太慢了,对于随机梯度下降,对于每一个数据都会进行一次参数更新,避免了刚才的那种遍历所有的数据造成的浪费时间,但是太灵活了,容易发生震荡,那么很容易想到,采用小批量数据进行一次参数更新,这就是mini-batch gradient descent 。
BGD 采用整个训练集的数据来计算 cost function 对参数的梯度:
θ=θ?η?▽
θ
=
θ
?
η
?
▽
θ
θ
J(θ)
J
(
θ
)
SGD 采用整个训练集的数据来计算 cost function 对参数的梯度:
θ=θ?η?▽
θ
=
θ
?
η
?
▽
θ
θ
J(θ;xi;yi)
J
(
θ
;
x
i
;
y
i
)
MBGD 采用整个训练集的数据来计算 cost function 对参数的梯度:
θ=θ?η?▽
θ
=
θ
?
η
?
▽
θ
θ
J(θ;xi,i+n;yi,i+n)
J
(
θ
;
x
i
,
i
+
n
;
y
i
,
i
+
n
)
加入一维动量(固定学习率的优化算法)
SGD with Momentum
为了抑制SGD的震荡,SGDM认为梯度下降过程可以加入惯性。下坡的时候,如果发现是陡坡,那就利用惯性跑的快一些。SGDM全称是SGD with momentum,在SGD基础上引入了一阶动量。
SGD with Nesterov Acceleration
SGD 还有一个问题是困在局部最优的沟壑里面震荡。想象一下你走到一个盆地,四周都是略高的小山,你觉得没有下坡的方向,那就只能待在这里了。可是如果你爬上高地,就会发现外面的世界还很广阔。因此,我们不能停留在当前位置去观察未来的方向,而要向前一步、多看一步、看远一些。
加入二维动量 (自适应学习率的优化算法)
此前我们都没有用到二阶动量。二阶动量的出现,才意味着“自适应学习率”优化算法时代的到来。SGD及其变种以同样的学习率更新每个参数,但深度神经网络往往包含大量的参数,这些参数并不是总会用得到(想想大规模的embedding)。对于经常更新的参数,我们已经积累了大量关于它的知识,不希望被单个样本影响太大,希望学习速率慢一些;对于偶尔更新的参数,我们了解的信息太少,希望能从每个偶然出现的样本身上多学一些,即学习速率大一些。
Adagrad
这个算法就可以对低频的参数做较大的更新,对高频的做较小的更新,也因此,对于稀疏的数据它的表现很好,很好地提高了 SGD 的鲁棒性,例如识别 Youtube 视频里面的猫,训练 GloVe word embeddings,因为它们都是需要在低频的特征上有更大的更新。
Adadelta
这个算法是对 Adagrad 的改进,和 Adagrad 相比,就是分母的 G 换成了过去的梯度平方的衰减平均值。
RMSprop
RMSprop 是 Geoff Hinton 提出的一种自适应学习率方法。RMSprop 和 Adadelta 都是为了解决 Adagrad 学习率急剧下降问题的。
Adam
这个算法是另一种计算每个参数的自适应学习率的方法。除了像 Adadelta 和 RMSprop 一样存储了过去梯度的平方 vt 的指数衰减平均值 ,也像 momentum 一样保持了过去梯度 mt 的指数衰减平均值