深度学习中常见的优化算法比较

来源:互联网 发布:ubuntu gnome 安装 编辑:程序博客网 时间:2024/06/06 02:31

SGD

Basic SGD

the baisc sgd is:

# Vanilla update
x += - learning_rate * dx

Momentum Update

Momentum update 是一种几乎总会加快收敛速度的方法. 这种方法据说是物理学中某个理论的启发. 类比SGD, 其中loss 可以类比为一座山的高度, 参数的出书画过程类似于在这个山坡上面设置一个初始速度为0的点, 那么优化过程可以看做这个初始点在该山坡上面滚动的过程.

# Momentum update
v = mu * v - learning_rate * dx # integrate velocity
x += v # integrate position

这里我们引入一个新的变量 v, 并且该变量的初始值为0, 以及变量mu, mu 在优化中被称为 momentum(也许这个名称不合适, 但是是历史原因了). mu 一般设置为0.9. 从物理的角度讲, mu 更类似于摩擦力的系数. 有时候, 也会使用变化的momentum, 一般是随着优化过程的进行, 逐渐增大mu, 典型的方法是初始momentum设置为0.5, 然后逐渐增加到0.99左右.

With Momentum update, the parameter vector will build up velocity in any direction that has consistent gradient.

Nesterov Momentum

Nesterov Momentum 是最近比较流行的一种与传统的momentum update稍有不同的方法, Nesterov Momentum 在凸优化中有较强的理论保证收敛, 并且,在实践中, Nesterov Momentum也几乎重视比传统的Momentum的效果要好. 其过程为:

x_ahead = x + mu * v
# evaluate dx_ahead (the gradient at x_ahead instead of at x)
v = mu * v - learning_rate * dx_ahead
x += v

然而,在实践中, 为了类似于vanilla SGD, 一般会做一步变量转换工作, x_ahead = x + mu * v, 从而, 使用x_ahead描述优化过程. 所以, 优化过程变为:

v_prev = v # back this up
v = mu * v - learning_rate * dx # velocity update stays the same
x += -mu * v_prev + (1 + mu) * v # position update changes form

Annealing the Learning Rate

Step decay 每隔几个epoch减少一次learning rate, 一般是每运行5个epoch左右把learning rate减少一半, 或者是每隔20个epoch减少为原来的1/10. 然而,具体的learning rate 的调整方法还是要看网络的设计和模型. 另外, 还有一种方法是, 在训练的过程中观察training error和validation error, 当validation error不再减小的时候, 减小learning rate.

Exponential decay 的数学描述是 α=α0ektα=α0e−kt, 其中 α0,kα0,k 是超参数, tt 是迭代次数.

1/t decay 的数学描述是α=α01+ktα=α01+kt 其中 (α0,k(α0,k) 是超参数, tt 是迭代次数.

Per-parameter adaptive learning rate methods

上面讨论过的所有的方法都是所有的参数都使用相同的调整策略. 调整learning rate的代价一般比较高, 因此, 有很多探索自动调整learning rate的工作, 另外也有一些工作是分别调整每一个参数的更新方法. 这些方法仍然需要超参数, 但是, 这种方法对于超参数的的设置不像传统的方法那么敏感. 这里我们介绍几种实践中常用的方法.

AdaDelta

pass

AdaGrad

pass

# Assume the gradient dx and parameter vector x
cache += dx**2
x += - learning_rate * dx / (np.sqrt(cache) + eps)

cache 的大小和gradient的大小相同, 记录的是每个参数的梯度的平方和. 之后,cache 用来以element-wise的方式normalize参数的更新. 从上面的代码中可以看出, 梯度较高的权重的有效learning rate会减小, 相应的梯度较低的权重的有效learning rate会增大. 这里, 让人感到比较搞笑的是, sqrt 操作非常重要,如果没有sqrt操作, 该算法的效果非常糟糕. eps 是smooth 操作,一般设置为 10410−4  10810−8 之间,从而可以避免除0错误(这种方法,在CNN中训练中极为常见, 比如在batch normalization中也是通过这种方法避免出现除0的错误). Adagrad的一个缺点是,在深度学习中,the monotonic learning rate usually proves too aggressive, 因此常常过早结束了学习过程.

Adam

Adam 是最近提出的一种算法, 该算法和(下面将要介绍的)带有momentum的RMSprop比较类似, 过程类似于:

m = beta1*m + (1-beta1)*dx
v = beta2*v + (1-beta2)*(dx**2)
x += - learning_rate * m / (np.sqrt(v) + eps)

该方法和RMSProp唯一的区别是”smooth”过程, 这里使用的是m来做smooth操作, 而不是使用原始的gradient vector dx. 论文中推荐的超参数为eps=1e-6, bata1=0.9, beta2=0.999, 在实践中, 如果没有其他的特殊理由,一般推荐使用Adam方法, 并且, Adam算法通常会比RMSProp算法效果好. 另外,也可以尝试SGD+Nesterov Momentum. 完整的Adam算法中还包括bias的纠正机制, 这事因为,在刚开始的几个steps中,m和v都要初始化, 并且在warm up 之前他们都biased at zero. 更多的细节可以参考论文原文.

RMSProp

RMSProp是一个非常高效的算法,但是目前并没有发表. RMSProp通过一种非常简单的方法更新参数.

cache = decay_rate * cache + (1 - decay_rate) * dx**2
x += - learning_rate * dx / (np.sqrt(cache) + eps)

decay_rate 是超参数, 一般可以设置为0.9,0.99,0.9990.9,0.99,0.999. 其中, x+= 操作和Adagrad完全相同, 但是, 变量cache是leaky的,所以, RMSProp 仍然根据每个权重的gradient来调整learning rate.

本文链接 http://ask.5lulu.com/viewblog/p2n2e6jpip825d.html

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 全球角色等级考核 大雍女提刑 相府逃妾登基了 电竞:荣光归你 撩疯!禁欲傅总嗜我成瘾 惊!废材她捶了天道 病娇战神的醋坛子翻了 当npc成为天降娘亲后她佛了 女主修仙,法力无边 惊!疯批狐王哭着求我摸尾巴 穿成农女后拥有了一整片森林 锦鲤系统:小奶包她欧气爆棚 不可退出 傲娇殿下整天粘着我要入赘 路人甲她又又又上位了 鬼医王妃,带着医毒空间回来复仇 凤落人间千般好 我加载了怪谈游戏 大国体育 薄教授是个护妻狂魔 我在京都贫民巷当神医 我带着游戏账号回古代经商 暴君心尖宠她从天上来 在大理寺卿怀里假意娇嗔 软萌女法师 黑客大佬又被伪装奶狗缠上了 豪门大佬每天都在娱乐圈艰难求生 荒野攻略学长手札 端王殿下又在书房偷看我 我欲修仙,狗皇帝滚边 新鲜!乡下来的小娇娇震惊全球 穿越后,病弱王爷日夜娇哄我 穿成恶毒妃子后,靠弹幕洗白了 穿成炮灰后全家在古代逃荒求生 重生九零:替嫁傻妻成了大佬心头肉 夏日陷情 穿成万人迷文里的炮灰女配 闪婚后我成了疯批大佬们的团宠 顶级甜诱:柔弱娇妻人设崩了 快穿:千古风流人物 家属