优化算法

优化算法


转自:https://zhuanlan.zhihu.com/p/32230623


主要框架

待优化参数: w w
目标函数: f(x)
初始学习率: α α
而后,开始进行迭代优化。
在每个epoch t:

  1. 计算目标函数关于当前参数的梯度:
    gt=f(wt) g t = ∇ f ( w t )
  2. 根据历史梯度计算一阶动量和二阶动量:
    mt=ϕ(g1,g2,,gt);Vt=ψ(g1,g2,,gt) m t = ϕ ( g 1 , g 2 , ⋯ , g t ) ; V t = ψ ( g 1 , g 2 , ⋯ , g t ) ,
  3. 计算当前时刻的下降梯度:
    ηt=αVtmt η t = α V t m t
  4. 根据下降梯度进行更新:
    wt+1=wtηt w t + 1 = w t − η t

SGD

SGD没有动量概念,即

mt=gt m t = g t

Vt=I2 V t = I 2

代入步骤3,可以看到下降梯度就是最简单的
ηt=αgt η t = α ⋅ g t

SGD最大的缺点是下降速度慢,而且可能会在沟壑的两边持续震荡,停留在一个局部最优点。

待优化参数: w w
目标函数: f(x)
初始学习率: α α
而后,开始进行迭代优化。

For epoch t:

  1. 计算目标函数关于当前参数的梯度:
    gt=f(wt) g t = ∇ f ( w t )
  2. 根据历史梯度计算一阶动量:
    mt=gt m t = g t
  3. 计算当前时刻的下降梯度:
    ηt=αgt η t = α g t
  4. 根据下降梯度进行更新:
    wt+1=wtηt w t + 1 = w t − η t

SGD with Momentum

为了抑制SGD的震荡,SGDM认为梯度下降过程可以加入惯性。下坡的时候,如果发现是陡坡,那就利用惯性跑的快一些。SGDM全称是SGD with momentum,在SGD基础上引入了一阶动量:

mt=β1mt1+(1β1)gt m t = β 1 ⋅ m t − 1 + ( 1 − β 1 ) ⋅ g t

一阶动量是各个时刻梯度方向的指数移动平均值,约等于最近 1/(1β1) 1 / ( 1 − β 1 ) 个时刻的梯度向量和的平均值。

也就是说, t t 时刻的下降方向,不仅由当前点的梯度方向决定,而且由此前累积的下降方向决定。 β1 的经验值为0.9,这就意味着下降方向主要是此前累积的下降方向,并略微偏向当前时刻的下降方向。想象高速公路上汽车转弯,在高速向前的同时略微偏向,急转弯可是要出事的。

待优化参数: w w
目标函数: f(x)
初始学习率: α α , 动量参数 β1 β 1
而后,开始进行迭代优化。

For epoch t:

  1. 计算目标函数关于当前参数的梯度:
    gt=f(wt) g t = ∇ f ( w t )
  2. 根据历史梯度计算一阶动量:
    mt=β1mt1+(1β1)gt m t = β 1 ⋅ m t − 1 + ( 1 − β 1 ) ⋅ g t
  3. 计算当前时刻的下降梯度:
    ηt=αgt η t = α g t
  4. 根据下降梯度进行更新:
    wt+1=wtηt w t + 1 = w t − η t

AdaGrad

二阶动量的出现,才意味着“自适应学习率”优化算法时代的到来。SGD及其变种以同样的学习率更新每个参数,但深度神经网络往往包含大量的参数,这些参数并不是总会用得到(想想大规模的embedding)。对于经常更新的参数,我们已经积累了大量关于它的知识,不希望被单个样本影响太大,希望学习速率慢一些;对于偶尔更新的参数,我们了解的信息太少,希望能从每个偶然出现的样本身上多学一些,即学习速率大一些。

怎么样去度量历史更新频率呢?那就是二阶动量——该维度上,迄今为止所有梯度值的平方和:

Vt=τ=1tg2τ V t = ∑ τ = 1 t g τ 2

我们再回顾一下步骤3中的下降梯度:

ηt=mtαVt η t = m t α V t

可以看出,此时实质上的学习率由 α α 变成了 αVt α V t 。 一般为了避免分母为0,会在分母上加一个小的平滑项。因此 Vt V t 是恒大于0的,而且参数更新越频繁,二阶动量越大,学习率就越小。

这一方法在稀疏数据场景下表现非常好。但也存在一些问题:因为 Vt V t 是单调递增的,会使得学习率单调递减至0,可能会使得训练过程提前结束,即便后续还有数据也无法学到必要的知识。

待优化参数: w w
目标函数: f(x)
初始学习率: α α
而后,开始进行迭代优化。

For epoch t:

  1. 计算目标函数关于当前参数的梯度:
    gt=f(wt) g t = ∇ f ( w t )
  2. 根据历史梯度计算一阶动量,二阶动量:
    mt=ϕ(g1,g2,,gt)SGDMomentum m t = ϕ ( g 1 , g 2 , ⋯ , g t ) ( 可 取 S G D 或 M o m e n t u m 等 )

    Vt=τ=1tg2t V t = ∑ τ = 1 t g t 2
  3. 计算当前时刻的下降梯度:
    ηt=mtαVt η t = m t α V t
  4. 根据下降梯度进行更新:
    wt+1=wtηt w t + 1 = w t − η t

SGD with Nesterov Acceleration

SGD 还有一个问题是困在局部最优的沟壑里面震荡。想象一下你走到一个盆地,四周都是略高的小山,你觉得没有下坡的方向,那就只能待在这里了。可是如果你爬上高地,就会发现外面的世界还很广阔。因此,我们不能停留在当前位置去观察未来的方向,而要向前一步、多看一步、看远一些。

NAG全称Nesterov Accelerated Gradient,是在SGD、SGD-M的基础上的进一步改进,改进点在于步骤1。我们知道在时刻t的主要下降方向是由累积动量决定的,自己的梯度方向说了也不算,那与其看当前梯度方向,不如先看看如果跟着累积动量走了一步,那个时候再怎么走。因此,NAG在步骤1,不计算当前位置的梯度方向,而是计算如果按照累积动量走了一步,那个时候的下降方向:

gt=f(wtmt1αVt1) g t = ∇ f ( w t − m t − 1 α V t − 1 )

然后用下一个点的梯度方向,与历史累积动量相结合,计算步骤2中当前时刻的累积动量。

待优化参数: w w
目标函数: f(x)
初始学习率: α α
而后,开始进行迭代优化。

For epoch t:

  1. 计算目标函数关于当前参数的梯度:
    gt=f(wtmt1αVt1) g t = ∇ f ( w t − m t − 1 α V t − 1 )
  2. 根据历史梯度计算一阶动量,二阶动量:
    mt=ϕ(g1,g2,,gt),SGDMomentum m t = ϕ ( g 1 , g 2 , ⋯ , g t ) , ( 可 取 S G D 或 M o m e n t u m 等 )

    Vt=ψ(g1,g2,,gt),(AdaGrad) V t = ψ ( g 1 , g 2 , ⋯ , g t ) , ( 可 取 A d a G r a d 等 )
  3. 计算当前时刻的下降梯度:
    ηt=mtαVt η t = m t α V t
  4. 根据下降梯度进行更新:
    wt+1=wtηt w t + 1 = w t − η t

AdaDelta / RMSProp

由于AdaGrad单调递减的学习率变化过于激进,我们考虑一个改变二阶动量计算方法的策略:不累积全部历史梯度,而只关注过去一段时间窗口的下降梯度。这也就是AdaDelta名称中Delta的来历。

修改的思路很简单。前面我们讲到,指数移动平均值大约就是过去一段时间的平均值,因此我们用这一方法来计算二阶累积动量:

Vt=β2Vt1+(1β2)g2t V t = β 2 ⋅ V t − 1 + ( 1 − β 2 ) ⋅ g t 2

这就避免了二阶动量持续累积、导致训练过程提前结束的问题了。

待优化参数: w w
目标函数: f(x)
初始学习率: α α β2 β 2
而后,开始进行迭代优化。

For epoch t:

  1. 计算目标函数关于当前参数的梯度:
    gt=f(wt) g t = ∇ f ( w t )
  2. 根据历史梯度计算一阶动量,二阶动量:
    mt=ϕ(g1,g2,,gt),SGDMomentum m t = ϕ ( g 1 , g 2 , ⋯ , g t ) , ( 可 取 S G D 或 M o m e n t u m 等 )

    Vt=β2Vt1+(1β2)g2t V t = β 2 ⋅ V t − 1 + ( 1 − β 2 ) ⋅ g t 2
  3. 计算当前时刻的下降梯度:
    ηt=mtαVt η t = m t α V t
  4. 根据下降梯度进行更新:
    wt+1=wtηt w t + 1 = w t − η t

Adam

谈到这里,Adam和Nadam的出现就很自然而然了——它们是前述方法的集大成者。我们看到,SGD-M在SGD基础上增加了一阶动量,AdaGrad和AdaDelta在SGD基础上增加了二阶动量。把一阶动量和二阶动量都用起来,就是Adam了——Adaptive + Momentum。
SGD的一阶动量:

mt=β1mt1+(1β1)gt m t = β 1 ⋅ m t − 1 + ( 1 − β 1 ) ⋅ g t

加上AdaDelta的二阶动量:

Vt=β2Vt1+(1β2)g2t V t = β 2 ⋅ V t − 1 + ( 1 − β 2 ) ⋅ g t 2

优化算法里最常见的两个超参数 β1 β 1 β2 β 2 就都在这里了,前者控制一阶动量,后者控制二阶动量。

待优化参数: w w
目标函数: f(x)
初始学习率: α α β1 β 1 β2 β 2
而后,开始进行迭代优化。

For epoch t:

  1. 计算目标函数关于当前参数的梯度:
    gt=f(wt) g t = ∇ f ( w t )
  2. 根据历史梯度计算一阶动量,二阶动量:
    mt=β1mt1+(1β1)gt m t = β 1 ⋅ m t − 1 + ( 1 − β 1 ) ⋅ g t

    Vt=β2Vt1+(1β2)g2t V t = β 2 ⋅ V t − 1 + ( 1 − β 2 ) ⋅ g t 2
  3. 计算当前时刻的下降梯度:
    ηt=mtαVt η t = m t α V t
  4. 根据下降梯度进行更新:
    wt+1=wtηt w t + 1 = w t − η t

Nadam

最后是Nadam。我们说Adam是集大成者,但它居然遗漏了Nesterov,这还能忍?必须给它加上,按照NAG的步骤1:

gt=f(wtαmt1/Vt) g t = ∇ f ( w t − α ⋅ m t − 1 / V t )

这就是Nesterov + Adam = Nadam了。

待优化参数: w w
目标函数: f(x)
初始学习率: α α β1 β 1 β2 β 2
而后,开始进行迭代优化。

For epoch t:

  1. 计算目标函数关于当前参数的梯度:
    gt=f(wtαmt1/Vt) g t = ∇ f ( w t − α ⋅ m t − 1 / V t )
  2. 根据历史梯度计算一阶动量,二阶动量:
    mt=β1mt1+(1β1)gt m t = β 1 ⋅ m t − 1 + ( 1 − β 1 ) ⋅ g t

    Vt=β2Vt1+(1β2)g2t V t = β 2 ⋅ V t − 1 + ( 1 − β 2 ) ⋅ g t 2
  3. 计算当前时刻的下降梯度:
    ηt=mtαVt η t = m t α V t
  4. 根据下降梯度进行更新:
    wt+1=wtηt w t + 1 = w t − η t
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值