版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010899985/article/details/81836299
梯度下降算法针对凸优化问题原则上是可以收敛到全局最优的,因为此时只有唯一的局部最优点。而实际上深度学习模型是一个复杂的非线性结构,一般属于非凸问题,这意味着存在很多局部最优点(鞍点),采用梯度下降算法可能会陷入局部最优,这应该是最头疼的问题。这点和进化算法如遗传算法很类似,都无法保证收敛到全局最优。因此,我们注定在这个问题上成为“高级炼丹师”。可以看到,梯度下降算法中一个重要的参数是学习速率,适当的学习速率很重要:学习速率过小时收敛速度慢,而过大时导致训练震荡,而且可能会发散。理想的梯度下降算法要满足两点:收敛速度要快;能全局收敛。为了这个理想,出现了很多经典梯度下降算法的变种,下面将分别介绍它们。
SGD
梯度下降算法(Gradient Descent Optimization)是神经网络模型训练最常用的优化算法。梯度下降算法背后的原理:目标函数J(θ)关于参数θ的梯度将是目标函数上升最快的方向,对于最小化优化问题,只需要将参数沿着梯度相反的方向前进一个步长(学习速率),就可以实现目标函数的下降。参数更新公式如下:
其中是参数的梯度。
根据计算目标函数J(θ)采用数据量的大小,梯度下降算法又可以分为批量梯度下降算法(Batch Gradient Descent),随机梯度下降算法(Stochastic GradientDescent)和小批量梯度下降算法(Mini-batch Gradient Descent)。
批量梯度下降算法,J(θ)是在整个训练集上计算的,如果数据集比较大,可能会面临内存不足问题,而且其收敛速度一般比较慢。
随机梯度下降算法,J(θ)是针对训练集中的一个训练样本计算的,又称为在线学习,即得到了一个样本,就可以执行一次参数更新。所以其收敛速度会快一些,但是有可能出现目标函数值震荡现象,因为高频率的参数更新导致了高方差。
小批量梯度下降算法,是折中方案,J(θ)选取训练集中一个小批量样本计算,这样可以保证训练过程更稳定,而且采用批量训练方法也可以利用矩阵计算的优势。这是目前最常用的梯度下降算法。
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(loss)
momentum
SGD方法的一个缺点是,其更新方向完全依赖于当前的batch,因而其更新十分不稳定,每次迭代计算的梯度含有比较大的噪音。解决这一问题的一个简单的做法便是引入momentum,momentum即动量,是BorisPolyak在1964年提出的,其基于物体运动时的惯性:将一个小球从山顶滚下,其初始速率很慢,但在加速度作用下速率很快增加,并最终由于阻力的存在达到一个稳定速率,即更新的时候在一定程度上保留之前更新的方向,同时利用 当前batch的梯度 微调最终的更新方向。这样一来,可以在一定程度上增加稳定性,从而学习地更快,并且还有一定摆脱局部最优的能力。
其更新方程如下:
可以看到,参数更新时不仅考虑当前梯度值,而且加上了一个动量项γm,但多了一个超参γ,通常γ设置为0.5,直到初始学习稳定,然后增加到0.9或更高。相比原始梯度下降算法,动量梯度下降算法有助于加速收敛。当梯度与动量方向一致时,动量项会增加,而相反时,动量项减少,因此动量梯度下降算法可以减少训练的震荡过程。
tf.train.MomentumOptimizer(learning_rate=learning_rate,momentum=0.9)
NAG
NAG(Nesterov Accelerated Gradient),,由Ilya Sutskever(2012 unpublished)在Nesterov工作的启发下提出的。对动量梯度下降算法的改进版本,其速度更快。其变化之处在于计算“超前梯度”更新动量项 γm,具体公式如下:
既然参数要沿着动量项 γm更新,不妨计算未来位置(θ -γm)的梯度,然后合并两项作为最终的更新项,其具体效果如图1所示,可以看到一定的加速效果。
 
momentum基础上设置 use_nesterov=True
tf.train.MomentumOptimizer(learning_rate=learning_rate,momentum=0.9, use_nesterov=True)
AdaGrad
AdaGrad是Duchi在2011年提出的一种学习速率自适应的梯度下降算法。在训练迭代过程,其学习速率是逐渐衰减的,经常更新的参数其学习速率衰减更快,这是一种自适应算法。其更新过程如下:
每步迭代过程:
从训练集中的随机抽取一批容量为m的样本{x1,…,xm},以及相关的输出yi
计算梯度和误差,更新r,再根据r和梯度计算参数更新量: 
 
其中,全局学习速率 ϵ, 初始参数 θ,梯度平方的累计量r初始化为0), δ(通常为10^−7)是为了防止分母的为 0。
由于梯度平方的累计量r逐渐增加的,那么学习速率是衰减的。考虑下图所示的情况,目标函数在两个方向的坡度不一样,如果是原始的梯度下降算法,在接近坡底时收敛速度比较慢。而当采用AdaGrad,这种情况可以被改善。由于比较陡的方向梯度比较大,其学习速率将衰减得更快,这有利于参数沿着更接近坡底的方向移动,从而加速收敛。对于每个参数,随着其更新的总距离增多,其学习速率也随之变慢。
缺点: 任然要设置一个变量ϵ ,经验表明,在普通算法中也许效果不错,但在深度学习中,深度过深时会造成训练提前结束。
tf.train.AdagradOptimizer(learning_rate=0.001).minimize(loss)
Adadelta
Adadelta是对Adagrad的扩展,最初方案依然是对学习率进行自适应约束,但是进行了计算上的简化。 
Adagrad会累加之前所有的梯度平方,而Adadelta只累加固定大小的项,并且也不直接存储这些项,仅仅是近似计算对应的平均值。即:
 
其中,η是学习率,gt 是梯度
在此处Adadelta其实还是依赖于全局学习率的,但是作者做了一定处理,经过近似牛顿迭代法之后:
其中,E代表求期望。此时,可以看出Adadelta已经不用依赖于全局学习率了。
tf.train.AdadeltaOptimizer(learning_rate=0.001).minimize(loss)
RMSProp 
RMSprop是对Adagrad算法的改进,主要是解决。其实思路很简单,类似Momentum思想,引入一个衰减系数,让梯度平方的累计量r 每回合都衰减一定比例:
其中,衰减系数ρ
decay: 衰减率
epsilon: 设置较小的值,防止分母的为 0.
tf.train.RMSPropOptimizer(learning_rate=0.001,momentum=0.9, decay=0.9, epsilon=1e-10)
优点: 
- 相比于AdaGrad,这种方法有效减少了出现梯度爆炸情况,因此避免了学习速率过快衰减的问题。 
- 适合处理非平稳目标,对于RNN效果很好
缺点: 
- 又引入了新的超参—衰减系数ρ 
- 依然依赖于全局学习速率,
总结:RMSprop算是Adagrad的一种发展,和Adadelta的变体,效果趋于二者之间。
Adam 
自适应矩估计(daptive moment estimation,Adam),是Kingma等在2015年提出的一种新的优化算法,本质上是带有动量项的RMSprop,其结合了Momentum和RMSprop算法的思想。它利用梯度的一阶矩估计 和 二阶矩估计 动态调整每个参数的学习率。
具体实现每步迭代过程:
从训练集中的随机抽取一批容量为m的样本{x1,…,xm},以及相关的输出yi
计算梯度和误差,更新r和s,再根据r和s以及梯度计算参数更新量 : 
其中,一阶动量s,二阶动量r(初始化为0),一阶动量衰减系数ρ1, 二阶动量衰减系数ρ2 
超参数的建议值是ρ1=0.9,ρ2 =0.999,epsilon: 设置较小的值,防止分母的为 0。
实践
各种优化方法在CIFAR-10图像识别上比较:
图片来源:The Marginal Value of Adaptive Gradient Methods in Machine Learning
自适应优化算法在训练前期阶段在训练集上收敛的更快,但是在测试集上反而并不理想。 
用相同数量的超参数来调参,SGD和SGD +momentum 方法性能在测试集上的额误差好于所有的自适应优化算法,尽管有时自适应优化算法在训练集上的loss更小,但是他们在测试集上的loss却依然比SGD方法高, 
总结:
对于稀疏数据,优先选择学习速率自适应的算法如RMSprop和Adam算法,而且最好采用默认值,大部分情况下其效果是较好的
SGD通常训练时间更长,容易陷入鞍点,但是在好的初始化和学习率调度方案的情况下,结果更可靠。
如果要求更快的收敛,并且较深较复杂的网络时,推荐使用学习率自适应的优化方法。例如对于RNN之类的网络结构,Adam速度快,效果好,而对于CNN之类的网络结构,SGD +momentum 的更新方法要更好(常见国际顶尖期刊常见优化方法).
Adadelta,RMSprop,Adam是比较相近的算法,在相似的情况下表现差不多。
在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果。
特别注意学习速率的问题。学习速率设置得非常大,那么训练可能不会收敛,就直接发散了;如果设置的比较小,虽然可以收敛,但是训练时间可能无法接受。理想的学习速率是:刚开始设置较大,有很快的收敛速度,然后慢慢衰减,保证稳定到达最优
其实还有很多方面会影响梯度下降算法,如梯度的消失与爆炸,梯度下降算法目前无法保证全局收敛还将是一个持续性的数学难题。
参考:
[1]Adagrad 
[2]RMSprop[Lecture 6e] 
[3]Adadelta 
[4]Adam 
[5]Nadam 
[6]On the importance of initialization and momentum in deep learning 
————————————————
版权声明:本文为CSDN博主「Charles_yy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u010899985/article/details/81836299

深度学习最全优化方法总结比较及在tensorflow实现的更多相关文章

  1. 深度学习最全优化方法总结比较(SGD,Adagrad,Adadelta,Adam,Adamax,Nadam)(转)

    转自: https://zhuanlan.zhihu.com/p/22252270    ycszen 另可参考: https://blog.csdn.net/llx1990rl/article/de ...

  2. 深度学习(九) 深度学习最全优化方法总结比较(SGD,Momentum,Nesterov Momentum,Adagrad,Adadelta,RMSprop,Adam)

    前言 这里讨论的优化问题指的是,给定目标函数f(x),我们需要找到一组参数x(权重),使得f(x)的值最小. 本文以下内容假设读者已经了解机器学习基本知识,和梯度下降的原理. SGD SGD指stoc ...

  3. [深度学习] 最全优化方法总结比较--SGD,Adagrad,Adadelta,Adam,Adamax,Nadam

    SGD 此处的SGD指mini-batch gradient descent,关于batch gradient descent, stochastic gradient descent, 以及 min ...

  4. 深度学习主机环境配置: Ubuntu16.04+GeForce GTX 1080+TensorFlow

    接上文<深度学习主机环境配置: Ubuntu16.04+Nvidia GTX 1080+CUDA8.0>,我们继续来安装 TensorFlow,使其支持GeForce GTX 1080显卡 ...

  5. 【深度学习】在linux和windows下anaconda+pycharm+tensorflow+cuda的配置

    在linux和windows下anaconda+pycharm+tensorflow+cuda的配置 在linux和windows下anaconda+pycharm+tensorflow+cuda的配 ...

  6. 深度学习之卷积神经网络(CNN)详解与代码实现(一)

    卷积神经网络(CNN)详解与代码实现 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/10430073.html 目 ...

  7. 【深度学习】关于Adam

    版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_31866177/articl ...

  8. 【转载】 深度学习之卷积神经网络(CNN)详解与代码实现(一)

    原文地址: https://www.cnblogs.com/further-further-further/p/10430073.html ------------------------------ ...

  9. Tensorflow 2.0 深度学习实战 —— 详细介绍损失函数、优化器、激活函数、多层感知机的实现原理

    前言 AI 人工智能包含了机器学习与深度学习,在前几篇文章曾经介绍过机器学习的基础知识,包括了监督学习和无监督学习,有兴趣的朋友可以阅读< Python 机器学习实战 >.而深度学习开始只 ...

随机推荐

  1. Vue事件修饰符,.capture关键字详解

    .prevent 用于阻止默认事件,点击a标签href可以打开相应的链接,那么给事件加    上此关键字,click.prevent .capture 冒泡顺序    例如 div1中嵌套div2中嵌 ...

  2. Cheat Engine 人造指针

    打开游戏 查看内存区域 查看游戏当前使用的内存区域 下面这一段是游戏当前使用的内存区域,选择一片可以读写的内存区域 跳转到这片内存 查看是否有空余内存可以使用 使用空闲内存 我们选择0075DFD0开 ...

  3. Cheat Engine 基本用法

    打开游戏 当前血量2620 打开Cheat Engine 扫描2620 掉点血 再次扫描2600 此时,会根据第一次扫描结果,再次扫描 扫描成功 将数据放到修改区,点击箭头 修改数据 双击Value进 ...

  4. SpringBoot学习<二>——SpringBoot的默认配置文件application和多环境配置

    一.SpringBoot的默认文件appliction 上一篇文章已经说明,springboot启动会内嵌tomcat,端口也是默认的8080,如果我们想要改变端口如果做呢? 在springboot项 ...

  5. Hibernate 5.x 生成 SessionFactory 源码跟踪分析

    我们要使用 Hibernate 的功能,首先需要读取 Hibernate 的配置文件,根据配置启动 Hibernate ,然后创建 SessionFactory. 创建 SessionFactory ...

  6. getResourceAsStream的路径问题

    1.Class类的getResourceAsStream this.getClass().getResourceAsStream("/resource.properties"); ...

  7. 【MySql】Update批量更新与批量更新多条记录的不同值实现方法

    mysql更新语句很简单,更新一条数据的某个字段,一般这样写: UPDATE mytable SET myfield = 'value' WHERE other_field = 'other_valu ...

  8. docker的小技巧记录(如果使用了更多会继续添加)

    docker小技巧 复制本地sql脚本到docker容器mysql中进行使用 # 找到容器 docker ps # 复制文件 cp ./xxx.sql container-id:/tmp/ # 进入容 ...

  9. [TJOI2018]最长上升子序列

    Link 动态维护LIS? 观察题目:在第 i 轮操作时,将数字 i 插入 插入的数字是当前最大的 如果答案与上次不同,新的LIS必以 i 结尾 以 i 结尾的LIS无法再伸长(因为比 i 小的都插入 ...

  10. 使用icepdf将pdf文件转换成照片(以及隐藏的一个bug)

    首先引入依赖: <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox ...