深度学习之梯度更新的几种算法及其python实现【SGD,Momentum,Nesterov Momentum,AdaGrad,RMSProp,Adam】(无公式)

梯度更新的最终目的是为了“到山最底端”,梯度更新算法优化的目的是“最稳最快的 到山最底端”。

图1 梯度更新模型理解图

0.SGD

 SGD是非常好用,经典的梯度更新算法。算法思路比较简单,直接上代码。

def sgd(w, dw, config=None):
    """
    单纯的sgd实现

    """
    if config is None: config = {}
    config.setdefault('learning_rate', 1e-2)

    w -= config['learning_rate'] * dw
    return w, config

虽然sgd简单有效,但是也有问题,比如,sgd收敛的图像可能是下图这样的。

 

图1.1 SGD 优化loss时的loss值的轨迹图

 

翻译一下: 小人P在从R(小红点)点去往山的最低处F(笑脸)点时,最近的路线方向应该是R->F的直线方向,但是现在P听从SGD的建议,就往其他各种方向走来走去,但是大方向还是R->F的方向。

 解决办法?下面有。

1.Momentum

图1.2  上图中的轨迹  在各自方向上分解示意图

 通过图1.1可知,所有方向上的loss值都在来回震荡。如果给震荡一个“摩擦力”,那么慢慢的震荡就会终止。于是有了momentum。python代码是这样的:

def sgd_momentum(w, dw, config=None):
    """
    带动量的sgd实现
    """
    if config is None: config = {}
    learning_rate=config.setdefault('learning_rate', 1e-2)
    mu=config.setdefault('momentum', 0.9)
    v = config.get('velocity', np.zeros_like(w))

    next_w = None 
    v = mu * v - learning_rate * dw 
    next_w = w + v

    config['velocity'] = v

    return next_w, config

2.Nesterov Momentum 

这个是Momentum的升级版本,因为有了“预测“功能,所以损失函数收敛更快一些。

def sgd_nesterov_momentum(w, dw, config=None):

    if config is None:
        config = {}
    learning_rate = config.get('learning_rate', 1e-2)
    mu = config.get('momentum', 0.9)
    v = config.get('velocity', np.zeros_like(w))
 
    v_pre = v
    v = -dw * learning_rate + mu * v
    v = v + mu * (v - v_pre)
    next_w = w + v

    config['velocity'] = v
    return next_w,config

3. AdaGrad

def adagrad(w, dw, config=None):
   
    if config is None: config = {}
    learning_rate=config.get('learning_rate', 1e-2)
    epsilon=config.get('epsilon', 1e-8)
    config.setdefault('cache', np.zeros_like(w))

    cache=np.zeros_like(w)
    cache +=  dw ** 2
    next_w = w - learning_rate * dw / (np.sqrt(cache) + epsilon)

    config['cache'] = cache

    return next_w, config

 

翻译一下:相当于使得每一个方向的梯度都有了自己的learning_rate,而且会让梯度较大的方向上梯度更新越来越慢,梯度较小的方向的梯度更新也会越来越慢,但变慢的速率明显小于梯度大的方向上的。“稳当地下到山的最低处“。

效果:抑制大梯度方向上的更新,扩大小梯度方向上的更新,各个方向上的梯度更新趋向与一致。

缺点:因为cache越来越大,就会导致dw/( cache+epsilon)=0,梯度更新消失。

4.RMSProp

RMSProp是AdaGrad的升级版本,它使用衰减系数解决了Adagrad后面导致梯度更新变成0而导致学习终止的问题。

def rmsprop(w, dw, config=None):
    if config is None: config = {}
    learning_rate = config.get('learning_rate', 1e-2)
    decay_rate = config.get('decay_rate', 0.99)
    epsilon = config.get('epsilon', 1e-8)
    cache = config.get('cache', np.zeros_like(w))

    cache = decay_rate * cache + (1 - decay_rate) * dw ** 2
    next_w = w - learning_rate * dw / (np.sqrt(cache) + epsilon)
    config['cache'] = cache

    return next_w, config

5. Adam

Adam是集大成者,对于上面RMSProp和Nesterov Momentum取其精华。

def adam(w, dw, config=None):
    """
    config format:
    - learning_rate: Scalar learning rate.
    - beta1: Decay rate for moving average of first moment of gradient.
    - beta2: Decay rate for moving average of second moment of gradient.
    - epsilon: Small scalar used for smoothing to avoid dividing by zero.
    - m: Moving average of gradient.
    - v: Moving average of squared gradient.
    - t: Iteration number.
    """
    if config is None: config = {}
    config.setdefault('learning_rate', 1e-3)
    config.setdefault('beta1', 0.9)
    config.setdefault('beta2', 0.999)
    config.setdefault('epsilon', 1e-8)
    config.setdefault('m', np.zeros_like(w))
    config.setdefault('v', np.zeros_like(w))
    config.setdefault('t', 0)

    m = config['m']
    v = config['v']
    t = config['t'] + 1
    beta1 = config['beta1']
    beta2 = config['beta2']
    epsilon = config['epsilon']
    learning_rate = config['learning_rate']

    m = beta1 * m + (1 - beta1) * dw
    v = beta2 * v + (1 - beta2) * (dw ** 2)
    mb = m / (1 - beta1 ** t)
    vb = v / (1 - beta2 ** t)
    next_w = w - learning_rate * mb / (np.sqrt(vb) + epsilon)

    config['m'] = m
    config['v'] = v
    config['t'] = t

    return next_w, config

参考资料:

深度学习与计算机视觉 李飞飞 系列课程

  • 4
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值