斯坦福CS231n - CNN for Visual Recognition(8)-lecture6学习率更新、超参数调优

本节主要讲了神经网络学习率退火和超参数调优等问题

学习率更新

学习率衰减

  训练深度网络时,让学习率随着时间退火通常很有帮助。如果学习率很高,系统的动能就过大,参数向量就会无规律地跳动,不能够稳定到损失函数更深更窄的部分去。

  何时开始衰减学习率是有技巧的:缓慢减小它,可能很长时间内只能是浪费计算资源地看着它混沌地跳动,实际进展很少。而如果快速地减小它,系统可能过快地失去能量,不能到达原本可以到达的最好位置。

  通常,实现学习率退火以下三种:

  • 随步数衰减:每进行几个周期就根据一些因素降低学习率。典型的值是每过5个周期就将学习率减少一半,或者每20个周期减少到之前的0.1。这些数值的设定是严重依赖具体问题和模型的选择的。在实践中经验做法是:使用固定的学习率训练的同时观察验证集错误率,每当验证集错误率停止下降,就乘以一个常数(比如0.5)来降低学习率。
  • 指数衰减。数学公式是α=α0e−kt\alpha=\alpha_0e^{-kt},其中α0,k\alpha_0,k是超参数,tt是迭代次数(也可以使用周期作为单位)。
  • 1/t1/t衰减的数学公式是α=α0/(1+kt)\alpha=\alpha_0/(1+kt),其中α0,k\alpha_0,k是超参数,t是迭代次数。

实践中,随步数衰减的随机失活(dropout)更受欢迎,因为它使用的超参数(衰减系数和以周期为时间单位的步数)比kk更有解释性。

二阶迭代法

  该优化方法基于牛顿法,其迭代方式如下:

x←x−[Hf(x)]−1∇f(x)

x \leftarrow x - [H f(x)]^{-1} \nabla f(x)   这里Hf(x)Hf(x)是Hessian矩阵,它是函数的二阶偏导数的平方矩阵。∇f(x) \nabla f(x)是梯度向量,这和梯度下降中一样。直观理解上,Hessian矩阵描述了损失函数的局部曲率,从而使得可以进行更高效的参数更新。具体来说,就是乘以Hessian转置矩阵可以让最优化过程在曲率小的时候大步前进,在曲率大的时候小步前进。这个公式中没有学习率这个超参数,因此比一阶方法好得多。

  在实际深度学习应用中,上述更新方法很难运用,这是因为计算(以及求逆)Hessian矩阵操作非常耗费时间和空间。例如,假设一个有一百万个参数的神经网络,其Hessian矩阵大小就是[1,000,000 x 1,000,000],将占用将近3725GB的内存。好消息是,各种各样的拟-牛顿法就被发明出来用于近似转置Hessian矩阵。最流行的是L-BFGS,该方法使用随时间的梯度中的信息来隐式地近似(整个矩阵没有被计算)。

  然而,即使解决了存储空间的问题,L-BFGS应用的一个巨大劣势是需要对整个训练集进行计算,而整个训练集一般包含几百万的样本。和小批量随机梯度下降(mini-batch SGD)不同,让L-BFGS在小批量上运行起来是很需要技巧,同时也是研究热点。 在实践中,使用L-BFGS之类的二阶方法并不常见。基于(Nesterov的)动量更新的各种随机梯度下降方法更加常用,因为它们更加简单且容易扩展。   感兴趣的同学可以参考以下文献:

逐参数适应学习率

  前面讨论的基于梯度的优化方法(SGD、Momentum、NAG)的学习率是全局的,且对所有参数是相同的。 参数的有些维度变化快,有些维度变化慢;有些维度是负的斜坡,有些维度是正的斜坡(如鞍点);采用相同的学习率并不科学,比如有的参数可能已经到了仅需要微调的阶段,但又有些参数由于对应样本少等原因,还需要较大幅度的调动。理想的方案是根据参数每个维度的变化率,采用对应的学习率。    学习率调参是很耗费计算资源的过程,所以很多工作投入到发明能够适应性地对学习率调参的方法,甚至是逐个参数适应学习率调参。很多这些方法仍需其他超参数设置,但普遍认为这些方法对于更广范围的超参数比原始的学习率方法有更良好的表现。下面将介绍一些在实践中可能遇到的常用适应算法:

AdaGrad(Adaptive Gradient )

  Adagrad是一个由Duchi等提出的适应性学习率算法

# 假设有梯度和参数向量x
cache += dx**2
x += - learning_rate * dx / (np.sqrt(cache) + eps)

  变量cache的尺寸和梯度矩阵的尺寸相同,还跟踪了每个参数的梯度的平方和。这个一会儿将用来归一化参数更新步长,归一化是逐元素进行的。注意,接收到高梯度值的权重更新的效果被减弱,而接收到低梯度值的权重的更新效果将会增强。平方根的操作非常重要,如果去掉,算法的表现将会糟糕很多。用于平滑的式子eps(一般设为1e−41e^{-4}到1e−81e^{-8}之间)防止出现除0的情况。

  优点:不需要手动调整Learning Rate,默认值为0.01即可。   缺点:在分母中累积了梯度的平方,且此累积值单调递增,从而导致学习率单调递减,直至无限小(在深度学习中单调的学习率被证明通常过于激进且过早停止学习),从而不能再学到相关知识(AdaDelta、RMSprop、Adam专为解决此问题而生)。    AdaGrad方法给参数的每个维度给出适应的学习率。给不经常更新的参数以较大的学习率, 给经常更新的参数以较小的学习率。Google使用此优化方法“识别Youtube视频中的猫” 。    在AdaGrad中,每个参数θi\theta_i在每一次更新时都使用不同的学习率。其公式如下:

gt,i=∇θJ(θi)θt+i=θt,i−η⋅gt,iθt+i=θt,i−ηGt,ii+ϵ−−−−−−−√⋅gt,iGt∈Rd×d是一个对角矩阵,每个对角元素i,i是θi过去所有梯度平方的和ϵ是一个平滑项。避免除0,通常取1e−8θt+1=θt−ηGt+ϵ⊙gt

\begin {align}    & g_{t,i}=\nabla_\theta J(\theta_i) \\    &\theta_{t+i}= \theta_{t,i}-\eta\cdot g_{t,i} \\    &\theta_{t+i}= \theta_{t,i}-\frac{\eta}{\sqrt{G_{t,ii}+\epsilon}}\cdot g_{t,i}\\    &G_{t}\in \mathbb{R}^{d\times d} \text{是一个对角矩阵,每个对角元素}i,i\text{是}\theta_i\text{过去所有梯度平方的和}\\    & \epsilon\text{是一个平滑项。避免除0,通常取}1e^{-8}\\    & \theta_{t+1}=\theta_t - \frac{\eta}{G_t + \epsilon}\odot g_t    \end {align}   learning_rate 是初始学习率,由于之后会自动调整学习率,所以初始值就不像之前的算法那样重要了。其含义是,对于每个参数,随着其更新的总距离增多,其学习速率也随之变慢。

AdaDelta (Adaptive Delta)

  优点:   1) 解决了AdaGrad Learning Rate单调递减的问题。 (是AdaGrad的扩展)    2) 不需要设置默认的Learning Rate   Adagrad算法存在三个问题:    1)其学习率是单调递减的,训练后期学习率非常小    2)其需要手工设置一个全局的初始学习率    3)更新W时,左右两边的单位不同

   Adadelta针对上述三个问题提出了比较漂亮的解决方案。

RMSprop

  RMS(Root Mean Squared均方根) 是一个非常高效,但没有公开发表的适应性学习率方法。引自Geoff Hinton的Coursera课程的第六课的第29页PPT。这个方法用一种很简单的方式修改了Adagrad方法,让它不那么激进,单调地降低了学习率。具体说来,就是它使用了一个梯度平方的滑动平均:

E[g2]t=0.9E[g2]t−1+0.1g2tθt+1=θt−ηE[g2]t+ϵ−−−−−−−−√⋅gtη is 0.001 

\begin{align}  & E[g^2]_t = 0.9E[g^2]_{t-1}+ 0.1g_t^2\\ &\theta_{t+1}=\theta _t - \frac{\eta}{\sqrt{E[g_2]_t+\epsilon}}\cdot g_t\\ &\eta\text{ is 0.001 }  \end{align}

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][0.9,0.99,0.999]。其中x+=和Adagrad中是一样的,但是cache变量是不同的。因此,RMSProp仍然是基于梯度的大小来对每个权重的学习率进行修改,这同样效果不错。但是和Adagrad不同,其更新不会让学习率单调变小。

Adam (Adaptive Moment Estimation)

  Adam是最近才提出的一种更新方法,它看起来像是RMSProp的动量版。简化的代码是下面这样:

mt=β1mt−1+(1−β1)gtvt=β2vt−1+(1−β2)g2tmt:梯度的均值(the mean)估计vt:梯度的非中心方差(the uncentered variance)估计m^t=mt1−βt1v^t=vt1−βt2θt+1=θt−ηvt^−−√+ϵ⋅m^t0.9 for β1,0.999 for β2 and 10−8 for ϵ

\begin{align} &m_t=\beta_1m_{t-1}+(1-\beta_1)g_t\\ &v_t=\beta_2v_{t-1}+(1-\beta_2)g_t^2\\ &m_t:梯度的均值(the mean)估计\\ &v_t:梯度的非中心方差(the  uncentered  variance)估计\\ &\hat m_t=\frac{m_t}{1-\beta_1^t}\\ &\hat v_t=\frac{v_t}{1-\beta_2^t}\\ &\theta_{t+1}=\theta_t - \frac{\eta}{\sqrt{\hat{v_t}}+\epsilon }\cdot\hat m_t\\ &0.9\text{ for } \beta_1,0.999 \text{ for } \beta_2\text{ and } 10^{-8}\text{ for } \epsilon \end{align}

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

  这个更新方法看起来很像RMSProp,除了使用的是平滑版的梯度m,而不是用的原始梯度向量dx。论文中推荐的参数值eps=1e-8, beta1=0.9, beta2=0.999。在实际操作中,我们推荐Adam作为默认的算法,一般而言跑起来比RMSProp要好一点。但是也可以试试SGD+Nesterov动量。完整的Adam更新算法也包含了一个偏置(bias)矫正机制,因为m,v两个矩阵初始为0,在没有完全热身之前存在偏差,需要采取一些补偿措施。   有兴趣地可以读以下文献:   Matthew Zeiler提出的Adadelta Adam: A Method for Stochastic Optimization Unit Tests for Stochastic Optimization

如何选择优化算法

  1)总结

  • RMSprop是AdaGrad的扩展,以解决learning rate逐步消失的问题
  • RMSprop与AdaDelta相比,AdaDelta在分子更新规则中使用了参数RMS更新,其它相同
  • Adam与RMSprop相比,增加了偏差校正和动量
  • RMSprop、AdaDelta和Adam是非常类似的算法,在类似的环境下,效果相当
  • 从整体上看,Adam目前是最好的选择 2)如果输入数据是稀疏的(sparse),使用adaptive learning-rate(AdaGrad、AdaDelta、RMSprop、Adam)可以获得最好的结果,且不需要调整learning rate; 3)如果你关心快速收敛,你应当选择adaptive learning-rate方法

超参数调优

  神经网络最常用的超参数设置有:初始学习率学习率衰减方式(例如一个衰减常量)、正则化强度(L2惩罚,随机失活强度)。下面将介绍一些额外的调参要点和技巧:

随机设置参数并记录。对于大的深层次神经网络而言,我们需要很多的时间去训练。因此在此之前我们花一些时间去做超参数搜索,以确定最佳设定是非常有必要的。最直接的方式就是在框架实现的过程中,设计一个会持续变换超参数实施优化,并记录每个超参数下每一轮完整训练迭代下的验证集状态和效果。

使用验证集。实际工程中,神经网络里确定这些超参数,我们一般很少使用n折交叉验证,一般使用一份固定的交叉验证集就可以了。

超参数范围。一般对超参数的尝试和搜索都是在对数域进行的。例如,一个典型的学习率搜索序列就是learning_rate = 10 ** uniform(-6, 1)。我们先生成均匀分布的序列,再以10为底做指数运算,其实我们在正则化系数中也做了一样的策略。比如常见的搜索序列为[0.5,0.9,0.95,0.99][0.5, 0.9, 0.95, 0.99]。 随机搜索优于网格搜索。 Bergstra和Bengio在文章Random Search for Hyper-Parameter Optimization中说“随机选择比网格化的选择更加有效”,而且在实践中也更容易实现。

对于边界上的最优值要小心。这种情况一般发生在你在一个不好的范围内搜索超参数(比如学习率)的时候。比如,假设我们使用learning_rate = 10 ** uniform(-6,1)来进行搜索。一旦我们得到一个比较好的值,一定要确认你的值不是出于这个范围的边界上,不然你可能错过更好的其他搜索范围。

从粗到细地分阶段搜索。在实践中,先进行初略范围(比如10 ** [-6, 1])搜索,然后根据好的结果出现的地方,缩小范围进行搜索。进行粗搜索的时候,让模型训练一个周期就可以了,因为很多超参数的设定会让模型没法学习,或者突然就爆出很大的损失值。第二个阶段就是对一个更小的范围进行搜索,这时可以让模型运行5个周期,而最后一个阶段就在最终的范围内进行仔细搜索,运行很多次周期。

贝叶斯超参数最优化是一整个研究领域,主要是研究在超参数空间中更高效的导航算法。其核心的思路是在不同超参数设置下查看算法性能时,要在探索和使用中进行合理的权衡。基于这些模型,发展出很多的库,比较有名的有: Spearmint, SMAC, 和Hyperopt。然而,在卷积神经网络的实际使用中,比起上面介绍的先认真挑选的一个范围,然后在该范围内随机搜索的方法,这个方法还是差一些。这里有更详细的讨论。


模型融合与优化

  在实践的时候,一个能提升神经网络几个百分点准确率的方法是在训练的时候训练几个独立的模型,然后在测试的时候平均它们预测结果。集成的模型数量增加,算法的结果也单调提升(但提升效果越来越少)。还有模型之间的差异度越大,提升效果可能越好。进行集成有以下几种方法:

同一个模型,不同的初始化。使用交叉验证来得到最好的超参数,然后用最好的参数来训练不同初始化条件的模型。这种方法的风险在于多样性只来自于不同的初始化条件。

在交叉验证中发现最好的模型。使用交叉验证来得到最好的超参数,然后取其中最好的几个(比如10个)模型来进行集成。这样就提高了集成的多样性,但风险在于可能会包含不够理想的模型。在实际操作中,这样操作起来比较简单,在交叉验证后就不需要额外的训练了。

一个模型设置多个记录点。如果训练非常耗时,那就在不同的训练时间对网络留下记录点(比如每个周期结束),然后用它们来进行模型集成。很显然,这样做多样性不足,但是在实践中效果还是不错的,这种方法的优势是代价比较小。

在训练的时候跑参数的平均值。和上面一点相关的,还有一个也能得到1-2个百分点的提升的小代价方法,这个方法就是在训练过程中,如果损失值相较于前一次权重出现指数下降时,就在内存中对网络的权重进行一个备份。这样你就对前几次循环中的网络状态进行了平均。你会发现这个“平滑”过的版本的权重总是能得到更少的误差。直观的理解就是目标函数是一个碗状的,你的网络在这个周围跳跃,所以对它们平均一下,就更可能跳到中心去。

  模型集成的一个劣势就是在测试数据的时候会花费更多时间。最近Geoff Hinton在“Dark Knowledge”上的工作很有启发:其思路是通过将集成似然估计纳入到修改的目标函数中,从一个好的集成中抽出一个单独模型。


总结

  训练一个神经网络需要:

  1. 利用小批量数据对实现进行梯度检查,还要注意各种错误。 
  2. 初始权重进行合理性检查,确认初始损失值是合理的,在小数据集上能得到100%的准确率。
  3. 在训练时,跟踪损失函数值,训练集和验证集准确率,还可以跟踪更新的参数量相对于总参数量的比例(一般在1e−31e^{-3}左右)。如果是对于卷积神经网络,可以将第一层的权重可视化。
  4. 推荐的两个更新方法是SGD+Nesterov动量方法,或者Adam方法。
  5. 随着训练进行学习率衰减。比如,在固定多少个周期后让学习率减半,或者当验证集准确率下降的时候。
  6. 使用随机搜索(不要用网格搜索)来搜索最优的超参数。分阶段从粗(比较宽的超参数范围训练1-5个周期)到细(窄范围训练很多个周期)地来搜索。
  7. 进行模型集成来获得额外的性能提高。

拓展阅读

Leon Bottou的《SGD要点和技巧》。 Yann LeCun的《Efficient BackProp》。 Yoshua Bengio的《Practical Recommendations for Gradient-Based Training of Deep Architectures》。


参考资料

链接:http://cs231n.github.io/neural-networks-3/ 链接:https://zhuanlan.zhihu.com/p/21741716?refer=intelligentunit https://zhuanlan.zhihu.com/p/21798784?refer=intelligentunit 链接:http://blog.csdn.net/han_xiaoyang/article/details/50521064 链接:http://blog.csdn.net/myarrow/article/details/51848285

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏CreateAMind

keras中文文档之:CNN眼中的世界:利用Keras解释CNN的滤波器

1562
来自专栏机器学习之旅

总结:常见算法工程师面试题目整理(一)

最近抽风,出去面试了不少公司,和不少算法工程师招聘的朋友有所交流,整理了相关比较有意思的题目,供大家参考:

1294
来自专栏marsggbo

DeepLearning.ai学习笔记(二)改善深层神经网络:超参数调试、正则化以及优化--Week2优化算法

1. Mini-batch梯度下降法 介绍 假设我们的数据量非常多,达到了500万以上,那么此时如果按照传统的梯度下降算法,那么训练模型所花费的时间将非常巨大,...

2196
来自专栏数据科学与人工智能

【智能】自然语言处理概述

1 什么是文本挖掘? 文本挖掘是信息挖掘的一个研究分支,用于基于文本信息的知识发现。文本挖掘的准备工作由文本收集、文本分析和特征修剪三个步骤组成。目前研究和应用...

4095
来自专栏人工智能LeadAI

机器学习中如何解决过拟合

机器学习中出现的非常频繁的问题:过拟合与规则化。我们先简单的来理解下常用的L0、L1、L2和核范数规则化。 监督机器学习问题无非就是"minimizeyour...

2883
来自专栏机器之心

每个Kaggle冠军的获胜法门:揭秘Python中的模型集成

6329
来自专栏机器之心

业界 | Tensor Core究竟有多快?全面对比英伟达Tesla V100/P100的RNN加速能力

3719
来自专栏ATYUN订阅号

【学术】Ferenc Huszár:剪枝神经网络两篇最新论文的解读

我想简要地介绍两篇关于修剪神经网络的论文: Learning Sparse Neural Networks through L0 Regularization...

4457
来自专栏目标检测和深度学习

深度学习之基础网络演进、分类与定位的权衡|牛喀技研

深度学习,目标检测,图像,智能驾驶 编译:牛喀网-钱伟 前言 本篇关注基础网络架构的演进和处理分类、定位这一矛盾问题上的进展。 基础网络结构的演进 基础网络(...

8587
来自专栏CSDN技术头条

使用scikit-learn解释随机森林算法

在以前的一篇博文里,我讨论过如何将随机森林算法转化为一个“白盒”,这样每次预测就能被分解为各项特征的贡献和,即 ? 我多次想找相关的代码。然而,绝大多数的随机森...

19110

扫码关注云+社区

领取腾讯云代金券