最优化方法:深度学习最优化方法

最优化方法:深度学习最优化方法http://blog.csdn.net/pipisorry/article/details/52135832深度学习最优化算法深度学习框架中常见的最优化方法,如tensorflow中的最优化方法及相关参数如下:tf.train.Optimizer tf.train.GradientDescentOptimizer tf.train.AdadeltaOptimizer tf.tr…_最优权重的深度学习算法

http://最优化方法:深度学习最优化方法

深度学习最优化算法

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

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

[torch.optim — PyTorch 2.0 documentation]

基本算法

权重衰减Weight decay

L2 regularization 和 Weight decay 只在SGD优化的情况下是等价的。
在这里插入图片描述

[权重衰减与 L2 正则化]

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})作为近似下一位置

vt=γvt−1+η∇θJ(θ−γvt−1).  θ=θ−vt.

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较小,能够约束梯度;
  • 主要优势之一,是它不需要对每个学习率手工地调节。
  • 自适应调整学习率。在SGD和MBSD中,对于每个权值(each weight)或者说对于每个参数(each parameter),学习率的值都是相同的。而AdaGrad在每个时间步长(every time step)对每个参数使用不同的学习率。因为它是在更新参数时会对每个参数的梯度进行平方求和,然后对每个参数的学习率进行加权,这样就可以针对每个参数自适应地调整学习率。
  • 自适应学习率和适合处理稀疏梯度。对不频繁的参数执行较大的更新,对频繁的参数执行较小的更新(It adapts the learning rate to the parameters, performing larger updates for infrequent and smaller updates for frequent parameters)。对于稠密(经常更新的、频繁的)参数,不希望被单个样本影响太大,希望学习率慢一些(稠密的参数分子分母加和项都会更多,而分母二次项加和更快,这样加和项越多,分子/分母更小);对于稀疏(偶尔更新的、不频繁的、只有少量的参数具有非零的梯度)参数,希望能从每个偶然出现的样本上多学一些,即学习率大一些。(通常nlp模型的输入是非常稀疏的。对于包含几十万上百万词的词表,在训练的每个 Batch 中能出现的独立词数不超过几万个。也就是说,在每一轮梯度计算过程中,只有几万个词的 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)形式类似,因而我们使用相应的简写来替换:

最优化方法:深度学习最优化方法

特点:

  • 训练初中期,加速效果不错,很快
  • 训练后期,反复在局部最小值附近抖动
  • 善于处理稀疏梯度(同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 来抵消这些偏差。

最优化方法:深度学习最优化方法

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,也可参考 在文本分类任务中,有哪些论文中很少提及却对性能有重要影响的tricks? – 知乎 的实现。

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

Adam 和其他优化器的对比:

最优化方法:深度学习最优化方法

AdamW

        Adam自动调整学习率,大幅提高了训练速度,也很少需要调整学习率,但是有相当多的资料报告Adam优化的最终精度略低于SGD。问题出在哪呢,其实Adam本身没有问题,问题在于目前大多数DL框架都是在优化器之前加上L2正则项来替代weight decay。

        Ilya Loshchilov 和 Frank Hutter 在他们的论文《Fixing Weight Decay Regularization in Adam》中指出,每个库在 Adam 上实施的权重衰减似乎都是错误的,并提出了一种简单的方法(他们称之为 AdamW)来修复它。这个优化器和 Adam 一样, 但是多了一些 weight decay regularization处理 (see “Decoupled Weight Decay Regularization” by Ilya Loshchilov and Frank Hutter)。应用:比如Huggingface的Trainer 的默认优化器时 AdamW。

        当你听到人们说 Adam 的泛化性能不如 SGD+Momentum 时,你基本上总会发现他们为自己的模型所选择的超参数不咋地。通常 Adam 需要的正则化比 SGD 多,因此在从 SGD 转向 Adam 时,确保调整正则化超参数。

Adam vs AdamW

在这里插入图片描述

在这里插入图片描述

Adam 和 AdamW 对比:

最优化方法:深度学习最优化方法

[AdamW优化器简单理解_Nick Blog的博客-CSDN博客]

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

[torch.optim — PyTorch 2.0 documentation]

效果比较

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

最优化方法:深度学习最优化方法最优化方法:深度学习最优化方法

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

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

from: 最优化方法:深度学习最优化方法_-柚子皮-的博客-CSDN博客

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

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

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

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

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

今天的文章最优化方法:深度学习最优化方法分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/58108.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注