1.梯度降落算法(优化器)

1.1 原理解释

如果咱们定义了一个机器学习模型,比方一个三层的神经网络,那么就须要使得这个模型可能尽可能拟合所提供的训练数据。然而咱们如何评估模型对于数据的拟合是否足够呢?那就须要应用相应的指标来评估它的拟合水平,所应用到的函数就称为损失函数(Loss Function),当损失函数值降落,咱们就认为模型在拟合的路上又后退了一步。最终模型对训练数据集拟合的最好的状况是在损失函数值最小的时候,在指定数据集上时,为损失函数的平均值最小的时候。

因为咱们个别状况下很难间接准确地计算失去当模型的参数为何值时,损失函数最小,所以,咱们能够通过让参数在损失函数的“场”中,向着损失函数值减小的方向挪动,最终在收敛的时候,失去一个极小值的近似解。为了让损失函数的数值降落,那么就须要应用优化算法进行优化,其中,损失函数值降落最快的方向称为负梯度方向,所应用的算法称为梯度降落法,即最速降落法(steepest descent)。以后,简直所有的机器学习优化算法都是基于梯度降落的算法。

总结的来讲优化器(例如梯度降落法)就是在深度学习反向流传过程中,指引损失函数(指标函数)的各个参数往正确的方向更新适合的大小,使得更新后的各个参数让损失函数(指标函数)值一直迫近全局最小。

举一个简略例子

优化问题能够看做是咱们站在山上的某个地位(以后的参数信息),想要以最佳的路线去到山下(最长处)。首先,直观的办法就是环顾四周,找到下山最快的方向走一步,而后再次环顾四周,找到最快的方向,直到下山——这样的办法便是奢侈的梯度降落——以后的海拔是咱们的指标(损失)函数值,而咱们在每一步找到的方向便是函数梯度的反方向(梯度是函数回升最快的方向,所以梯度的反方向就是函数降落最快的方向)。

应用梯度降落进行优化,是简直所有优化器的核心思想。当咱们下山时,有两个方面是咱们最关怀的:

  • 首先是优化方向,决定“后退的方向是否正确”,在优化器中反映为梯度或动量。
  • 其次是步长,决定“每一步迈多远”,在优化器中反映为学习率。

所有优化器都在关注这两个方面,但同时也有一些其余问题,比方应该在哪里登程、路线谬误如何解决……这是一些最新的优化器关注的方向。

1.2 梯度降落法作用

梯度降落是机器学习中常见优化算法之一,梯度降落法有以下几个作用:

  1. 梯度降落是迭代法的一种,能够用于求解最小二乘问题(线性和非线性都能够),其余的问题,只有损失函数可导也能够应用梯度降落,比方穿插熵损失等等。
  2. 在求解机器学习算法的模型参数,即无约束优化问题时,次要有梯度降落法,牛顿法等。
  3. 在求解损失函数的最小值时,能够通过梯度降落法来一步步的迭代求解,失去最小化的损失函数和模型参数值。
  4. 如果咱们须要求解损失函数的最大值,可通过梯度回升法来迭代。梯度降落法和梯度回升法可互相转换。

2.深度学习支流模型与梯度降落

下表列举了自然语言解决(NLP),计算机视觉(CV),举荐零碎(Recommendation System,RS),强化学习(Reinforcement Learning,RL)这四个方向的支流模型应用优化器的状况,能够看出在NLP畛域AdamW(AdamWeightDecayOptimizer)应用比拟广泛,CV畛域SGD和momentum应用比拟广泛,举荐畛域比拟杂,强化学习畛域Adam应用比拟广泛。

根据计算指标函数梯度应用的数据量的不同,有三种梯度降落的变体,即批量梯度降落,随机梯度降落,Mini-batch梯度降落。依据数据量的大小,在参数更新的准确性和执行更新所需工夫之间做了一个衡量。

2.1 批量梯度降落,BGD

规范的梯度降落,即批量梯度降落(batch gradient descent,BGD),在整个训练集上计算损失函数对于参数的梯度

$\theta=\theta-\eta\nabla_\theta J(\theta)$

其中是模型的参数,是学习率,$∇J()$为损失函数对参数的导数。因为为了一次参数更新咱们须要在整个训练集上计算梯度,导致 BGD 可能会十分慢,而且在训练集太大而不能全副载入内存的时候会很辣手。BGD 也不容许咱们在线更新模型参数,即实时减少新的训练样本。

BGD 对于凸误差曲面(convex error surface)保障收敛到全局最长处,而对于非凸曲面(non-convex surface)则是部分最长处

2.2 随机梯度降落,SGD

随机梯度降落( stotastic gradient descent, SGD )则是每次应用一个训练样本$x_i$和标签$y_i$进行一次参数更新。

$\theta=\theta-\eta\cdot\nabla_\theta J(\theta;x^i;y^i)$

其中是模型的参数,是学习率,∇J()为损失函数对参数的导数。BGD 对于大数据集来说执行了很多冗余的计算,因为在每一次参数更新前都要计算很多类似样本的梯度。SGD 通过一次执行一次更解决了这种冗余。因而通常 SGD 的速度会十分快而且能够被用于在线学习。SGD以高方差的特点进行间断参数更新,导致指标函数重大震荡.

BGD 可能收敛到(部分)最长处,然而 SGD 的震荡特点导致其能够跳到新的潜在的可能更好的部分最长处。曾经有钻研显示当咱们缓缓的升高学习率时,SGD 领有和 BGD 一样的收敛性能,对于非凸和凸曲面简直同样可能达到部分或者全局最长处。

2.3 Mini-batch梯度降落,MBGD

Mini-batch gradient descent( mini-batch gradient descent, MBGD )则是在下面两种办法中采取了一个折中的方法:每次从训练集中取出batchsize个样本作为一个mini-batch,以此来进行一次参数更新

$\theta=\theta-\eta\cdot\nabla_\theta J(\theta;x^{(i:i+n);y^{(i:i+n)}})$

其中
是模型的参数,是学习率,$\nabla_{\theta}J(\theta;x^{(i:i+n);y^{(i:i+n)}}$为损失函数对参数的导数,n为Mini-bach的大小(batch size)。 batch size越大,批次越少,训练工夫会更快一点,但可能造成数据的很大节约;而batch size越小,对数据的利用越充沛,节约的数据量越少,但批次会很大,训练会更耗时

2.3.1 长处

  • 减小参数更新的方差,这样能够有更稳固的收敛。
  • 利用当初最先进的深度学习库对矩阵运算进行了高度优化的特点,这样能够使得计算 mini-batch 的梯度更高效。

样本数目较大的话,个别的mini-batch大小为64到512,思考到电脑内存设置和应用的形式,如果mini-batch大小是2的n次方,代码会运行地快一些,64就是2的6次方,以此类推,128是2的7次方,256是2的8次方,512是2的9次方。所以我常常把mini-batch大小设成2的次方。

MBGD 是训练神经网络时的罕用办法,而且通常即便实际上应用的是 MBGD,也会应用 SGD 这个词来代替。

2.3.2MBGD面临的问题

  • 学习率抉择

抉择一个好的学习率是十分艰难的。太小的学习率导致收敛十分迟缓,而太大的学习率则会妨碍收敛,导致损失函数在最长处左近震荡甚至发散。雷同的学习率被利用到所有参数更新中。如果咱们的数据比拟稠密,特色有十分多不同的频率,那么此时咱们可能并不想要以雷同的水平更新他们,反而是对更少呈现的特色给予更大的更新。为了能在学习期间主动调节学习率,依据先前定义好的一个规定来减小学习率,或者两次迭代之间指标函数的扭转低于一个阈值的时候。然而这些规定和阈值也是须要在训练前定义好的,所以也不能做到自适应数据的特点

上图中,学习率设置过大,导致指标函数值沿着 “山谷” 四周大幅震荡,可能永远都达到不了最小值。

  • 鞍点

对于神经网络来说,另一个最小化高度非凸误差函数的要害挑战是防止陷入他们大量的次部分最长处(suboptimal)。事实上艰难来自于鞍点而不是部分最长处,即损失函数在该点的一个维度上是上坡(slopes up),而在另一个维度上是下坡(slopes down)。这些鞍点通常被一个具备雷同误差的立体所突围,这使得对于 SGD 来说十分难于逃脱,因为在各个维度上梯度都趋近于 0 。

如图,鞍点得名于它的形态相似于马鞍。只管它在 x 方向上是一个最小值点,然而它在另一个方向上是部分最大值点,并且,如果它沿着 x 方向变得更平坦的话,梯度降落会在 x 轴振荡并且不能持续依据 y 轴降落,这就会给咱们一种曾经收敛到最小值点的错觉。

3. Momentum

为了克制SGD的震荡,SGDM认为梯度降落过程能够退出惯性。能够简略了解为:当咱们将一个小球从山上滚下来时,没有阻力的话,它的动量会越来越大,然而如果遇到了阻力,速度就会变小。SGDM全称是SGD with momentum,在SGD根底上引入了一阶动量:

$v_t=\gamma v_{t-1}+\eta\nabla J(\theta)$

SGD-M参数更新公式如下,其中是学习率,∇J()是以后参数的梯度

$\theta=\theta-v_t$

一阶动量是各个时刻梯度方向的指数挪动平均值,也就是说,t时刻的降落方向,不仅由以后点的梯度方向决定,而且由此前累积的降落方向决定。的经验值为0.9,这就意味着降落方向次要是此前累积的降落方向,并稍微偏差以后时刻的降落方向。设想高速公路上汽车转弯,在高速向前的同时稍微偏差,急转弯可是要出事的。 SGD 震荡且迟缓的沿着沟壑的下坡方向朝着部分最长处后退,如下图:

momentum可能减速SGD办法,并且可能缩小震荡,如下图:

特点

  • 退出了动量因素,SGD-M缓解了SGD在部分最长处梯度为0,无奈继续更新的问题和振荡幅度过大的问题。
  • 当部分沟壑比拟深,动量加持用完了,仍然会困在部分最优里来回振荡

4.NAG

SGD 还有一个问题是困在部分最优的沟壑外面震荡。设想一下你走到一个盆地,周围都是略高的小山,你感觉没有下坡的方向,那就只能待在这里了。可是如果你爬上洼地,就会发现里面的世界还很广大。因而,咱们不能停留在以后地位去察看将来的方向,而要向前一步、多看一步、看远一些。

NAG全称Nesterov Accelerated Gradient,是在SGD、SGD-M的根底上的进一步改良,咱们晓得在时刻t的次要降落方向是由累积动量决定的,本人的梯度方向说了也不算,那与其看以后梯度方向,不如先看看如果跟着累积动量走了一步,那个时候再怎么走。因而,NAG不计算以后地位的梯度方向,而是计算如果依照累积动量走了一步,那个时候的降落方向:

$v_t=\gamma v_{t-1}+\eta\nabla_\theta J(\theta-\gamma v_{t-1})$

NAG参数更新公式如下,其中是学习率, $\nabla_\theta J(\theta-\gamma v_{t-1})$是以后参数的梯度

$\theta=\theta-v_t$

而后用下一个点的梯度方向,与历史累积动量相结合,计算以后时刻的累积动量。

如上图,动量法首先计算以后梯度(图中的小蓝色向量),而后在更新累积梯度(updated accumulated gradient)方向上大幅度的跳跃(图中的大蓝色向量)。与此不同的是,NAG 首先在先前的累积梯度(previous accumulated gradient)方向上进行大幅度的跳跃(图中的棕色向量),评估这个梯度并做一下修改(图中的红色向量),这就形成一次残缺的 NAG 更新(图中的绿色向量)。这种预期更新避免咱们进行的太快,也带来了更高的相应速度,这在一些工作中十分无效的晋升了 RNN 的性能。

特点

  • 有利于跳出以后部分最优的沟壑,寻找新的最优值,但收敛速度慢

5.AdaGrad,自适应学习率开启

SGD系列的都没有用到二阶动量。二阶动量的呈现,才意味着“自适应学习率”优化算法时代的到来。SGD及其变种以同样的学习率更新每个参数,但深度神经网络往往蕴含大量的参数,这些参数并不是总会用失去。对于常常更新的参数,咱们曾经积攒了大量对于它的常识,不心愿被单个样本影响太大,心愿学习速率慢一些;对于偶然更新的参数,咱们理解的信息太少,心愿能从每个偶尔呈现的样本身上多学一些,即学习速率大一些。因而,Adagrad 十分实用于稠密数据。

Dean 等人发现 Adagrad 可能大幅提高 SGD 的鲁棒性,并在 Google 用其训练大规模神经网络,这其中就包含 在 YouTube 中学习辨认猫。除此之外,Pennington 等人用 Adagrad 来训练 GloVe 词嵌入,因为常见的词汇须要比常见词更大的更新。

AdaGrad算法就是将每一个参数的每一次迭代的梯度取平方累加后在开方,用全局学习率除以这个数,作为学习率的动静更新。对于不同的参数动静的采取不同的学习率,让指标函数更快的收敛。为了简洁,咱们用$g_t$来示意t时刻的梯度,$g_{t,i}$就是指标函数的偏导数:

$g_{t,i}=\nabla_{\theta}J(\theta_{t,i})$

SGD在在每个时刻t对参数$i$的更新为:

$\theta_{t+1,i}=\theta_{t,i}-\eta\cdot g_{t,i}$

Adagrad批改了t时刻对于每个参数$i$的学习率:

$\theta_{t+1,i}=\theta_{t,i}-\dfrac{\eta}{\sqrt{G_{t,ii}+\epsilon}}\cdot g_{t,i}$

其中$G_t∈R_d×d$是对角矩阵,其中每一个对角元素i,i是$i$在时刻t的梯度平方和,个别为了防止分母为0,会在分母上加一个小的平滑项,用符号示意,通常为10−8 左右。因而$\sqrt{G_{t}+\epsilon}$恒大于0,而且参数更新越频繁,二阶动量越大,学习率就越小。乏味的是,如果去掉开方操作,算法性能会大幅降落

  • 长处

    • 在稠密数据场景下体现十分好
    • 此前的SGD及其变体的优化器次要聚焦在优化梯度后退的方向上,而AdaGrad首次应用二阶动量来关注学习率(步长),开启了自适应学习率算法的里程。大多数实现应用一个默认值 0.01 。
  • 毛病

    • $\sqrt{G_{t}+\epsilon}$是枯燥递增的,会使得学习率枯燥递加至0,可能会使得训练过程提前结束,即使后续还有数据也无奈学到必要的常识。

6. AdaDelta

因为AdaGrad枯燥递加的学习率变动过于激进,思考一个扭转二阶动量计算方法的策略:不累积全副历史梯度,而只关注过来一段时间窗口的降落梯度。这也就是AdaDelta名称中Delta的来历。Adadelta是 Adagrad 的扩大,旨在帮忙缓解后者学习率枯燥降落的问题

  • 长处

    • 防止了二阶动量继续累积、导致训练过程提前结束的问题了

7.RMSProp(2012)

RMSProp 算法(Hinton,2012)批改 AdaGrad 以在非凸状况下体现更好,它扭转梯度累积为指数加权的挪动平均值,从而抛弃间隔较远的历史梯度信息。RMSProp 与 Adadelta 的挪动均值更新形式十分相似

$E[g^2]_{t}=0.9E[g^2]_{t-1}+0.1g_{t}^{2}$

RMSProp参数更新公式如下,其中是学习率, $g_t$是以后参数的梯度

$\theta_{t+1}=\theta_t-\dfrac{\eta}{\sqrt{E[g^2]_t+\epsilon}}g_t$

RMSprop将学习速率除以梯度平方的指数衰减平均值。Hinton倡议设置为0.9,默认学习率为0.001

8.Adam

Adam最开始是由 OpenAI 的 Diederik Kingma 和多伦多大学的 Jimmy Ba提出的。Adam应用动量和自适应学习率来放慢收敛速度。SGD-M在SGD根底上减少了一阶动量,AdaGrad和AdaDelta在SGD根底上减少了二阶动量(二阶矩预计)。把一阶动量和二阶动量都用起来,就是Adam了——Adaptive + Momentum。

  • 长处

    • 通过一阶动量和二阶动量,无效管制学习率步长和梯度方向,避免梯度的振荡和在鞍点的静止
    • 实现简略,计算高效,对内存需要少
    • 参数的更新不受梯度的伸缩变换影响
    • 超参数具备很好的解释性,且通常无需调整或仅需很少的微调
    • 更新的步长可能被限度在大抵的范畴内(初始学习率)
    • 能天然地实现步长退火过程(主动调整学习率)
    • 很适宜利用于大规模的数据及参数的场景
    • 实用于不稳固指标函数
    • 实用于梯度稠密或梯度存在很大噪声的问题
    • Adam在很多状况下算作默认工作性能比拟优良的优化器。
  • 毛病
  • 可能不收敛:二阶动量是固定工夫窗口内的累积,随着工夫窗口的变动,遇到的数据可能发生巨变,使得$V_t$可能会时大时小,不是枯燥变动。这就可能在训练前期引起学习率的震荡,导致模型无奈收敛。

$v_t=max(\beta_2\cdot v_{t-1}+(1-\beta_2)g_t^2,v_{t-1})\quad\text{}$

修改的办法。因为Adam中的学习率次要是由二阶动量管制的,为了保障算法的收敛,能够对二阶动量的变动进行管制,防止高低稳定。

  • 可能错过全局最优解:自适应学习率算法可能会对后期呈现的特色过拟合,前期才呈现的特色很难纠正后期的拟合成果。前期Adam的学习率太低,影响了无效的收敛

9.Adamax

10.Nadam

Adam能够被看作是交融了RMSProp和momentum,RMSprop 奉献了历史平方梯度的指数衰减的平均值$v_t$,而动量则负责历史梯度的指数衰减平均值$m_t$,Nadam在Adam的根底上退出了一阶动量的累积,即Nesterov + Adam = Nadam,为了把NAG融入到Adam中,咱们须要批改momentum的项$m_t$

11.AMSGrad(2018)

AMSGrad在ICLR 2018年被提出来,并取得了最佳论文。AMSGrad是一个随机梯度降落优化办法,它试图解决基于Adam的优化器的收敛问题。AMSGrad应用最大化过来平方梯度vt
来更新参数,而不是应用指数均匀,这样就升高了指数衰减均匀,造成重要历史信息疾速失落的影响。

$\begin{array}{c}m_t=\beta_1m_{t-1}+(1-\beta_1)g_t\\ v_t=\beta_2v_{t-1}+(1-\beta_2)g_t^2\end{array}$

下面的两个公式跟Adam是一样的,求的是一阶矩和二阶矩,$g_t$是以后参数的梯度,$1$为一阶矩预计的指数衰减率,$2$是二阶矩预计的指数衰减率,前者管制一阶矩预计,后者管制二阶矩预计。

$\hat{v}_t=max(\hat{v}_{t-1},v_t)$

上式求过来最大的平方梯度$v^t$,参数的更新公式如下:

$\theta_{t+1}=\theta_t-\dfrac{\eta}{\sqrt{\hat{v}_t}+\epsilon}m_t$

从下面的公式能够看出,参数更新公式与Adam没有啥区别,然而求$v^t$有区别。AMSGRAD不减少步长,防止了ADAM和RMSPROP算法的缺点。

12.AdaBound

AdaBound算法训练速度比肩Adam,性能媲美SGD。SGD当初前期调优时还是常常应用到,但SGD的问题是后期收敛速度慢。SGD后期收敛慢的起因: SGD在更新参数时对各个维度上梯度的放缩是统一的,并且在训练数据分布极不均很时训练成果很差。而因为收敛慢的问题应运而生的自适应优化算法Adam、AdaGrad、RMSprop 等,但这些自适应的优化算法尽管能够在训练晚期展现出疾速的收敛速度,但其在测试集上的体现却会很快陷入停滞,并最终被 SGD 超过。

13.AdamW

L2 正则化是缩小过拟合的经典办法,它会向损失函数增加由模型所有权重的平方和组成的惩办项,并乘上特定的超参数以管制惩办力度。退出L2正则当前,损失函数就变为:

从下面的公式能够看出,AdamW实质上就是在损失函数外面退出了L2正则项,而后计算梯度和更新参数的时候都须要思考这个正则项。AdamW应用在hugging face版的transformer中,BERT,XLNET,ELECTRA等支流的NLP模型,都是用了AdamW优化器

14.RAdam

RAdam(Rectified Adam)是Adam优化器的一个变体,它引入了一项来纠正自适应学习率的方差,试图解决Adam的收敛性差的问题。

15.Lookahead

Lookahead是一种梯度降落优化器,它迭代的更新两个权重汇合,”fast”和”slow”。直观地说,该算法通过向前看由另一个优化器生成的疾速权值序列来抉择搜寻方向。 梯度降落的时候,走几步会退回来查看是否方向正确。防止忽然掉入部分最低点。

Lookahead的算法形容如下:

  • Fast weights

它是由内循环优化器(inner-loop)生成的k次序列权重;这里的优化器就是原有的优化器,如SGD,Adam等均可;其优化办法与原优化器并没有区别,例如给定优化器A,指标函数L,以后训练mini-batch样本d,这里会将该轮循环的k次权重,用序列都保留下来。

  • Slow Weights:

在每轮内循环完结后,依据本轮的k次权重,计算等到Slow Weights;这里采纳的是指数挪动均匀(exponential moving average, EMA)算法来计算,最终模型应用的参数也是慢更新(Slow Weights)那一套,因而快更新(Fast Weights)相当于做了一系列试验,而后慢更新再依据试验后果选一个比拟好的方向,这有点相似 Nesterov Momentum 的思维。