深度学习优化算法经历了 SGD -> SGDM -> NAG ->AdaGrad -> AdaDelta -> Adam -> Nadam 这样的发展历程。我们结合CS231n课程中的讲解来比较一下这些优化算法的优缺点。
1 SGD 随机梯度下降
SGD示意图:
1 2 3 4 |
# SGD伪代码 while True: dx = gradient(x) x += learning_rate * dx |
缺点:
SGD最大的缺点是下降速度慢(下降速度固定),而且可能会在沟壑的两边持续震荡,停留在一个局部最小值。当遇到鞍点时,由于梯度为0而无法下降。
2 SGD+Momentum(SGDM) 带动量的SGD
1 2 3 4 5 6 |
# SGDM伪代码 vx = 0 while True: dx = gradient(x) vx = rho * vx + dx # rho表示“摩擦力”的作用,通常为0.9或0.99 x += learning_rate * vx |
由于加入了速度值,能够更快收敛,在鞍点虽然梯度为0,仍然可以下降。
SGD还有一个问题是困在局部最优的沟壑里面震荡,因此引入了Nesterov Acceleration来解决这个问题。
3 SGD with Nesterov Acceleration(NAG)
Nesterov Acceleration考虑到了动量的累积,当累积了足够的动量时就可以跳出局部最小点。由于累积动量的存在,NAG有时会忽略陡峭的局部最小值(类似于骑摩托车加速飞跃沟壑)。
1 2 3 4 5 |
# NAG伪代码 dx = gradient(x) old_v = v v = rho * v - learning_rate * dx x += -rho * old_v + (1 + rho) * v |
以上的几种优化方法都只用到了一阶动量。但是没有考虑到的是,对于经常更新的参数,我们希望学习率低一些,对于不经常更新的参数,我们希望学习率大一些,为此引入了自适应学习率的优化算法。
4 AdaGrad
AdaGrad优化算法记录梯度的累积值,梯度累积越大,学习率越小。
1 2 3 4 5 6 7 |
# AdaGrad伪代码 grad_squared = 0 while True: dx = gradient(x) grad_squared += dx * dx # 累积变化越大时,学习率越小 x -= learning_rate * dx / (np.sqrt(grad_squared + 1e-7)) |
缺点:
因为AdaGrad的学习率是单调递增的,会使得学习率逐渐趋向于0,可能会使得训练过程提前结束,即便后续还有数据也无法学到必要的知识。
5 AdaDelta / RMSProp
由于AdaGrad单调递减的特性导致后期学不到东西,AdaDelta只关注过去一段时间窗口的下降梯度,而不是累积全部的历史梯度。RMSProp在累积梯度的同时持续衰减累积值。这样就避免了二阶动量持续累积、导致训练过程提前结束的问题。
1 2 3 4 5 6 |
# RMSProp伪代码 grad_squared = 0 while True: dx = gradient(x) grad_squared = decay_rate * grad_squared + (1 - decay_rate)* dx * dx # decay_rate通常取0.9或0.99 x -= learning_rate * dx / (np.sqrt(grad_squared + 1e-7)) |
6 Adam
将以上的一阶动量与二阶动量结合,就产生了Adam优化算法。
1 2 3 4 5 6 7 8 9 10 |
# Adam伪代码 first_moment = 0 second_moment = 0 for t in range(num_iterations): dx = gradient(x) first_moment = beta1 * first_moment + (1 - beta1) * dx second_moment = beta2 * second_moment + (1 - beta2) * dx * dx first_unbias = first_moment / (1 - beta1 ^ t) second_unbias = second_moment / (1 - beta2 ^ t) # 防止刚开始训练时second_moment很小产生很大的学习率。 x -= learning_rate * first_unbias / (np.sqrt(second_unbias + 1e-7)) |
Adam优化算法一般取beta1=0.9,beta2=0.999,learning_rate=1e-3或5e-4。
7 Nadam
Nadam在Adam的基础上加入了一阶动量的累积,即Nesterov + Adam = Nadam。
8 总结
优化算法 | Momentum(动量) | Nesterov(动量累积) | 二阶动量累积 |
---|---|---|---|
SGD | × | × | × |
SGDM | ○ | × | × |
NAG | ○ | ○ | × |
AdaGrad | × | × | 一直累积 |
AdaDelta / RMSProp | × | × | 一段时间 |
Adam | ○ | × | ○ |
Nadam | ○ | ○ | ○ |
9 参考资料
CS231n Lecture7 https://www.bilibili.com/video/av13260183/?p=7
http://www.sohu.com/a/226332315_633698
https://blog.csdn.net/shuzfan/article/details/75675568#2-1-batch-gradient-descent-bgd