优化器Optimizer

先说优化器的目标是啥,优化器的目标就是找到函数的最优解,例如现在有一个函数f(X),其中X=x1,x2....xn,如何找到这个函数的最小值,以及找到最小值时的X取值应该是啥,就是优化器要处理的问题。

常见的优化器

1. 梯度下降

梯度下降:GD/SGD/MiniBatch-SGD都是同一套,分别是全部数据、单条数据、若干条数据的梯度下降,是最基础的优化器,函数好比一座山(二元函数比较直观),现在站在山的某个某个位置,如果想要找整座山最低的那个山谷,要做的就两件事:

* 1. 方向:当前这个位置朝哪个方向走,可以以最快的速度下山

* 2. 速度/步长(单步距离):往这个方向走多远的距离比较合适(假设我是一个巨人,一步可以跨很远。。跨的太远有可能会把最低点跨过去)

SGD (Stochastic gradient descent), 随机梯度下降

为了解决方向和距离的问题,就引出梯度下降的方法

* 1. 方向:对于一个函数来说,导数的方向就是上山最快的方向,导数相反的方向就是下山最快的方向,所以这个时候求个导数就知道方向了。梯度下降说白了,就是对函数求导,直接拿梯度对应的方向用就行了。

* 2. 速度/步长(单步距离):这个就需要根据经验?来解决了,也就是梯度下降这个优化方法里唯一的一个参数:学学习率learning rate,也就是这个α

优缺点:

  • 优点:实现简单,易于理解。
  • 缺点:
    • 方向上:收敛速度慢(SGD可能产生振荡),另外容易陷入局部最优解
    • 速度上:学习率得自己定义,太大容易走偏(错过最优解),太小收敛速度太慢

因此接下来的所有优化基本都是在方向和速度两个方面进行的:

2. 动量优化器Momentum

严格来说应该叫gradient descent with momentum,带动量的梯度下降

虽然GD/SGD/MBSGD的大概原理类似,但是实际上还是有区别的,区别就在于,GD是真的全局的梯度,而SGD只是在那几个样本上的算出来的梯度,是一个估计值,这个估计值有可能和GroundTruth差不多也可能差很多。如图,左侧是理想的GD,右侧是可能的SGD,特别是在坡度比较明确和广阔的区域,就一直沿着某一方向走就好了,经常跳动很容易带来收敛速度的减缓。

    为了解决振荡的问题(即一个mini-batch的梯度可能偏差很大的问题),解决mini-batch和全量SGD的之间GAP的方式,当然就是扩大mini-batch的batch_size,显然batch_size越大,两者就倾向于越接近,振荡也就越小。 但是扩大batch_size很多时候是受到资源限制的,那怎么办呢?所以能不能将每一步的batch加起来,例如将上一步算的梯度和这一步算的梯度合起来求个平均,这个时候batch_size就相当于扩大了一倍。但是将上一步的梯度(甚至更往前的梯度)和这一步的梯度直接合到一块儿,会产生什么效果呢?

    首先,这意味着,多次累计的梯度的方向会产生趋势,而每一次的迭代,只是对趋势产生一部分的影响,而不是完全替换掉。

这个靠谱么?看两种情况:

* 1. 在离低谷比较远的时候:这种情况下,一般来说两次的梯度之间,方向上不应该差很多。所以引入前面的方向之后,会变的更平滑,缓解振荡,使得收敛速度更快

     * 作为一种特例,在平坦的区域(梯度为0不一定意味着是低谷)也有助于可以穿越过去

* 2. 在离低谷比较近的时候:如果没有动量,每一次迭代步骤本身都容易跳过最低谷,然后在最低谷附近来回振荡,而无法真正的达到。加上动量之后,方向应该不会乱跳了,基本上可以朝正确的最低谷的方向走(但有可能会因步数大跳过去)。 另外由于动量的存在,到达低谷之后,大概率还会再往前冲几步,如果这个谷是一个小的低谷,可能就能冲出去,从而摆脱当前的这个低谷(可能是局部最优解,当然也可能miss掉了一个最优解。。),如果是个大谷,可能冲不出去,过了若干步又回来了。。。

定义动量变量:              

                                        

   其中,g(t) 是当前时间步的梯度,v(t) 是当前的动量,β是动量因子,通常设为0.9。

更新参数

    其中,θ是模型参数,α是学习率,这一步和SGD是一样的,其实就是第一步里面,计算方向的这一步在计算梯度的基础上,又加了个历史梯度,而且一般历史梯度占的权重远大于新的梯度。。。

     还有有一点值得注意的是,梯度本身有个特点,就是在越陡峭的地方,梯度越大,从而使得下降的速度也会越快,因此利用累计梯度的话,会使得即使现在已经在不那么陡峭的地方了,但下降速度仍然很快,这一点有一个好处,就是这样也会使得下降更快(也就是说不光是方向上的稳定带来的收敛更快,在速度上带动量趋势也会加速收敛)。 但这也会带来一个弊端,就是真到了最低值的时候,其实应该慢点,否则有可能会因为跨的步子太大,从最低点越过去。。。

     另外,在参数量上,因为为每个参数都维护了一个自己的动量,因此额外引入了一倍的参数量,即如果模型参数量是N,则又引入了一个N的参数量。

3.内斯特洛夫加速梯度 Nesterov’s Accelerated Gradient

        这个方法名字比较多,有叫Nesterov Momentum等,这篇文章管这种方法叫做Nesterov Accelerated Gradient On The Importance Of Initialization And Momentum In Deep Learning 也简称NAG。

4. AdaGrad - Adaptive Gradient Algorithm

主要动机Why:主为了解决在机器学习和深度学习训练过程中,不同参数可能需要不同学习率的问题。

这里面应该是有两个假设:

1. 对梯度大的参数,需要相对小一点的学习率,因为太大的话会振荡?

2. 对梯度小的参数,需要相对大一点的学习率,因为太小会让收敛速度太慢?

但是问题是梯度大本来就表示可能离最优解还比较远,就得快点走啊。。。梯度小反过来。。当然Adagrad实际是用的累积梯度,不知道是不是累积的多就应该慢一点。。

所以如果两个参数,一个梯度很大,一个梯度很小,可能就分开走比较好。

核心思想和方法HOW:随着时间的推移

* 如果某个参数的梯度一直较大,注意是一直大,也就是梯度的累积比较大,那么它的学习率就让其减小得更快(因为担心走的太快,会振荡)

* 相反,如果某个参数的梯度较小,它的学习率减小得就慢。(因为担心走的太慢,收敛的太慢)

所以这里就是在原始的SGD梯度的基础上,除以了一个累加的梯度(ϵ是一个很小的数,如10−8,避免除以0),t表示更新的步数,i表示第i个参数,即每个参数有自己的梯度累积。gt​=∇θ​f(θt−1​)表示梯度

这个Gt就是所有历史梯度的平方和

优缺点:

  • 优点:可以让快的慢一点,慢的快一点,自适应的调学习率
  • 缺点:Gt是一个累加值,会越来越大,后面作为分母之后可能导致整个乘积项趋向于0,导致梯度消失,更新不动了。

另外需要注意的是,在参数量上,因为为每个参数都维护了一个自己的梯度累积值,因此额外引入了一倍的参数量,即如果模型参数量是N,则又引入了一个N的参数量。

5. RMSprop-Root Mean Square Propogation

动机:是由Geoffrey Hinton在2012年提出的一种自适应学习率的方法,它是AdaGrad的一个变体,主要为了解决AdaGrad在训练后期学习率下降过快的问题

方法:主要是引入了指数移动平均(exponential moving average, EMA)来估计梯度的平方根,而不是直接累积所有的历史梯度平方,从而提供了更加稳定的梯度尺度估计,避免了学习率过度减小

将Adagrad里的梯度累积公式,变成:

 

相当于在右侧两个加数之前,分别乘上了一个因子,累积的梯度一般占主导ρ一般设置为0.9

但事实上,因为分别乘了两个和为1的因子,已经不能算是严格意义上的梯度累积了。举个例子,如果更新了10次,每次梯度都是一样的话,每次得到的累积值其实也都是一样的。。。并没有真的累积起来,而如果最新的一次梯度很大,求得的累计值也会比上次大,如果最新的一次梯度很小,求得的累计值也会比上次小。。。

而如果不用历史累计值的话,那不如直接把公式第一个加数舍去,直接用最新这一步的偏导,扔到公式里,变成偏导的导数,再乘以偏导,结果变成了1(也可能是-1)。。。这样相当于梯度就算了个+/-号,具体的梯度大小没关系了。。直接变成以斜率更新。。。。

实际上现在这个公式,如果当前梯度和之前梯度”累积值”一样的话,就是这个效果,就算不一样,那也是当前梯度值大一点,那就以learning rate乘上一个大于1的数更新,当前梯度小一点及时learning rate乘上一个小于1的数更新。  也就是说这个时候梯度大的还是快一些,但是收到了一定程度的抑制,反之亦然。

6. Adam-Adaptive Moment Estimation

这个基本上可以理解为2.Momentum和5.RMSprop的结合版

对梯度(方向):

对学习率(步长):

上面这两个公式从形式上看很像,实际上一个是对梯度的一阶矩估计,另一个是对梯度的二阶矩估计,当然这两者的作用不太一样,梯度那个是直接替换掉SGD里的梯度,作为新的梯度直接使用;而二阶那个,是作为一个因子,开根号之后,用学习率除以这个值得到的新值。

但是这个地方有一个小问题,就是初始化的时候m0和v0都是0,会导致一开始算出来的初始值都非常小。。所以每一步算完m和v之后会除以一个比较大的数做一个扩大,分别是:

这里面β1和β2都是t次幂,步数多了之后这两个数都会趋近于0,分母就趋近于1,接近于不用优化了。

然后最终得到一个新的值,这个值从形式上看和前面的RMSprop等几个差不多。

7. AdamW - Adam with decoupled weight decay

AdamW其实就是在损失函数引入了L2正则项之后,对原始的Adam做了一下优化。

为了方式模型过拟合,通常会引入L2正则项,抑制权重:

这样形式的损失函数,用Adam进行优化就是下面红色框里的形式

AdamW对Adam进行的改造,本质上就是说在梯度下降的时候,只对原始的Loss函数进行方向和步长上的调整,而额外引入的L2正则项,按照正常的SGD的逻辑迭代,不加入到Adam的一阶矩、二阶矩的调整当中。

AdamW某种程度上是对含L2正则项的损失函数,在用Adam优化器优化的时候进行的一种修正,保证L2损失函数的本身可以高效和准确的发挥自身作用。

Backup:

在深度学习中,优化器(Optimizer)是用于更新模型参数以最小化损失函数的算法。以下是一些最常见的优化器:

  1. SGD (Stochastic Gradient Descent):

    • 这是最基本的优化器,逐个样本更新参数。
    • 优点:实现简单,易于理解。
    • 缺点:收敛速度慢,可能在局部最优解附近震荡。
  2. Momentum:

    • 是对SGD的一种改进,使用历史梯度来加速当前梯度的更新。
    • 优点:可有效减少震荡,加快收敛。
    • 缺点:需要选择合适的动量超参数。
  3. Nesterov Accelerated Gradient (NAG):

    • 在Momentum的基础上,使用了梯度的更新进行“预见”来调整参数。
    • 优点:更进一步地减少震荡,提供更快的收敛速度。
  4. AdaGrad:

    • 根据参数的历史梯度自适应调整学习率,适合处理稀疏数据。
    • 优点:对于频繁更新的参数,它会降低学习率,反之则增加。
    • 缺点:学习率随着时间的推移而单调减小,可能导致训练过早停止。
  5. RMSprop:

    • 结合了AdaGrad的优点,使用指数衰减移动平均来计算梯度的平方。
    • 优点:解决了AdaGrad学习率过早降低的问题。
    • 常用于循环神经网络(RNN)等问题。
  6. Adam (Adaptive Moment Estimation):

    • 结合了Momentum和RMSprop的优点,维护一阶矩(均值)和二阶矩(方差)的移动平均。
    • 优点:能够自适应调整学习率,适合大规模数据和高维空间。
    • 是目前使用最广泛的优化器之一。
  7. AdamW:

    • 是Adam的变体,增加了权重衰减(L2正则化)的实现方式,以改善正则化效果。
    • 优点:在训练过程中保持学习率的稳定性和正则化能力。
  8. Nadam:

    • 是Nesterov动量和Adam的结合,尝试获得两者的优点。
    • 优点:能更快地收敛,适用于许多任务。
  9. FTRL (Follow The Regularized Leader):

    • 在大规模在线学习中常用,适合处理稀疏数据。

不同的任务、数据集和模型架构可能会对优化器的选择产生影响。在实践中,找到最适合特定问题的优化器通常需要实验和调优。

Reference:

https://zhuanlan.zhihu.com/p/627756271

AdamW:https://arxiv.org/pdf/1711.05101

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值