机梯度下降及各种更新方法

普通更新

最简单的更新形式是沿着负梯度方向改变参数(因为梯度指向的是上升方向,但是我们通常希望最小化损失函数)。假设有一个参数向量x及其梯度dx,那么最简单的更新的形式是:

# 普通更新
x += - learning_rate * dx

其中learning_rate是一个超参数,它是一个固定的常量。当在整个数据集上进行计算时,只要学习率足够低,总是能在损失函数上得到非负的进展。

动量(Momentum)更新

是另一个方法,这个方法在深度网络上几乎总能得到更好的收敛速度。该方法可以看成是从物理角度上对于最优化问题得到的启发。损失值可以理解为是山的高度(因此高度势能是,所以有)。用随机数字初始化参数等同于在某个位置给质点设定初始速度为0。这样最优化过程可以看做是模拟参数向量(即质点)在地形上滚动的过程。

因为作用于质点的力与梯度的潜在能量()有关,质点所受的力就是损失函数的(负)梯度。还有,因为,所以在这个观点下(负)梯度与质点的加速度是成比例的。注意这个理解和上面的随机梯度下降(SDG)是不同的,在普通版本中,梯度直接影响位置。而在这个版本的更新中,物理观点建议梯度只是影响速度,然后速度再影响位置:

# 动量更新
v = mu * v - learning_rate * dx # 与速度融合
x += v # 与位置融合

在这里引入了一个初始化为0的变量v和一个超参数mu。说得不恰当一点,这个变量(mu)在最优化的过程中被看做动量(一般值设为0.9),但其物理意义与摩擦系数更一致。这个变量有效地抑制了速度,降低了系统的动能,不然质点在山底永远不会停下来。通过交叉验证,这个参数通常设为[0.5,0.9,0.95,0.99]中的一个。和学习率随着时间退火(下文有讨论)类似,动量随时间变化的设置有时能略微改善最优化的效果,其中动量在学习过程的后阶段会上升。一个典型的设置是刚开始将动量设为0.5而在后面的多个周期(epoch)中慢慢提升到0.99

通过动量更新,参数向量会在任何有持续梯度的方向上增加速度


Nesterov动量

与普通动量有些许不同,最近变得比较流行。在理论上对于凸函数它能得到更好的收敛,在实践中也确实比标准动量表现更好一些。

Nesterov动量的核心思路是,当参数向量位于某个位置x时,观察上面的动量更新公式可以发现,动量部分(忽视带梯度的第二个部分)会通过mu * v稍微改变参数向量。因此,如果要计算梯度,那么可以将未来的近似位置x + mu * v看做是“向前看”,这个点在我们一会儿要停止的位置附近。因此,计算x + mu * v的梯度而不是“旧”位置x的梯度就有意义了。

————————————————————————————————————————

Nesterov动量。既然我们知道动量将会把我们带到绿色箭头指向的点,我们就不要在原点(红色点)那里计算梯度了。使用Nesterov动量,我们就在这个“向前看”的地方计算梯度。

————————————————————————————————————————

也就是说,添加一些注释后,实现代码如下:

x_ahead = x + mu * v
# 计算dx_ahead(在x_ahead处的梯度,而不是在x处的梯度)
v = mu * v - learning_rate * dx_ahead
x += v

然而在实践中,人们更喜欢和普通SGD或上面的动量方法一样简单的表达式。通过对x_ahead = x + mu * v使用变量变换进行改写是可以做到的,然后用x_ahead而不是x来表示上面的更新。也就是说,实际存储的参数向量总是向前一步的那个版本。x_ahead的公式(将其重新命名为x)就变成了:

v_prev = v # 存储备份
v = mu * v - learning_rate * dx # 速度更新保持不变
x += -mu * v_prev + (1 + mu) * v # 位置更新变了形式

NAG(Nesterov's Accelerated Momentum)的来源和数学公式推导,我们推荐以下的拓展阅读:

  • Yoshua Bengio的Advances in optimizing Recurrent Networks,Section 3.5。
  • Ilya Sutskever's thesis (pdf)在section 7.2对于这个主题有更详尽的阐述。

学习率退火

在训练深度网络的时候,让学习率随着时间退火通常是有帮助的。可以这样理解:如果学习率很高,系统的动能就过大,参数向量就会无规律地跳动,不能够稳定到损失函数更深更窄的部分去。知道什么时候开始衰减学习率是有技巧的:慢慢减小它,可能在很长时间内只能是浪费计算资源地看着它混沌地跳动,实际进展很少。但如果快速地减少它,系统可能过快地失去能量,不能到达原本可以到达的最好位置。通常,实现学习率退火有3种方式

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

在实践中,我们发现随步数衰减的随机失活(dropout)更受欢迎,因为它使用的超参数(衰减系数和以周期为时间单位的步数)比更有解释性。最后,如果你有足够的计算资源,可以让衰减更加缓慢一些,让训练时间更长些。

二阶方法

在深度网络背景下,第二类常用的最优化方法是基于牛顿法的,其迭代如下:

这里是Hessian矩阵,它是函数的二阶偏导数的平方矩阵。是梯度向量,这和梯度下降中一样。直观理解上,Hessian矩阵描述了损失函数的局部曲率,从而使得可以进行更高效的参数更新。具体来说,就是乘以Hessian转置矩阵可以让最优化过程在曲率小的时候大步前进,在曲率大的时候小步前进。需要重点注意的是,在这个公式中是没有学习率这个超参数的,这相较于一阶方法是一个巨大的优势。

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

然而,即使解决了存储空间的问题,L-BFGS应用的一个巨大劣势是需要对整个训练集进行计算,而整个训练集一般包含几百万的样本。和小批量随机梯度下降(mini-batch SGD)不同,让L-BFGS在小批量上运行起来是很需要技巧,同时也是研究热点。

实践。在深度学习和卷积神经网络中,使用L-BFGS之类的二阶方法并不常见。相反,基于(Nesterov的)动量更新的各种随机梯度下降方法更加常用,因为它们更加简单且容易扩展。

参考资料:

  • Large Scale Distributed Deep Networks 一文来自谷歌大脑团队,比较了在大规模数据情况下L-BFGS和SGD算法的表现。

  • SFO算法想要把SGD和L-BFGS的优势结合起来。

逐参数适应学习率方法

前面讨论的所有方法都是对学习率进行全局地操作,并且对所有的参数都是一样的。学习率调参是很耗费计算资源的过程,所以很多工作投入到发明能够适应性地对学习率调参的方法,甚至是逐个参数适应学习率调参。很多这些方法依然需要其他的超参数设置,但是其观点是这些方法对于更广范围的超参数比原始的学习率方法有更良好的表现。下面介绍一些在实践中可能会遇到的常用适应算法:

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

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

注意,变量cache的尺寸和梯度矩阵的尺寸是一样的,还跟踪了每个参数的梯度的平方和。这个一会儿将用来归一化参数更新步长,归一化是逐元素进行的。注意,接收到高梯度值的权重更新的效果被减弱,而接收到低梯度值的权重的更新效果将会增强。有趣的是平方根的操作非常重要,如果去掉,算法的表现将会糟糕很多。用于平滑的式子eps(一般设为1e-4到1e-8之间)是防止出现除以0的情况。Adagrad的一个缺点是,在深度学习中单调的学习率被证明通常过于激进且过早停止学习。

都是一种权值更新算法,类似于SGD算法,其中,RMSProp是RProp算法的改良版。

RProp算法

  1. 首先为各权重变化赋一个初始值,设定权重变化加速因子与减速因子。
  2. 在网络前馈迭代中当连续误差梯度符号不变时,采用加速策略,加快训练速度;当连续误差梯度符号变化时,采用减速策略,以期稳定收敛。
  3. 网络结合当前误差梯度符号与变化步长实现BP,同时,为了避免网络学习发生振荡或下溢,算法要求设定权重变化的上下限。

不同权值参数的梯度的数量级可能相差很大,因此很难找到一个全局的学习步长。 
靠参数梯度的符号,动态的调节学习步长 
适用于full-batch learning,不适用于mini-batch learning

缺点:不能应用于mini-batch learning中。 
原因:

假设有一个在线学习系统,batch==1,初始的学习步长较小,在其上应用prop算法。这里有十组训练数据,前九组都使得梯度符号与之前的梯度符号相同,那么学习步长就会增加九次;而第十次得来的梯度符号与之前的相反,那么学习步长就会减小一次。这样一个过程下来,学习步长会增长很多(增大了9次学习步长,只减小了一次学习步长),如果系统的训练数据集非常之大,那学习步长可能频繁的来回波动,这样肯定是不利于学习的。

改进版,rmsprop算法:

RMSprop。是一个非常高效,但没有公开发表的适应性学习率方法。有趣的是,每个使用这个方法的人在他们的论文中都引用自Geoff Hinton的Coursera课程的第六课的第29页PPT。这个方法用一种很简单的方式修改了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变量是不同的。因此,RMSProp仍然是基于梯度的大小来对每个权重的学习率进行修改,这同样效果不错。但是和Adagrad不同,其更新不会让学习率单调变小。

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很像,除了使用的是平滑版的梯度m,而不是用的原始梯度向量dx。论文中推荐的参数值eps=1e-8, beta1=0.9, beta2=0.999。在实际操作中,我们推荐Adam作为默认的算法,一般而言跑起来比RMSProp要好一点。但是也可以试试SGD+Nesterov动量。完整的Adam更新算法也包含了一个偏置(bias)矫正机制,因为m,v两个矩阵初始为0,在没有完全热身之前存在偏差,需要采取一些补偿措施。建议读者可以阅读论文查看细节,或者课程的PPT。

Nadam

最后是Nadam。我们说Adam是集大成者,但它居然遗漏了Nesterov,这还能忍?必须给它加上,按照NAG的步骤1:

这就是Nesterov + Adam = Nadam了。

说到这里,大概可以理解为什么j经常有人说 Adam / Nadam 目前最主流、最好用的优化算法了。新手上路,先拿来一试,收敛速度嗖嗖滴,效果也是杠杠滴。

那为什么Adam还老招人黑,被学术界一顿鄙夷?难道只是为了发paper灌水吗?

总结:

  • momentum主要就是,累计了之前的梯度,如果当前梯度和累计的梯度方向一致,则增大学习率,如果不一致就减小学习率,也就是相当于如果 是一个斜坡,就加大步伐,作用就是,可以加速收敛,(因为还累计了之前的梯度),而nes momentum相当于前移一点,比如你落入一个局部最优被堵住了,在一个小山坡里,你走前移一点(这个前移是累累积的梯度作为前移的步伐)走上山坡去看一下,说不定就能走出局部最优。
  • Adagrad就是将之前的梯度平方累积起来,然后用学习率去除这些平方和开根号,可以让学习率逐渐下降,
  • 为什么要下降呢?因为越到后面越接近最优点,到了后阶段,如果你迈的步子太大,就有可能错过最优点
  • 但是有个缺点就是下降太快了,所以就有了RMSProp这个,在平方和前面加了权重,导致学习率下降的没那么快,
  • ADAM就是把一阶动量加了上去,
  • NADAM就是把NES这个动量加速也加了上去,
  • 现在供人最好的还是ADAM,NADAM,但是有缺陷,比如不容易收敛,因为学习率忽大忽小,容易陷入局部最优,至于为什么详细请看点击打开链接,但是具体的我还没太看懂,但是调参的时候有一个经研就是,将ADAM和sgd一起用,用ADAM在前半阶段加速,sgd在后半阶段自己精调,这个之前那个连接里面也有。
  • 还有一个就是full batch 适合用prop,因为训练一个神经网络肯定需要很多epoches,所以用全数据集,每次训练的话梯度变化不大,大概方向差不多,但是min batch就不适合,因为不同的Mini bacth之间有差异,所以每次训练后的梯度方向可能不一致,学习率忽大忽小,容易造成不收敛。
  • Momentum是为了对冲mini-batch带来的抖动。

    RMSprop是为了对hyper-parameter进行归一。这两个加起来就是Adam了 转自https://www.zhihu.com/question/55843162

转载:https://zhuanlan.zhihu.com/p/21798784?refer=intelligentunit

https://zhuanlan.zhihu.com/p/32262540

【深度学习 学习率,优化器】——深刻解读训练网络时各种学习率,优化器的区别,learning rate, Momentum相关推荐

  1. 深度学习笔记第二门课 改善深层神经网络 第二周:优化算法

    本文是吴恩达老师的深度学习课程[1]笔记部分. 作者:黄海广[2] 主要编写人员:黄海广.林兴木(第四所有底稿,第五课第一二周,第三周前三节).祝彦森:(第三课所有底稿).贺志尧(第五课第三周底稿). ...

  2. 文本深度表示模型Word2Vec 简介 Word2vec 是 Google 在 2013 年年中开源的一款将词表征为实数值向量的高效工具, 其利用深度学习的思想,可以通过训练,把对文本内容的处理简

    文本深度表示模型Word2Vec 简介 Word2vec 是 Google 在 2013 年年中开源的一款将词表征为实数值向量的高效工具, 其利用深度学习的思想,可以通过训练,把对文本内容的处理简化为 ...

  3. 【转】[caffe]深度学习之图像分类模型AlexNet解读

    [caffe]深度学习之图像分类模型AlexNet解读 原文地址:http://blog.csdn.net/sunbaigui/article/details/39938097 本文章已收录于:  深 ...

  4. 深度学习教程(10) | 卷积神经网络解读(吴恩达·完整版)

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/35 本文地址:http://www.showmeai.tech/article-det ...

  5. 3月13日云栖精选夜读:通过阿里云容器服务深度学习解决方案上手Caffe+多GPU训练

    阿里云容器服务提供的深度学习解决方案内置了对Tensorflow, Keras, MXnet框架的环境,并支持基于它们的深度学习模型开发.模型训练和模型预测.同时,对于模型训练和预测,用户还可以通过指 ...

  6. 3月13日云栖精选夜读:通过阿里云容器服务深度学习解决方案上手Caffe+多GPU训练...

    阿里云容器服务提供的深度学习解决方案内置了对Tensorflow, Keras, MXnet框架的环境,并支持基于它们的深度学习模型开发.模型训练和模型预测.同时,对于模型训练和预测,用户还可以通过指 ...

  7. 深度学习R语言 mlr3 建模,训练,预测,评估(随机森林,Logistic Regression)

    深度学习R语言 mlr3 建模,训练,预测,评估(随机森林,Logistic Regression) 本文主要通过使用mlr3包来训练German credit数据集,实现不同的深度学习模型. 1. ...

  8. 【深度学习】基于PyTorch的模型训练实用教程之数据处理

    [深度学习]基于PyTorch的模型训练实用教程之数据处理 文章目录 1 transforms 的二十二个方法 2 数据加载和预处理教程 3 torchvision 4 如何用Pytorch进行文本预 ...

  9. [caffe]深度学习之图像分类模型VGG解读

    一.简单介绍 vgg和googlenet是2014年imagenet竞赛的双雄,这两类模型结构有一个共同特点是go deeper.跟googlenet不同的是.vgg继承了lenet以及alexnet ...

最新文章

  1. Excel中配置VBA的工作环境
  2. mongo connections url string 的问题
  3. docker卸载命令_Docker入门篇
  4. 【图像处理】——遍历图像所有像素的方法(for 循环和np.where遍历)应用在模板制作
  5. 嵌入式linux图形系统设计,轻量级嵌入式Linux图形系统设计与实现
  6. java replacefirst第n_Java中replace()、replaceFirst()和replaceAll()区别
  7. 语言课设医院诊疗系统_江苏孤独症孩子有哪些典型特征?上海六一儿童医院
  8. python软件测试面试题及答案_软件测试面试 | 一道大厂算法面试真题,你能答上来吗?(附答案)...
  9. 使用Live555类库实现的网络直播系统
  10. 把项目通过maven生产源码包和文档包并发布到自己的私服上
  11. 为什么一定要重视隐式反馈?
  12. 新浪微博html5,新浪微博接入Html5游戏 注重轻量碎片化
  13. JAVA:实现crc校验算法(附完整源码)
  14. Base64、32、16 编码解析
  15. freyja v2版本发布
  16. 学生服务器是什么?学生服务器有什么用?
  17. 双球坐标系_【天文】教你认识三大天球坐标系!(上)
  18. FFmpeg超低延迟视频推流笔记
  19. vagrant给vmbox创建虚拟机及docker安装mysql和redis
  20. 【复杂句的逻辑练习题】规则变化的过去分词

热门文章

  1. kde4实在是太漂亮了
  2. 【前端开发 | 实例】网页中实现 js 繁体简体切换
  3. NLP-生成模型-2017-PGNet:Seq2Seq+Attention+Coverage+Copy【Coverage解决解码端重复解码问题;Copy机制解决解码端OOV问题】【抽取式+生成式】
  4. 高级软件工程第六次作业:“希希敬敬对”团队作业-3
  5. JDBC 学习笔记3
  6. 图片局部无失真放大的两种方式
  7. 学计算机颈椎痛,有效缓解颈椎疼痛的七个简单动作及附图 (电脑族必备)
  8. Aspectj some problems
  9. 网站设计的理念与方法
  10. 基于arcpy开发arcgis工具