http://blog.csdn.net/pipisorry/article/details/52135832

深度学习最优化算法

深度学习框架中常见的最优化方法。

tensorflow tf.keras.optimizers中的最优化方法及相关参数如下:

Adadelta、Adagrad、Adam、Adamax、Ftrl、Nadam、Optimizer、RMSprop、SGD

[https://www.tensorflow.org/api_docs/python/tf/keras/optimizers][tensorflow Optimizers]

pytorch中的最优化方法及相关参数如下:

SGD、Adagrad、Adadelta、RMSprop、Adam、AdamW、SparseAdam、Adamax、ASGD、LBFGS、Rprop

[https://pytorch.org/docs/stable/optim.html#]

基本算法

SGD 随机梯度下降(Stochastic Gradient Descent)

此处的SGD一般指mini-batch gradient descent。SGD就是每一次迭代计算mini-batch的梯度,然后对参数进行更新,是最常见的优化方法。即:

θ^t+1 = θ^t + delta(θ^t)

其中,η是学习率,g_t是梯度SGD完全依赖于当前batch的梯度。

缺点:SGD 的缺点在于收敛速度慢,可能在鞍点处震荡,并且如何合理的选择学习率是 SGD 的一大难点。

具体为1 选择合适的learning rate比较困难- 对所有的参数更新使用同样的learning rate。对于稀疏数据或者特征,有时我们可能想更新快一些(lz稀疏特征少,不平滑,影响更大),对于不经常出现的特征,对于常出现的特征更新慢一些,这时候SGD就不太能满足要求了。2 SGD容易收敛到局部最优,并且在某些情况下可能被困在鞍点【查阅论文发现,其实在合适的初始化和step size的情况下,鞍点的影响并没这么大】。

[最优化方法:梯度下降(批梯度下降和随机梯度下降)]

动量Momentum

如果把要优化的目标函数看成山谷的话,可以把要优化的参数看成滚下山的石头,参数随机化为一个随机数可以看做在山谷的某个位置以0速度开始往下滚。目标函数的梯度可以看做给石头施加的力,由力学定律知:F=ma,所以梯度(施加的力)与石头下滚的加速度成正比。因而,梯度直接影响速度,速度的累加得到石头的位置,对这个物理过程进行建模,可以得到参数更新过程为:

启发式算法:物体的动能 = 上一个时刻的动能 + 上一时刻的势能差(相对于单位质量),当前的速度取决于上一个时刻的速度和势能的改变量。由于有阻力和转换时的损失,所以两者都乘以一个系数。

这样在更新参数时,除了考虑到梯度以外,还考虑了上一个时刻参数的历史变更幅度。如果参数上一次更新幅度较大,并且梯度还不小(当前还远未到达谷底),那么再更新时也应该很猛烈(不一定更猛烈,因为还有系数嘛,但是正因为有系数,不好定,所以不怎么自适应)。

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

代码中v指代速度,其计算过程中有一个超参数momentum,称为动量(momentum)。虽然名字为动量,其物理意义更接近于摩擦,其可以降低速度值,降低了系统的动能,防止石头在山谷的最底部不能停止情况的发生(除非momentum为0,不然还是停不下来的,可能通过NAG解决部分问题,但是怎么说momentum和nag都容易在谷底震荡停不下来,可以看下面的“鞍点”和“损失平面等高线”动图)。

动量的取值范围通常为[0.5, 0.9, 0.95, 0.99],一种常见的做法是在迭代开始时将其设为0.5,在一定的迭代次数(epoch)后,将其值更新为0.99。

在实践中,一般采用SGD+momentum的配置,相比普通的SGD方法,这种配置通常能极大地加快收敛速度。faster convergence and reduced oscillation振荡。

 

NAG 加速梯度法(Nesterov accelerated gradient,NAG)

还是以小球的例子来看,momentum方式有个缺点就是在临近最优点附近控制不住速度(梯度为0了,但是moment不为0,还是有速度,还会运动;lz并且快到最优点时,势能系数*势能还是>0的,还会运动)。我们希望小球很smart,它可以预判后面的"地形",要是后面地形还是很陡,那就继续坚定不移的大胆走下去;不然的话咱就收敛点。当然,小球自己也不知道真正要走到哪里,所以这里(θ−γv_{t−1})作为近似下一位置

Hinton的slides是这样给出的:

momentum首先计算一个梯度(短的蓝色向量,势能),然后在加速更新梯度的方向进行一个大的跳跃(长的蓝色向量,动能);两个blue vectors分别理解为梯度和动能,两个向量和即为momentum方式的作用结果。

nesterov项首先在之前加速的梯度方向进行一个大的跳跃(棕色向量,动能),计算梯度然后进行校正(绿色梯向量,势能)(反着来也没问题);靠左边的brown vector是动能,可以看出它那条blue vector是平行的,但是它预测了下一阶段的梯度是red vector,因此向量和就是green vector,即NAG方式的作用结果。

-柚子皮-

其实,momentum项和nesterov项都是为了使梯度更新更加灵活,对不同情况有针对性。但是,人工设置一些学习率总还是有些生硬(之前所讲的方法中所有参数在更新时均使用同一个learning rate),接下来介绍几种自适应学习率的方法。

自适应学习率算法

Adagrad

Adagrad的每一个参数的每一次更新中都使用不同的learning rate,其实是对学习率进行了一个约束。即:

(学习率为,当前梯度g_t在“所有历史梯度和”中的占比,占比大则更新快。这里很明显可以想到,应该只看最近几个历史梯度和更好,所以有了后面的adadelta)

对迭代次数 t,基于每个参数之前计算的梯度值,将每个参数的学习率η按如下方式修正:

其中G是一个对角阵,对角线上的元素是从一开始到 t 时刻目标函数对于参数梯度的平方和;\epsilon是一个平滑项,以避免分母为 0 的情况,它的数量级通常在1e^-8;一般超参数 η 就取 0.01。有趣的是,如果不开方的话,这个算法的表现会变得很糟。

因为在其对角线上,含有过去目标函数对于参数 梯度的平方和,我们可以利用一个元素对元素的向量乘法,将我们的表达式向量化:

[深度解读最流行的优化算法:梯度下降]

特点:

  • 前期g_t较小的时候, regularizer较大,能够放大梯度;后期g_t较大的时候,regularizer较小,能够约束梯度;
  • 主要优势之一,是它不需要对每个学习率手工地调节。
  • 适合处理稀疏梯度。("It adapts the learning rate to the parameters, performing larger updates for infrequent and smaller updates for frequent parameters." 它对不同的参数调整学习率,具体而言,对低频出现的参数进行大的更新(lz因为低频参数少,累积和也小,分母小),对高频出现的参数进行小的更新。因此,他很适合于处理稀疏数据,对于稀疏数据上有着良好的表现。)(通常nlp模型的输入是非常稀疏的。对于包含几十万上百万词的词表,在训练的每个 Batch 中能出现的独立词数不超过几万个。也就是说,在每一轮梯度计算过程中,只有几万个词的 embedding 的梯度是非 0 的,其它 embedding 的梯度都是 0。)

缺点:

  • 由公式可以看出,仍依赖于人工设置一个全局学习率
  • η设置过大的话,会使regularizer过于敏感,对梯度的调节太大
  • 主要劣势,是它在分母上的 Gt 项中积累了平方梯度和,中后期将会越来越大(每次加入的项总是一个正值),使gradient->0,使得训练提前结束——此时,这个算法已经不能从数据中学到额外的信息。RMSprop 和 Adadelta 都是为了解决 Adagrad 学习率急剧下降问题的。

然而一般大多数自适应的learning rate都是有根据变化幅度而更改,并且具有逐渐收敛的特性。所以这种启发式方法仅是一种可行性方式,并不是唯一的,也绝不是最好的,把握其本质即可。

Adadelta

Adadelta是对Adagrad的扩展。

计算上的简化,Adagrad会累加之前所有的梯度平方,而Adadelta只累加固定大小w的项,并且也不直接存储这些项,仅仅是近似计算对应的平均值。即:

超参数设定值: 学习率 η 为 0.001。

梯度值累积值按如下的方式递归地定义:它被定义为关于过去梯度值的衰减均值(decade average),当前时间 t 的梯度均值  是基于过去梯度均值  和当前梯度值平方  的加权平均,其中 p 是类似上述动量项的权值。此时Adadelta其实还是依赖于全局学习率。

但后来的方案中,作者做了一定处理,经过近似牛顿迭代法之后:

(其中,超参数一般设定为 0.9;E代表求期望。pytorch当前的adadelta基本就是这个版本的。)

此时,可以看出Adadelta已经不用依赖于全局学习率了。

因为分母表达式的形式与梯度值的方均根(root mean squared,RMS)形式类似,因而我们使用相应的简写来替换:

特点:

  • 训练初中期,加速效果不错,很快
  • 训练后期,反复在局部最小值附近抖动
  • lz善于处理稀疏梯度(同adagrade)

RMSprop

RMSprop 是 Geoff Hinton 提出的一种自适应学习率方法,和Adadelta法几乎同时被发展出来,他们解决Adagrad激进的学习率缩减问题。可以算作Adadelta的一个特例,实际上, RMSprop和我们推导出的Adadelta法第一个更规则相同

当\rho=0.5时,就变为了求梯度平方和的平均数。

(注:Hinton建议设定 \rho 为0.9,对\eta  而言,0.001是一个较好的默认值。)

如果再求根的话,就变成了RMS(均方根)。

此时,这个RMS就可以作为学习率\eta的一个约束:

特点:

  • 其实RMSprop依然依赖于全局学习率
  • RMSprop算是Adagrad的一种发展,和Adadelta的变体,效果趋于二者之间
  • 适合处理非平稳目标- 对于RNN效果很好

万金油优化器:Adam 适应性动量估计法(Adaptive Moment Estimation)

Adam 优化器可以说是目前使用最广泛、收敛速度较快且收敛过程较稳定的优化器。Adam(Adaptive Moment Estimation)本质上是带有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。

除了像 Adadelta 和 RMSprop 一样存储了过去梯度平方 vt 的指数衰减平均值 ,也像 momentum 一样保持了过去梯度 mt 的指数衰减平均值:

m_t、n_t分别是对梯度的一阶矩估计和二阶矩估计,可以看作对期望E|g_t|,E|g_t^2|的估计。

\hat{m_t},\hat{n_t}是对m_t、n_t的校正,这样可以近似为对期望的无偏估计。如果 mt 和 vt 被初始化为 0 向量,那它们就会向 0 偏置,所以做了偏差校正, 通过计算偏差校正后的 mt 和 vt 来抵消这些偏差。

(后面的n超参可以不要)

Note:这个格式是不是非常像牛顿迭代法?牛顿迭代法就是二阶收敛的,快。[最优化方法:牛顿迭代法和拟牛顿迭代法]

可以看出,直接对梯度的矩估计对内存没有额外的要求,而且可以根据梯度进行动态调整,而对学习率形成一个动态约束,而且有明确的范围。

超参数设定值:

建议 u= 0.9,v = 0.999,ϵ = 10e−8。

Adam 中二阶矩估计时,一般对于梯度稀疏问题如 NLP 与 CV,建议将此值设大,接近 1,因此通常默认设置为 0.999,而robert中设为 0.98。(lz太稀疏时,当前点可能更偏异常,占比小点好)[RoBERTa:高级丹药炼制记录]

实践表明,Adam 比其他适应性学习方法效果要好。

特点:

  • 动量的引入可以防止训练时产生震荡
  • 结合了Adagrad善于处理稀疏梯度和RMSprop善于处理非平稳目标的优点
  • 对内存需求较小
  • 为不同的参数计算不同的自适应学习率
  • 也适用于大多非凸优化- 适用于大数据集和高维空间

问题

NLP 输入稀疏的特点与 Adam 使用动量计算梯度的特点相结合就引入了麻烦。每一轮更新参数时,只有极少数 embedding 的梯度是非 0 的,大部分 embedding 的梯度是 0 即上图公式中的 gt 是 0。但是,计算了动量之后,这些原本梯度都应该是 0 的 embedding 有了非零梯度 mt 用于梯度下降更新。想象一个极端的例子,“拉姆塞”这个词在一个 epoch 中只在第一个 batch 出现了,于是第一个 batch 计算了“拉姆塞”这个 embedding 的真实梯度 g0 用于更新参数,在以后的每个 batch 中虽然“拉姆塞”这个词没有出现过,Adam 都会计算它的动量梯度 mt,并用于更新“拉姆塞”这个 embedding,实际上方向与 g0 完全相同,只是每一轮做一次 β1 倍的衰减。这样的做法就相当于对这些出现次数较少的低频词的 embedding,每次梯度下降的等效学习率是非常大的,容易引起类似过拟合的问题。

解决方法

知道了问题的根节,解决方法就很简单了,每轮迭代只更新这个 batch 中出现过的词的 embedding 即可。TensorFlow 中可以使用 tf.contrib.opt.LazyAdamOptimizer,也可参考 https://www.zhihu.com/question/265357659/answer/580469438 的实现。

[NLP 神经网络训练慎用 Adam 优化器]

Adamax

Adamax是Adam的一种变体,此方法对学习率的上限提供了一个更简单的范围。公式上的变化如下:

可以看出,Adamax学习率的边界范围更简单。

Nadam

Nadam类似于带有Nesterov动量项的Adam。Much like Adam is essentially RMSprop with momentum, Nadam is Adam with Nesterov momentum.[https://www.tensorflow.org/api_docs/python/tf/keras/optimizers/Nadam]

公式如下:

可以看出,Nadam对学习率有了更强的约束,同时对梯度的更新也有更直接的影响。

一般而言,在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果。

-柚子皮-

不同最优化算法对比

经验之谈

  • 对于稀疏数据,尽量使用学习率可自适应的优化方法,不用手动调节,而且最好采用默认值。
  • 如果在意更快的收敛,并且需要训练较深较复杂的网络时,推荐使用学习率自适应的优化方法。
  • SGD通常训练时间更长,但是在好的初始化和学习率调度方案的情况下,结果更可靠。
  • Adadelta,RMSprop,Adam是比较相近的算法,在相似的情况下表现差不多。
  • 在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果。

学习速率 alpha

如果 alpha 设置得非常大,那么训练可能不会收敛,就直接发散了;
如果 alpha 设置的比较小,虽然可以收敛,但是训练时间可能无法接受;
如果 alpha 设置的稍微高一些,训练速度会很快,但是当接近最优点会发生震荡,甚至无法稳定。

不同学习速率的训练效果

理想的学习速率是:刚开始设置较大,有很快的收敛速度,然后慢慢衰减,保证稳定到达最优点。所以,前面的很多算法都是学习速率自适应的。

How to adjust learning rate

[https://pytorch.org/docs/stable/optim.html#how-to-adjust-learning-rate]

效果比较

几种最优化算法在“鞍点”(optimization on saddle point)和“损失平面等高线”(optimization on loss surface contours)上的表现:

上面两种情况都可以看出,Adagrad, Adadelta, RMSprop 几乎很快就找到了正确的方向并前进,收敛速度也相当快,而其它方法要么很慢(SGD),要么走了很多弯路才找到(Momentum和NAG)。由图可知自适应学习率方法即 Adagrad, Adadelta, RMSprop, Adam 在这种情景下会更合适而且收敛性更好。[(Image credit: Alec Radford)]

[深度学习优化器算法详解:梯度更新规则+缺点+如何选择]

from: http://blog.csdn.net/pipisorry/article/details/52135832

ref: [http://sebastianruder.com/optimizing-gradient-descent/]

[深度学习最全优化方法总结比较(SGD,Adagrad,Adadelta,Adam,Adamax,Nadam)]*

[David Silver 增强学习补充知识——梯度下降法]*

[深度解读最流行的优化算法:梯度下降]

[从 SGD 到 Adam —— 深度学习优化算法概览(一)]

最优化方法:深度学习最优化方法相关推荐

  1. 总结整理之深度学习中的最优化方法

    最优化问题在机器学习/深度学习中是经常遇到的问题,也是很重要的一个问题.学习算法的本质都是建立优化模型,通过最优化方法对目标函数(或损失函数)进行优化,从而训练出最好的模型.常见的最优化方法主要有以下 ...

  2. 各种优化算法公式快速回忆优化器-深度学习

    本文是Deep Learning 之 最优化方法系列文章的RMSProp方法.主要参考Deep Learning 一书. 整个优化系列文章列表: Deep Learning 之 最优化方法 Deep ...

  3. 22张精炼图笔记,深度学习专项学习必备

    作者 | DL&CV_study9 编辑 | Elle 来源 | CSDN 博客 本文为人工智能学习笔记记录. [深度学习基础篇] 一.深度学习基本概念 监督学习:所有输入数据都有确定的对应输 ...

  4. 22张图全解深度学习知识,建议收藏

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 转载于:Sophia知乎 https://zhuanlan.zhih ...

  5. 22张深度学习精炼图笔记总结

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:机器学习算法那些小事 最近在做笔记查阅内容,觉得这个总结 ...

  6. 《繁凡的深度学习笔记》前言、目录大纲 一文让你完全弄懂深度学习所有基础(DL笔记整理系列)

    <繁凡的深度学习笔记>前言.目录大纲 (DL笔记整理系列) 一文弄懂深度学习所有基础 ! 3043331995@qq.com https://fanfansann.blog.csdn.ne ...

  7. 神经网络和深度学习简史(三)

    一.可以做决定的神经网络   在了解了神经网络在无监督学习方面的应用以后,我们接下来将见到机器学习的第三部分:增强学习.尽管这个概念需要一个明确的数学表示进行描述,但我们可以先从简单理解一下:增强学习 ...

  8. 22张深度学习精炼图笔记总结(附原版下载)

    来源:迈微AI研习社本文约7800字,建议阅读10分钟 本文介绍了吴恩达在推特上展示了一份由 TessFerrandez 完成的深度学习专项课程信息图,这套信息图优美地记录了深度学习课程的知识与亮点. ...

  9. 《深度学习,统计学习,数学基础》人工智能算法工程师手册:程序员写的AI书,50 章一网打尽...

    来源:专知 本文约3400字,建议阅读10+分钟. 免费开源人工智能手册,带你快速上手写代码! [ 导读 ]市面上很多人工智能相关的书籍.大部分的书,面向小白,内容深度不够:小部分教材书或者科研书,内 ...

  10. 干货 | 吴恩达亲自为这份深度学习专项课程精炼图笔记点了赞!(附下载)

    来源:机器之心.AI有道 本文约7500字,建议阅读10+分钟. 本文整理了深度学习基础.卷积网络和循环网络的学习笔记,附下载哦~ [ 导读 ]吴恩达在推特上展示了一份由 TessFerrandez ...

最新文章

  1. 在react next 中使用rem_CSS中的rem:了解和使用rem单位
  2. 第一次使用Android Studio时你应该知道的一切配置(二):新建一个属于自己的工程并安装Genymotio...
  3. 简单了解一下函数模板
  4. 勒索病毒攻击应急防范
  5. 算法入门篇六 二叉树
  6. 电机的入门之路系列4--PWM控制直流电机
  7. 视频编码中为什么须要进行变换编码?
  8. Javascript 给页面元素添加事件函数探讨
  9. SPI协议学习Cubmx——读写Flash W25Q64
  10. java生成mib文件_Mib浏览器设计(附源码) | 学步园
  11. Horizon8桌面虚拟化(一)
  12. pytorch:自定义损失函数total variation loss
  13. TDS510-USB2.0驱动
  14. 草莓 西瓜 柚子……
  15. spring boot 2.5.5 reference chapter 5 生词
  16. 六轴机器人光机_六轴机器人主要用到哪些传感器?
  17. Games101-课程20笔记
  18. Spring boot Whitelabel Error Page解决方法(弱鸡方法,非全部适用)
  19. 通过实例学习Pytorch加载权重.load_state_dict()与保存权重.save()
  20. 实习html周日志,实习日志:最后的一周

热门文章

  1. 做好数据分析的关键是打好组合拳
  2. ProjectManage.rar 自动生成模板
  3. Codeforces 1174E Ehab and the Expected GCD Problem
  4. java获取当前项目或类路径
  5. Android学习(五)—— Android初级控件
  6. sql Server获取表中今天、昨天、本周、上周、本月、上月等数据
  7. unbuffered low level IO 和 bufferd IO
  8. http://Live.GIGA.NET.TW/FM917/
  9. EVC获取当前工作路径
  10. re.findall的正则参数为什么不能包含元组表达式()或竖线符号,先挖个坑