常用的几款优化器

https://blog.csdn.net/u010899985/article/details/81836299
https://www.jianshu.com/p/ee39eca29117


  1. 梯度下降算法(Gradient Descent Optimization)

根据计算目标函数J(θ)采用数据量的大小,梯度下降算法又可以分为批量梯度下降算法(Batch Gradient Descent),随机梯度下降算法(Stochastic GradientDescent)和小批量梯度下降算法(Mini-batch Gradient Descent)。

  • 批量梯度下降算法:
    针对的是整个数据集,通过对所有的样本的计算来求解梯度的方向。
    优点:全局最优解;易于并行实现;
    缺点:当样本数据很多时,计算量开销大,计算速度慢

  • 随机梯度下降算法:只通过一个随机选取的数据(xn,yn) 来获取“梯度”,以此对w进行更新。这种优化方法叫做随机梯度下降。其收敛速度会快一些,但是有可能出现目标函数值震荡现象,因为高频率的参数更新导致了高方差。
    每个数据都计算算一下损失函数,然后求梯度更新参数。
    优点:计算速度快
    缺点:收敛性能不好

  • 小批量梯度下降算法(通常选用该方案),是折中方案,J(θ)选取训练集中一个小批量样本计算,这样可以保证训练过程更稳定,而且采用批量训练方法也可以利用矩阵计算的优势。这是目前最常用的梯度下降算法。

常见问题:
  • 选择合适的learning rate比较困难,如果对所有的参数更新使用同样的learning rate。对于稀疏数据或者特征,有时我们可能想对不经常出现的特征更新快一些,对于常出现的特征更新慢一些,这时候SGD就不太能满足要求了。
常用的几款优化器_第1张图片
image.png
  • SGD容易收敛到局部最优,并且在某些情况下可能被困在鞍点,容易产生局部最优,而不能达到全局最优。

  1. Momentum(动量)
    https://zhuanlan.zhihu.com/p/21475880

SGD更新方向完全依赖于当前的batch,因而其更新十分不稳定,每次迭代计算的梯度含有比较大的噪音。

  • 滑板问题:
常用的几款优化器_第2张图片
image.png

下图为函数,可知最小值位于(0,0)点,从(150,75)这个点开始下降。

# 梯度函数,返回x,y方向上的导数。
def g(x):
    return np.array([2 * x[0], 100 * x[1]])
def momentum(x_start, step, g, discount = 0.7):   
    x = np.array(x_start, dtype='float64')
    pre_grad = np.zeros_like(x)
    for i in range(50):
        grad = g(x)
        pre_grad = pre_grad * discount + grad * step
        # 部分(discount)保留之前的惯性pre_grad
        x -= pre_grad
        
        print '[ Epoch {0} ] grad = {1}, x = {2}'.format(i, grad, x)
        if abs(sum(grad)) < 1e-6:
            break;
    return x
常用的几款优化器_第3张图片
朴素SGD.png

当使用了动量后,实际上沿-y和+y方向的两个力可以相互抵消,而-x方向的力则会一直加强,这样滑板少年会在y方向打转,但是y方向的力量会越来越小,但是他在-x方向的速度会比之前快不少。但还是在y轴方向浪费了不少时间,产生了强烈的震荡抖动。

常用的几款优化器_第4张图片
Momentum.png

  1. Nesterov Accelerated Gradient(2012年)

该优化器相对于Momentum,唯一不同的是计算反向梯度的时机。Momentum计算的是当前位置的反向梯度,Nesterov Momentum 计算的是按照上次更新方向走一小步后的反向梯度。

def g(x):
    return np.array([2 * x[0], 100 * x[1]])
def momentum(x_start, step, g, discount = 0.7):   
    x = np.array(x_start, dtype='float64')
    pre_grad = np.zeros_like(x)
    for i in range(50):
        grad = g(x+pre_grad*discount)
        # 提前跨一步,但是是用于提取它的梯度
        pre_grad = pre_grad * discount + grad * step
        # 部分(discount)保留之前的惯性pre_grad
        x -= pre_grad
        
        print '[ Epoch {0} ] grad = {1}, x = {2}'.format(i, grad, x)
        if abs(sum(grad)) < 1e-6:
            break;
    return x
常用的几款优化器_第5张图片
image.png

因为momentum的值更小,所以可以减弱震荡,避免跨过头太多导致剧烈的震荡。

常用的几款优化器_第6张图片
Nesterov.png


  1. AdaGrad算法(2011年)

增加了一个学习率递减系数。在训练迭代过程,初期步长大后期步长小。由于比较陡的方向梯度比较大,其学习速率将衰减得更快,这有利于参数沿着更接近坡底的方向移动,从而加速收敛。

注: 通常为,是为了防止分母的为 0,为步长(学习率)

注:如果第t次训练有m个样本,则取

  • 特点:
    (1)适合处理稀疏梯度。
  • 缺点:
    (1)由公式可以看出,仍依赖于人工设置一个全局学习率。
    (2)分母上梯度平方的累加将会越来越大,会造成训练提前结束。
    (3)深度学习中,深度过深时会造成训练提前结束。

  1. RMSProp算法

衰减系数累积了所有更新步骤中的梯度,我们可能更希望考察最近几步中的梯度来决定衰减系数。所以我们添加了一个衰减系数,使距离远的更新影响更弱,距离近的更新影响大。这就是RMSProp。

衰减系数ρ
步长ε
第t轮迭代的梯度g^t


  1. 自适应矩估计(adaptive moment estimation):
    https://blog.csdn.net/qq_41747565/article/details/86100697
    https://blog.csdn.net/fengchao03/article/details/78208414
常用的几款优化器_第7张图片
详细版.png

  • 偏置修正:因为初始化为0,为了能快点进入工作状态,给每个都除以校正初始化偏差。

t从0开始,m0,n0初始化为0,和是对和的无偏估计, gt指Θt在该处目标函数的梯度值,u一般取0.9, v一般取0.999, ε一般取。是步长。


各种算法的选择:
https://blog.csdn.net/weixin_40170902/article/details/80092628

  1. 对于稀疏数据,优先选择学习速率自适应的算法如RMSprop和Adam算法,而且最好采用默认值,大部分情况下其效果是较好的
    SGD通常训练时间更长,容易陷入鞍点,但是在好的初始化和学习率调度方案的情况下,结果更可靠。
  2. 如果要求更快的收敛,并且较深较复杂的网络时,推荐使用学习率自适应的优化方法。例如对于RNN之类的网络结构,Adam速度快,效果好,而对于CNN之类的网络结构,SGD +momentum 的更新方法要更好(常见国际顶尖期刊常见优化方法).
  3. Adadelta,RMSprop,Adam是比较相近的算法,在相似的情况下表现差不多。
  4. 在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果。
  5. 特别注意学习速率的问题。学习速率设置得非常大,那么训练可能不会收敛,就直接发散了;如果设置的比较小,虽然可以收敛,但是训练时间可能无法接受。理想的学习速率是:刚开始设置较大,有很快的收敛速度,然后慢慢衰减,保证稳定到达最优
  6. 其实还有很多方面会影响梯度下降算法,如梯度的消失与爆炸,梯度下降算法目前无法保证全局收敛还将是一个持续性的数学难题。
  7. RMSprop适合处理非平稳目标 - 对于RNN效果很好

Momentum还有NAG这种动量算法容易在梯度翻转的时候因为惯性作用偏离目标航线,但是一但找到了正确的行驶方向就能跑得 比自适应的快很多。自适应相对比较稳妥

常用的几款优化器_第8张图片
三处低地的曲面.gif
常用的几款优化器_第9张图片
鞍点曲面.gif
常用的几款优化器_第10张图片
峡谷地貌.gif

你可能感兴趣的:(常用的几款优化器)