梯度下降优化方法总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_14845119/article/details/86491430

随机梯度下降stochastic gradient descent algorithm(SGD):

包括GD(batchsize=all),SGD(batchsize=1),mini-batch SGD(batchsize=mini-batch)

其中GD训练过程中可以不调整学习率,保持学习率不变训练到收敛

SGD,mini-batch SGD训练过程中必须保证不断减少学习率

当训练数据较大,GD每次迭代计算开销较大,因而mini-batch SGD更受青睐。

缺点:

  1. 学习率的选择比较困难,学习率过大过小都有问题。合适的学习率要靠实验来调。
  2. 收敛速度慢

代码:

# Mini-batch stochastic gradient descent.
def sgd(params, lr, batch_size):
    for param in params:
        param[:] = param - lr * param.grad / batch_size

SGD+momentum

论文:On the Momentum Term in Gradient Descent Learning Algorithms

其中a一般取值为0.5,0.9,0.99分别代表最大速度的2倍,10倍,100倍(放大倍数使用1/(1-a)计算)。和学习率一样,超参数a在训练中也随着时间不断变大。但是调整参数a没有调整学习率重要。

优点:

  1. 加速了SGD的收敛速度

缺点:

  1. 引入另外2个超参数a,v
  2. 所有的训练参数使用同样大小的学习率

代码:

def sgd_momentum(params, vs, lr, mom, batch_size):
    for param, v in zip(params, vs):
        v[:] = mom * v + lr * param.grad / batch_size
        param[:] = param - v

 

Adagrad:

论文:Adaptive Subgradient Methods for Online Learning and Stochastic Optimization∗

Adagrad在sgd的基础上,分母除以了一个二阶矩累加梯度的平方和,然后开根号。Adagrad是一个在迭代过程中不断自我调整学习率,并让模型参数中每个元素都使用不同学习率的优化算法。

优点:

  1. 相比sgd+momentum,减少了参数量,去掉了a,v
  2. 不同的训练参数使用不同大小的学习率
  3. 在某些深度学习模型上效果不错,但不是全部

缺点:

(1)从训练开始累积的梯度平方会导致有效学习率过早和过量减少。由于分母不断的累加,如果刚开始累加的太多,会使得学习率下降的太快,导致训练到后期学习率很小,无法逃离局部极小值点。

代码:

# Adagrad.
def adagrad(params, sqrs, lr, batch_size):
    eps_stable = 1e-7
    for param, sqr in zip(params, sqrs):
        g = param.grad / batch_size
        sqr[:] += nd.square(g)
        div = lr * g / nd.sqrt(sqr + eps_stable)
        param[:] -= div

 

RMSprop:

未发表论文,Hinton课堂上提出,Lecture 6a Overview of mini-batch gradient descent

RMSprop在adagrad基础上,将分母由梯度平方和变为梯度的EMA

优点:

  1. 不同的训练参数使用不同大小的学习率,
  2. 对Adagrad进行了改进,改变梯度积累为指数加权移动平均。即对分母除的部分使用EMA进行计算,从而保证分母的值随着迭代次数不断累加,最终保持不变,这样最终学习率下降到某个点就不再下降,从而保证可以逃出局部极小值。

缺点:

  1. 分母刚开始的累加,由于初始化原因,假设初始化为0,则分母刚开始很小,导致学习率刚开始很大,造成误差较大,没解决冷启动问题

代码:

# RMSProp.
def rmsprop(params, sqrs, lr, gamma, batch_size):
    eps_stable = 1e-8
    for param, sqr in zip(params, sqrs):
        g = param.grad / batch_size
        sqr[:] = gamma * sqr + (1. - gamma) * nd.square(g)
        div = lr * g / nd.sqrt(sqr + eps_stable)
        param[:] -= div

 

Adadelta:

论文:ADADELTA: AN ADAPTIVE LEARNING RATE METHOD

在RMSprop基础上,将学习率替换为每个参数的平方和开根号,即分子为每个参数的EMA然后开根号,分母还是和RMSprop中一样,为每个梯度的EMA然后开根号。

优点:

  1. 没有学习率参数
  2. 不同的训练参数使用不同大小的学习率

缺点:

  1. 还是没解决冷启动问题

代码:

# Adadalta.
def adadelta(params, sqrs, deltas, rho, batch_size):
    eps_stable = 1e-5
    for param, sqr, delta in zip(params, sqrs, deltas):
        g = param.grad / batch_size
        sqr[:] = rho * sqr + (1. - rho) * nd.square(g)
        cur_delta = nd.sqrt(delta + eps_stable) / nd.sqrt(sqr + eps_stable) * g
        delta[:] = rho * delta + (1. - rho) * cur_delta * cur_delta
        # update weight
        param[:] -= cur_delta

 

Adam:

论文:ADAM: A METHOD FOR STOCHASTIC OPTIMIZATION

Adam组合了动量法和RMSProp。在RMSprop基础上,分子上梯度一阶矩加上了动量。分母保持RMSprop的梯度二阶矩,即EMA。并且为了解决冷启动问题,对分子的动量,分母的EMA都除了(1-p^t),从而保证刚开始值较大,随着迭代值再慢慢减少。

优点:

  1. 解决冷启动问题
  2. 不同的训练参数使用不同大小的学习率

代码:

# Adam.
def adam(params, vs, sqrs, lr, batch_size, t):
    beta1 = 0.9
    beta2 = 0.999
    eps_stable = 1e-8

    for param, v, sqr in zip(params, vs, sqrs):
        g = param.grad / batch_size

        v[:] = beta1 * v + (1. - beta1) * g
        sqr[:] = beta2 * sqr + (1. - beta2) * nd.square(g)

        v_bias_corr = v / (1. - beta1 ** t)
        sqr_bias_corr = sqr / (1. - beta2 ** t)

        div = lr * v_bias_corr / (nd.sqrt(sqr_bias_corr) + eps_stable)
        param[:] = param - div

 

对比:

 

References:

An overview of gradient descent optimization algorithms∗

https://gluon.mxnet.io/

猜你喜欢

转载自blog.csdn.net/qq_14845119/article/details/86491430
今日推荐