前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【模型训练】SGD的那些变种,真的比SGD强吗

【模型训练】SGD的那些变种,真的比SGD强吗

作者头像
用户1508658
发布2019-07-26 16:45:58
7770
发布2019-07-26 16:45:58
举报
文章被收录于专栏:有三AI有三AI

深度学习框架目前基本上都是使用梯度下降算法及其变种进行优化,通常意义上大家会认为原始的梯度下降算法是最弱的,但事实上并非如此。

很多的论文依然采用了原始的梯度下降算法而不采用更高级的算法,今天就以一个实践例子来给大家展示一下各类算法的比较,所有内容参考文章【An overview of gradient descent optimization algorithms】。

01梯度下降算法

本文目标不是为了从零开始讲清楚优化算法,所以有些细节和基础就略过。

梯度下降算法,即通过梯度的反方向来进行优化,批量梯度下降(Batch gradient descent)用公式表述如下:

写成伪代码如下:

for i in range(nb_epochs):

params_grad = evaluate_gradient(loss_function, data, params)

params = params - learning_rate * params_grad

上面的梯度下降算法用到了数据集所有的数据,这在解决实际问题时通常是不可能,想想imagenet1000有100G以上的图像,内存装不下,速度也很慢。

我们需要在线能够实时计算,于是一次取一个样本,就有了随机梯度下降(Stochastic gradient descent),简称sgd

公式如下:

写成伪代码如下:

for i in range(nb_epochs):

np.random.shuffle(data)

for example in data:

params_grad = evaluate_gradient(loss_function , example , params)

params = params - learning_rate * params_grad

sgd方法缺点很明显,梯度震荡,所以就有了后来大家常用的小批量梯度下降算法(Mini-batch gradient descent)

伪代码如下:

for i in range(nb_epochs):

np.random.shuffle(data) for batch in get_batches(data, batch_size=50):

params_grad = evaluate_gradient(loss_function, batch, params)

params = params - learning_rate * params_grad

下面我们要形成共识,说sgd算法,实际上指的就是mini-batch gradient descent算法,没有人会去一次拿整个数据集或者一个样本进行优化。

当然还是要总结一下SGD算法的毛病。

(1)学习率大小和策略选择困难,想必动手经验丰富的自然懂。

(2)学习率不够智能,对所有参数一视同仁。

(3)同时面临局部极值和鞍点的问题。

可能有同学不知道鞍点怎么回事,简单来说,它就是在某一些方向梯度下降,另一些方向梯度上升,形状似马鞍,抄来一张图如下,红点就是鞍点

02梯度下降方法改进

1.1 动量法

改进方法那么多,我觉得真正最有用的就是它。

前面说了梯度下降算法是按照梯度的反方向进行参数更新,但是刚开始的时候梯度不稳定呀,方向改变是很正常的,梯度就是抽疯了似的一下正一下反,导致做了很多无用的迭代。

而动量法做的很简单,相信之前的梯度。如果梯度方向不变,就越发更新的快,反之减弱当前梯度。

画成图就是这样。

效果对比就这意思。

1.2 nesterov动量法

仍然是动量法,只是它要求这个下降更加智能。

既然动量法已经把前一次的梯度和当前梯度融合,那何不更进一步,直接先按照前一次梯度方向更新一步将它作为当前的梯度,看下面的式子就明白了。

如上图,自己领会。

nesterov的好处就是,当梯度方向快要改变的时候,它提前获得了该信息,从而减弱了这个过程,再次减少了无用的迭代。

1.3 Adagrad法

思路很简单,不同的参数是需要不同的学习率的,有的要慢慢学,有的要快快学,所以就给了一个权重咯,而且是用了历史上所有的梯度幅值。

1.4 Adadelta与Rmsprop

adagrad用了所有的梯度,问题也就来了,累加的梯度幅值是越来越大的。导致学习率前面的乘因子越来越小,后来就学不动了呀。

adadelta就只是动了一丢丢小心思,只累加了一个窗口的梯度,而且计算方法也更有效。

并且,将学习率用前一时刻参数的平方根来代替,最终更新算法变成了这样。

γ变成0.9,就是RMSprop方法了,这个方法在Hinton的课程中使用的,没有发表成论文,毕竟有adadelta了,没有发表必要。与adadelta另一个不同是还是需要学习率的,建议0.001

1.5 adam法

最后就是这个adam算法,作为最晚出现的,当然是集大成者。

adam对梯度的一阶和二阶都进行了估计与偏差修正,使用梯度的一阶矩估计和二阶矩估计来动态调整每个参数的学习率。

看出来了吧,与adadelta和rmsprop如出一辙,与momentum sgd也颇为相似。上面的式子根据梯度对参数更新的幅度进行了动态调整,所以adam对学习率没有那么敏感。

1.6 adamax

将adam使用的二阶矩变成更高阶,就成了adamax算法。

1.7 nadam法

nag加上adam,就成了nadam方法,即带有动量项的adam,所以形式也很简单,如下,可以将其分别与adam算法和nag算法的式子比较看看。

说了这么多,对上面各种方法从一个鞍点开始优化,表现如何的预期效果图如下。

理论上,就是上面这样的。文章作者会告诉你对于数据稀疏的问题,用自适应学习率算法就好了,而且使用人家推荐的参数就好。其中,adam会最佳。

03各种方法表现究竟如何

上面说了这么多理论,分析起来头头是道,各种改进版本似乎各个碾压SGD算法,然而根据笔者经验,仔细调优后的SGD算法绝对吊打其他算法

实验结果看下图,基础任务模型和数据集上次已经说过,此处不再赘述。

所有方法都采用作者们的默认配置,并且进行了比较,不好的结果就不拿出来了。

  • nesterov方法,与sgd算法同样的配置。
  • adam算法,m1=0.9,m2=0.999,lr=0.001。
  • rms算法,rms_decay=0.9,lr=0.001。
  • adagrad,adadelta学习率不敏感。
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-12-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 有三AI 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
批量计算
批量计算(BatchCompute,Batch)是为有大数据计算业务的企业、科研单位等提供高性价比且易用的计算服务。批量计算 Batch 可以根据用户提供的批处理规模,智能地管理作业和调动其所需的最佳资源。有了 Batch 的帮助,您可以将精力集中在如何分析和处理数据结果上。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档