2.2.2 自适应学习率算法

从上一小节可知,随机梯度下降算法有如下几个缺点。

  • 很难选择合适的学习率,太大或太小都不合适。
  • 相同的学习率不应该适用于所有的参数更新。
  • 随机梯度下降容易被鞍点困住。

为了更有效地训练模型,比较合理的一种做法是,对每个参与训练的参数设置不同的学习率,在整个学习过程中通过一些算法自动适应这些参数的学习率。常用的自适应学习率算法有AdaGrad、RMSProp、Adam等。下面介绍这些算法的原理及Keras实现。

1. 算法基本原理

(1)AdaGrad

AdaGrad(Adaptive Gradient Algorithm,自适应梯度算法)能够独立地适应所有模型参数的学习率,当参数的损失偏导值比较大时,应该有一个比较大的学习率;而当参数的损失偏导值比较小时,应该有一个比较小的学习率。因此,对于稀疏的数据,AdaGrad的表现很好,能很好地提高随机梯度下降算法(SGD)的鲁棒性。

首先设全局学习率为η,初始化的参数为ω,一个为了维持数值稳定性而添加的常数048-6,例如10-7,以及一个使用梯度按元素平方的累加变量r,并将其中每个元素初始化为0。在每次迭代中,首先计算小批量梯度g,然后将该梯度按元素计算平方和后累加到变量r中。算法将循环执行以下步骤,在没有达到停止条件前不会停止。

1)从训练数据集中取出包含m个样本的小批量数据{x1x2,…,xm},数据对应的目标值用yi表示。在小批量数据的基础上按照以下公式计算梯度:

048-1

2)计算累积平方梯度,并刷新r

048-2

3)计算参数的更新量:

048-3

4)根据Δω更新参数:

048-4

在该算法中,每个参数的都反比于其所有梯度历史平方值总和的平方根(048-5),可以实现独立适应所有模型参数的学习率的目的。AdaGrad算法在某些深度学习模型上能获得很不错的效果,但这并不能代表该算法能够适应所有模型。由于r一直在累加按元素平方的梯度,每个元素的学习率在迭代过程中一直在降低或不变,所以在某些情况下,当学习率在迭代早期降得较快且当前解仍不理想时,AdaGrad在迭代后期可能较难找到一个有用的解。

(2)RMSProp

为了解决Adagrad学习率急剧下降的问题,Geoff Hinton于2012年提出了一种自适应学习率的RMSProp算法。RMSProp算法采用指数衰减的方式淡化了历史对当前步骤参数更新量Δω的影响。指数加权移动平均旨在消除梯度下降中的摆动。若某一维度的导数比较大,则指数加权平均就大;若某一维度的导数比较小,则其指数加权平均就小。这样保证了各维度导数都在一个量级,进而减少了摆动。相比于AdaGrad,RMSProp算法中引入了一个新的参数ρ,用于控制历史梯度值的衰减速率。算法步骤如下。

1)从训练数据集中取出包含m个样本的小批量数据{x1x2,…,xm},数据对应的目标值用yi表示。在小批量数据的基础上按照以下公式计算梯度:

049-1

2)计算累积平方梯度,并刷新r

049-2

3)计算参数的更新量:

049-3

4)根据Δω更新参数:

ωωω

需要强调的是,RMSProp只在AdaGrad的基础上修改了变量r的更新方法,即把累加改成了指数的加权移动平均,因此,每个元素的学习率在迭代过程中既可能降低又可能升高。大量的实际情况证明,RSMProp算法在优化深度神经网络时有效且实用。

(3)Adam

Adam算法(Adaptive Moment Estimation)是一种在RMSProp算法的基础上进一步改良的自适应学习率的优化算法。Adam是一个组合了动量法(Momentum)和RMSProp的优化算法,通过动量法加速收敛,并通过学习率衰减自动调整学习率。

Adam算法会使用一个动量变量v和一个RMSProp中梯度按元素的指数加权移动平均的变量r,并将它们的每个元素初始化为0;矩估计的指数衰减速率为ρ1ρ2ρ1ρ2在区间[0,1]内,通常设置为0.9和0.999);以及一个时间步t,初始化为0。算法步骤如下:

1)从训练数据集中取出包含m个样本的小批量数据{x1x2,…,xm},数据对应的目标值用yi表示。在小批量数据的基础上按照以下公式计算梯度:

049-5

2)刷新时间步:

tt+1

3)对梯度做指数加权移动平均并计算动量变量v

049-6

对偏差进行修正:

049-7

4)对梯度按元素平方后做指数加权移动平均并计算r

049-8

对偏差进行修正:

050-1

5)计算参数的更新量:

050-2

6)根据Δω更新参数:

ωωω

Adam将Momentum和RMSProp算法的优点集于一身,在现实中应用更广泛。

2. Keras优化器

Keras内置了多种优化器,可以轻松实现随机梯度下降、各种自适应学习率算法的函数,下面逐一介绍。

(1)optimizer_sgd()

optimizer_sgd()函数实现随机梯度下降算法,支持动量优化,学习率衰减(每次参数更新后)、Nestrov动量(NAG)优化。其形式为:

optimizer_sgd(lr = 0.01, momentum = 0, decay = 0, nesterov = FALSE,
              clipnorm = NULL, clipvalue = NULL)

各参数描述如下。

  • lr:大于0的浮点数,学习率。
  • momentum:大于0的浮点数,动量参数。
  • decay:大于0的浮点数,每次参数更新后学习率的衰减值。
  • nesterov:布尔型,是否使用Nesterov动量。

(2)optimizer_rmsprop()

optimizer_rmsprop()函数实现RMSProp优化器。RMSProp通过引入一个衰减系数,让r每回合都衰减一定比例,类似于Momentum中的做法,通常是面对递归神经网络时的一个良好选择。除学习率可调整外,建议保持优化器的其他默认参数不变。其形式为:

optimizer_rmsprop(lr = 0.001, rho = 0.9, epsilon = NULL, decay = 0,
                  clipnorm = NULL, clipvalue = NULL)

各参数描述如下。

  • lr:大于0的浮点数,学习率。
  • rho:大于0的浮点数,RMSProp梯度平方的移动均值的衰减率。
  • epsilon:大于0的浮点数,若为NULL,默认为K.epsilon()。
  • decay:大于0的浮点数,每次参数更新后学习率的衰减值。

(3)optimizer_adagrad()

optimizer_adagrad()函数实现AdaGrad优化器。AdaGrad是一种具有特定参数学习率的优化器。它根据参数在训练期间的更新频率进行自适应调整。建议使用优化器的默认参数。其形式为:

optimizer_adagrad(lr = 0.01, epsilon = NULL, decay = 0,
                  clipnorm = NULL, clipvalue = NULL)

各参数描述如下。

  • lr:大于0的浮点数,学习率。
  • epsilon:大于0的浮点数,若为NULL,默认为K.epsilon()。
  • decay:大于0的浮点数,每次参数更新后学习率的衰减值。

(4)optimizer_adadelta()

optimizer_adadelta()函数实现Adadelta优化器。Adadelta是AdaGrad的一个具有更强鲁棒性的扩展版本。该方法仅利用一阶信息动态地适应时间的变化,并且计算开销比一般的随机梯度下降算法要小。它不需要人工调整学习率,对噪声梯度信息、不同的模型结构选择、不同的数据模式和超参数选择具有鲁棒性。建议使用优化器的默认参数。其形式为:

optimizer_adadelta(lr = 1, rho = 0.95, epsilon = NULL, decay = 0,
                   clipnorm = NULL, clipvalue = NULL)

各参数描述如下。

  • lr:大于0的浮点数,学习率,建议保留默认值。
  • rho:大于0的浮点数,Adadelta梯度平方移动均值的衰减率。
  • epsilon:大于0的浮点数,若为None,默认为K.epsilon()。
  • decay:大于0的浮点数,每次参数更新后学习率的衰减值。

(5)optimizer_adam()

optimizer_adam()实现Adam优化器。Adam本质上是带有动量项的RMSProp,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有确定的范围,使得参数比较平稳。该优化器的默认值来源于参考文献。其形式为:

optimizer_adam(lr = 0.001, beta_1 = 0.9, beta_2 = 0.999,
               epsilon = NULL, decay = 0, amsgrad = FALSE, clipnorm = NULL,
               clipvalue = NULL)

各参数描述如下。

  • lr:大于0的浮点数,学习率,建议保留默认值。
  • beta_1|beta_2:0<beta<1,通常接近于1。
  • epsilon:大于0的浮点数,若为NULL,默认为K.epsilon()。
  • decay:大于0的浮点数,每次参数更新后学习率的衰减值。
  • amsgrad:布尔型,是否应用此算法的AMSGrad变种。

此外,还有optimizer_adamax()函数实现Adamax优化器。它是Adam算法基于无穷范数(infinity norm)的变种,参数默认遵循论文中提供的值。optimizer_nadam()函数实现Nesterov版本的Adam优化器,正如Adam本质上是Momentum与RMSProp的结合,Nadam是采用Nesterov Momentum版本的Adam优化器。建议使用优化器的默认参数。