zoukankan      html  css  js  c++  java
  • 神经网络优化器

    首先梯度下降算法一共有三个变形:BGD, SGD , MBGD, 这三种形式的区别就是取决于我们用多少数据来计算目标函数的梯度.

    1.BGD(Batch gradient descent

      BGD 采用整个训练集的数据来执行一次更新: 

    关于深度学习优化器 optimizer 的选择,你需要了解这些

      for i in range(nb_epochs ):
        params_grad = evaluate_gradient(loss_function , data , params)
        params = params  - learning_rate * params_grad

      缺点是:

        (1).Batch gradient descent is guaranteed to converge to the global minimum for convex error surfaces and to a local minimum for non-convex surfaces(凸函数可以保证到全局最优,非凸函数可能收敛到局部最优).

        (2).As we need to calculate the gradients for the whole dataset to perform just one update, batch gradient descent can be very slow and is intractable for datasets that do not fit in memory. Batch gradient descent also does not allow us to update our model online , i.e. with new examples on-the-fly(需要计算整个数据集来更新一次,批处理梯度下降可能非常慢,对于非常大量的、不可能一次放入内存的数据集来说非常棘手。另外不可在线计算)

    2.SGD(Stochastic gradient descent)

      SGD随机在整个数据集中抽取样本,对每个样本进行一次梯度更新。

      for i in range(nb_epochs ):
        np.random.shuffle(data)
        for  example  in data:
          params_grad = evaluate_gradient(loss_function , example , params)
          params = params  - learning_rate * params_grad
       改进之后的优点:(1)对大数据集来说,每次更新只用对其中的一个样本做计算,使得计算速度加快。

               (2)可以进行在线计算。

               (3)可能会使其跳到一个较好的局部最优

       缺点:SGD执行频繁的高方差更新,导致目标函数波动较大,如图所示。对于非凸函数,也可能收敛到局部最优,由于SGD的震荡,可能会使其跳到一个较好的局部最优。增加了收敛的复杂度。

         Batch gradient descent performs redundant computations for large datasets, as it recomputes gradients for similar examples before each parameter update. SGD does away with this redundancy by performing one update at a time. It is therefore usually much faster and can also be used to learn online. SGD performs frequent updates with a high variance that cause the objective function to fluctuate heavily as in Figure

     3.MBGD (Mini-batch gradient descent)

      MBGD每次在数据集中抽取一小批样本执行一次更新。

      for i in range ( nb_epochs ):
        np. random . shuffle ( data )
        for batch in get_batches (data , batch_size =50):
          params_grad = evaluate_gradient ( loss_function , batch , params )
          params = params - learning_rate * params_grad

      改进之后的优点:(1)减少了参数更新时的方差,使得收敛更平稳

              (2)能以较快的速度进行更新

    一般batch_size取50-256.

     经过两次改进,MBGD已经可以得到一个较好的优化效果,但是他还存在一下问题:

      (1)选择一个好的学习率很困难,太小可能导致收敛非常缓慢,太大可能导致来回震荡,甚至发散。可以再训练过程中动态的调整学习率,例如使用模拟退火算法,即根据预先定义的时间表或在不同时期目标的变化低于阈值时降低学习速率。然而,这些调度和阈值必须预先定义,因此不能适应所有数据集的特征。

      (2)如果数据是稀松的,这个方法将会将所有的特征做同样程度的更新,但是我们希望对较少出现的特征执行较大的更新。例如一个数据集有10万张兔子的照片,只有1000张猫的照片,两个特征的数据大小相差很大,如果执行同样程度的更新,那么会使得预测极不准确。

      (3)可能会陷入局部最优,这种困难实际上可能并非来自局部极小值,而是来自鞍点,即一维向上和另一维向下倾斜的点。这些鞍点通常被相同误差的平台包围,这使得SGD很难逃脱,因为所有维度的梯度都接近于零。

     

    为了解决以上的三个问题,下面介绍几种优化器。

    4.Momentum

      SGD可能会产生来回震荡,使得不能快速达到最优,如下图:

      新的梯度更新规则:,加入‘阻力项’,如果阻力同梯度下降的方向相同,那就让它更快的下降,若果不同,让它慢一点下降,这样不会轻易地错过最优值,使得收敛速度加快并减小震荡。(一般动量项γ取0.9).

      可以继续改进的是:这种情况相当于小球从山上滚下来时是在盲目地沿着坡滚,如果它能具备一些先知,例如快要上坡时,就知道需要减速了的话,适应性会更好。下面的Nesterov accelerated gradient方法的梯度更新规则就考虑到了这点。

    5.Nesterov accelerated gradient

      梯度更新规则:,利用θ−γv_t−1 来近似当做参数下一步会变成的值,有前瞻性,这样小球就会知道在即将要上坡的时候减速,在持续下坡的时候加速,小球变得更加聪明了。(一般动量项γ取0.9).

    两种方法的效果图如下:

    蓝色的为Momentum方法,首先计算当前的梯度,然后与动量因子项相加,如上图,他会有一个较大的累计梯度更新。

    绿色的为Nesterov accelerated gradient方法,它会有一个衡量的过程,预防走的太快。使得梯度更新始终保持在较为合理的范围。

    更为直观的解释为,一个小球沿着下坡路走,第一个方法是先计算当前的坡度,如果当前的坡度跟上一时刻的坡度方向一样,那么小球就加速下降(动量累积的过程),如果两次计算的坡度方向不同,就减速(动量减少的过程)

    第二个方法是利用上一坡度的值预测到当前的坡度,然后在做动量累积,或者动量减少。小球如果知道下一坡度更陡,动量累积的就快,知道下面平缓一下,动量累积的就慢,知道要上坡了,动量减少。

     

    知道这里我们把数据集中的所有特征看做是同样的重要,对其更新程度一样,但是这样对数据稀松的数据集的预测带来了很大不确定性,为此,下面介绍几种算法。可以根据参数的重要性而对不同的参数进行不同程度的更新。

    (6)Adagrad

      算法思想:Adagrad[8]是一种基于梯度的优化算法,它的作用是:根据参数调整学习速率,对于不频繁的参数执行较大的更新,对于频繁的参数执行较小的更新。此方法可以极大的提高SGD的鲁棒性。

      梯度更新规则:

      其中 Gt 是个对角矩阵, (i,i) 元素就是 t 时刻参数 θ_i 的梯度平方和。Adagrad的主要优点之一是它消除了手动调整学习速率的需要。大多数实现都使用默认值0.01。

      Adagrad的主要缺点是它在分母上累积平方梯度:因为每增加一项都是正的,所以在训练过程中累积和不断增长。这反过来又会导致学习速率减小,最终变得无穷小,这时算法就无法获得额外的知识。下面的算法旨在解决这个缺陷。

    (7)Adadelta

      adadelta分母根号里面采用,将梯度的和定义为所有过去平方梯度的衰减平均值。t 时刻的依赖于前一时刻的平均和当前的梯度。

    ——>。另外还将学习率设置成了RMS[Δθ],这样我们可以不用设置学习率了。梯度更新规则:。(γ 一般设定为 0.9

    (8)RMSprop

      RMSprop 与 Adadelta 的第一种形式相同。(Hinton 建议设定 γ 为 0.9, 学习率 η 为 0.001。)

    (9)Adam

      自适应矩估计(Adam)[10]是计算每个参数的自适应学习速率的另一种方法。除了像Adadelta和RMSprop那样存储过去梯度的指数衰减平均值vt外,Adam还保存了过去梯度mt的指数衰减平均值,类似于动量:

    mt和vt分别是梯度的第一个矩(平均值)和第二个矩(无中心方差)的估计值,因此该方法得名。当mt和vt初始化为0的向量时,Adam的作者观察到它们偏向于0,尤其是在初始时间步长时,尤其是在衰减率很小时(β1,β2趋近于1)

     通过计算校正过的第一和第二矩估计值来抵消这些偏差:

    使用这些来更新参数,就像我们在Adadelta和RMSprop中看到的那样,它们生成Adam更新规则:建议 β1 = 0.9,β2 = 0.999,ϵ = 10e−8。

    (10)AdaMax

      梯度更新规则:,通常取:

    (11)Nadam

      梯度更新规则:

      

    下面来比较一下各个算法的效果

    上面面两幅图对所提出的优化算法的优化行为提供了一些直观的认识。在图4a中,我们看到它们在损失表面的轮廓上的路径(Beale函数)。它们都是从同一个点开始,经过不同的路径到达最小值。请注意,Adagrad、Adadelta和RMSprop立即朝正确的方向前进,并以同样快的速度聚合,而动量和NAG则偏离了轨道,这让人想起一个球滚下山的画面。然而,NAG能够更快地纠正它的路线,因为它的反应能力增加了,它向前看,并朝着最小值前进。图4b显示了算法在鞍点处的行为,即一个维度的斜率为正,另一个维度的斜率为负,这给SGD带来了困难,如前所述。请注意,SGD、动量和NAG发现很难打破对称,尽管后两者最终设法逃脱鞍点,而Adagrad、RMSprop和Adadelta则迅速地沿着负斜率下降,Adadelta带头冲锋。

    我们可以看到,自适应学习率方法,即Adagrad、Adadelta、RMSprop和Adam是最合适的,它们为这些场景提供了最好的收敛性。

     如何选取

    如果输入数据是稀疏的,那么可以使用自适应学习率方法之一来获得最好的结果。另外一个好处是,不需要调整学习率,使用默认值可能会获得最佳的结果。总之,RMSprop是Adagrad的一个扩展,它处理的是学习速率急剧下降的问题。它与Adadelta相同,只是Adadelta在分子更新规则中使用了参数更新的RMS。最后,Adam为RMSprop添加了偏差修正和动量。到目前为止,RMSprop、Adadelta和Adam是非常相似的算法,它们在类似的环境中都能很好地工作。Kingma等人的[10]研究表明,当梯度变得稀疏时,其偏置校正帮助Adam在优化结束时略微优于RMSprop。到目前为止,Adam可能是最好的选择。有趣的是,许多最近的论文使用 vanillaSGD没有动量和一个简单的学习率退火时间表。正如所示,SGD通常能够找到最小值,但它可能比某些优化器花费的时间长得多,更依赖于健壮的初始化和退火调度,并且可能会卡在鞍点而不是局部最小值上。因此,如果关心快速收敛和训练一个深度或复杂的神经网络,你应该选择一种自适应学习速率方法。

    参考:An overview of gradient descent optimization algorithms

      

     

  • 相关阅读:
    X-CTF(REVERSE入门) python-trade
    X-CTF(REVERSE入门) getit
    X-CTF(REVERSE入门) csaw2013reversing2
    X-CTF(REVERSE入门) no-strings-attached
    X-CTF(REVERSE入门) insanity
    X-CTF(REVERSE入门) logmein
    面向对象编程的七大设计原则
    二叉树的性质
    Visual Studio 2017 WPF应用(.Net Freamwork)断点调试不命中的解决方法
    C语言读写文件
  • 原文地址:https://www.cnblogs.com/54hys/p/10224214.html
Copyright © 2011-2022 走看看