深度学习笔记(十三)—— 参数更新[Parameter Updates]

  这是深度学习笔记第十三篇,完整的笔记目录可以点击这里查看。
  

1 SGD and bells and whistles

1.1 Vanilla update

  最简单的更新形式是沿负梯度方向更新参数(因为梯度指示增加的方向,但我们通常希望最小化损失函数)。设参数x和梯度dx,最简单的更新形式如下:

# Vanilla update
x += - learning_rate * dx

  其中learning_rate是一个超参数(一个固定常数)。

1.2 Momentum update

  动量更新是另一种在深度网络上几乎总是具有更好收敛速度的方法。这个更新从物理角度来看待优化问题。与SGD优化中梯度直接对位置进行积分不同,它认为梯度只直接影响速度,而速度反过来又影响位置。

# Momentum update
v = mu * v - learning_rate * dx # integrate velocity
x += v # integrate position

  这里,v通常初始化为0,mu在最优化中被称为动量(其典型值约为0.9),但其物理意义与摩擦系数更为一致。这个变量有效地抑制了速度,降低了系统的动能,否则优化结果永远不会停在最低点。交叉验证时,此参数通常设置为[0.5、0.9、0.95、0.99]。与学习率的退火计划(annealing schedules,稍后讨论)类似,优化有时可以从动量计划(momentum schedules)中受益,动量在学习的后期阶段增加。一个典型的设置是从大约0.5的动量开始,在多个时间段内退火到0.99左右。

1.3 Nesterov Momentum

  Nesterov Momentum是Momentum更新的一个稍有不同的版本,该版本最近越来越流行。它对凸函数具有较强的理论收敛性保证,在实际应用中也始终比标准Momentum略好。两种方法的对比如下图所示:
在这里插入图片描述
  其运行代码示例:

x_ahead = x + mu * v
# evaluate dx_ahead (the gradient at x_ahead instead of at x)
v = mu * v - learning_rate * dx_ahead
x += v

  然而,在实践中,人们更喜欢表达的更像vanilla SGD或1.2中的动量更新的形式。这可以通过变量代换x_ahead = x + mu * v来实现,然后用x_ahead替换x来表示更新。也就是说,我们实际存储的参数向量始终是ahead版本。上面代码块中的x_ahead的方程式(但将其重新命名为x)变成:

v_prev = v # back this up
v = mu * v - learning_rate * dx # velocity update stays the same
x += -mu * v_prev + (1 + mu) * v # position update changes form

  更多信息参考Advances in optimizing Recurrent Networks by Yoshua Bengio, Section 3.5TRAINING RECURRENT NEURAL NETWORKS by Ilya Sutskever, Section 7.2

2 Annealing the learning rate

  在训练深层网络时,随着时间的推移对学习速度进行退火通常是有帮助的。要记住的好直觉是,在高学习率下,系统包含太多动能(kinetic energy),参数向量无序地反弹,无法稳定到损失函数的更深但更窄的部分。想知道什么时候降低学习速率是很棘手的:慢慢地降低学习速度,你会浪费计算时间,在很长一段时间内,你的学习速度几乎没有提高。但是,如果它的降低过于剧烈,系统会冷却得太快,无法达到它所能达到的最佳位置。实现学习率衰减有三种常见类型:

  1. Step decay。每过几个epochs,学习率就会降低一倍。典型的值可能是每5个epochs减少一半的学习率,或每20个epochs减少0.1。这些数字在很大程度上取决于问题的类型和模型。在实践中,你可能会看到一种启发式方法,即在使用固定学习率进行训练时观察validation error,并在validation error停止改善时将学习率降低一个常数(例如0.5)。
  2. Exponential decay。具有数学形式α=α0e−kt,其中α0,k是超参数,t是迭代次数(但也可以使用epochs为单位)。
  3. 1/t decay。具有数学形式α=α0/(1+kt),其中a0,k是超参数,t是迭代次数。

  在实践中,Step decay更为可取,因为它所涉及的超参数(the fraction of decay和以epochs为单位的step timings)比超参数k更易于解释。

3 Second order methods

  另一类流行的优化方法是基于牛顿法的二阶优化算法,它迭代了以下更新:
在这里插入图片描述
  这里,Hf(x)是Hessian矩阵,它是函数的二阶偏导数的平方矩阵。 Hessian矩阵直观地描述了损失函数的局部曲率,从而使我们能够执行更有效的更新。特别是,与Hessian的逆相乘导致优化在平缓曲率方向上采取更大的step,而在陡峭曲率方向上采取更小的step。值得注意的是,更新公式中没有任何学习率超参数,这被认为时该方法相比于一阶方法的一大优势。
  然而,上述更新对于大多数深度学习应用程序是不切实际的,因为计算(和求逆)显式形式的Hessian在空间和时间上都是一个非常昂贵的过程。因此,各种各样的quasi-Newton方法被提出,用以寻求近似求逆Hessian。其中,最流行的是L-BFGS,它使用随时间变化的梯度中的信息隐式地进行近似(即不计算完整矩阵)。
  在实际应用中,L-BFGS或类似的二阶方法应用于大规模深度学习和卷积神经网络的情况并不常见。相反,基于Nesterov动量的SGD变体更常见,因为它们更简单,更容易扩展。
  更多信息参考Large Scale Distributed Deep Networks from the Google Brain teamSFO algorithm

4 Per-parameter adaptive learning rate methods

  到目前为止,我们讨论的所有以前的方法都全局地、平等地操纵所有参数的学习速率。在本节中,我们将重点介绍一些在实践中可能遇到的常见自适应方法:

4.1 Adagrad

  Adagrad是Duchi等人提出的一种自适应学习率方法。

# Assume the gradient dx and parameter vector x
cache += dx**2
x += - learning_rate * dx / (np.sqrt(cache) + eps)

  其中,变量cache的大小等于梯度的大小,并跟踪每个参数的梯度平方和。然后,这将用于规范化参数更新步骤(按元素)。请注意,接收高梯度的权重将降低其有效学习率,而接收少量或不频繁更新的权重将提高其有效学习率。有趣的是,平方根运算非常重要,没有平方根运算,算法的性能就差得多。平滑项eps(通常设置在1e-4到1e-8的范围内)避免被零除。Adagrad的一个缺点是,在深度学习的情况下,单调的学习率通常过于激进,会出现过早停止学习的情况。

4.2 RMSprop

  RMSprop是一种非常有效的自适应学习率方法。RMSProp以一种非常简单的方式改进了Adagrad方法,试图降低其具有激进的、单调递减的学习速率。特别是,它使用梯度平方的移动平均值:

cache = decay_rate * cache + (1 - decay_rate) * dx**2
x += - learning_rate * dx / (np.sqrt(cache) + eps)

  这里,decay_rate是一个超参数,典型值是[0.9,0.99,0.999]。注意,x+=的更新与Adagrad相同,但是cache变量是一个“leaky”。因此,RMSProp仍然基于梯度的大小来调节每个权重的学习率,这具有有益的均衡效果,但与Adagrad不同的是,更新不会单调地变小。

4.3 Adam

  Adam是最近提出的一个更新方法,看起来有点像RMSProp。(简化的)更新如下所示:

m = beta1*m + (1-beta1)*dx
v = beta2*v + (1-beta2)*(dx**2)
x += - learning_rate * m / (np.sqrt(v) + eps)

  这里,更新看起来与RMSProp update完全相同,只是使用了梯度m的“平滑”版本,而不是原始(可能是有噪声的)梯度向量dx。原文的推荐值为eps=1e-8,beta1=0.9,beta2=0.999。在实践中,目前推荐使用Adam作为默认算法,并且通常比RMSProp稍微好一点。不过,作为替代方案,SGD+Nesterov Momentum通常也值得一试。完全Adam更新还包括bias校正机制,该机制补偿在向量mv完全“预热”(“warm up”)之前,在最初的几个时间步中向量mv都被初始化并且bias被置零的问题。使用bias校正机制,更新如下所示:

# t is your iteration counter going from 1 to infinity
m = beta1*m + (1-beta1)*dx
mt = m / (1-beta1**t)
v = beta2*v + (1-beta2)*(dx**2)
vt = v / (1-beta2**t)
x += - learning_rate * mt / (np.sqrt(vt) + eps)

  这里,更新是迭代和其他参数的函数。
  
  其他参考资料:
  Unit Tests for Stochastic Optimization提出了一系列测试作为随机优化的标准化基准。



*本博客翻译总结自CS231n课程作业网站,该网站需要翻墙才能访问。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值