如何选择深度学习优化器

前言

转载地址:如何选择深度学习优化器
作者:不会停的蜗牛 CSDN AI专栏作家

在很多机器学习和深度学习的应用中,我们发现用的最多的优化器是 Adam,为什么呢?

下面是 TensorFlow 中的优化器,
https://www.tensorflow.org/api_guides/python/train

这里写图片描述

在 keras 中也有 SGD,RMSprop,Adagrad,Adadelta,Adam 等:
https://keras.io/optimizers/

我们可以发现除了常见的梯度下降,还有 Adadelta,Adagrad,RMSProp 等几种优化器,都是什么呢,又该怎么选择呢?

在 Sebastian Ruder 的这篇论文中给出了常用优化器的比较,今天来学习一下:
https://arxiv.org/pdf/1609.04747.pdf

本文将梳理

  • 每个算法的梯度更新规则和缺点
  • 为了应对这个不足而提出的下一个算法
  • 超参数的一般设定值
  • 几种算法的效果比较
  • 选择哪种算法

优化器算法简述

首先来看一下梯度下降最常见的三种变形 BGD,SGD,MBGD,
这三种形式的区别就是取决于我们用多少数据来计算目标函数的梯度,
这样的话自然就涉及到一个 trade-off,即参数更新的准确率和运行时间。

1. Batch gradient descent

梯度更新规则:

BGD 采用整个训练集的数据来计算 cost function 对参数的梯度:
这里写图片描述

缺点:
由于这种方法是在一次更新中,就对整个数据集计算梯度,所以计算起来非常慢,遇到很大量的数据集也会非常棘手,而且不能投入新数据实时更新模型

for i in range(nb_epochs):params_grad = evaluate_gradient(loss_function, data, params)params = params - learning_rate * params_grad

我们会事先定义一个迭代次数 epoch,首先计算梯度向量 params_grad,然后沿着梯度的方向更新参数 params,learning rate 决定了我们每一步迈多大。

Batch gradient descent 对于凸函数可以收敛到全局极小值,对于非凸函数可以收敛到局部极小值。

2. Stochastic gradient descent

梯度更新规则:
和 BGD 的一次用所有数据计算梯度相比,SGD 每次更新时对每个样本进行梯度更新,
对于很大的数据集来说,可能会有相似的样本,这样 BGD 在计算梯度时会出现冗余,
而 SGD 一次只进行一次更新,就没有冗余,而且比较快,并且可以新增样本。
这里写图片描述

for i in range(nb_epochs):np.random.shuffle(data)for example in data:params_grad = evaluate_gradient(loss_function, example, params)params = params - learning_rate * params_grad

看代码,可以看到区别,就是整体数据集是个循环,其中对每个样本进行一次参数更新。

缺点:

但是 SGD 因为更新比较频繁,会造成 cost function 有严重的震荡。
这里写图片描述

BGD 可以收敛到局部极小值,当然 SGD 的震荡可能会跳到更好的局部极小值处。

当我们稍微减小 learning rate,SGD 和 BGD 的收敛性是一样的。

3. Mini-batch gradient descent

梯度更新规则:
MBGD 每一次利用一小批样本,即 n 个样本进行计算。这样它可以降低参数更新时的方差,收敛更稳定。另一方面可以充分地利用深度学习库中高度优化的矩阵操作来进行更有效的梯度计算。
这里写图片描述
和 SGD 的区别是每一次循环不是作用于每个样本,而是具有 n 个样本的批次

for i in range(nb_epochs):np.random.shuffle(data)for batch in get_batches(data, batch_size=50):params_grad = evaluate_gradient(loss_function, batch, params)params = params - learning_rate * params_grad

超参数设定值:

n 一般取值在 50~256

缺点:

不过 Mini-batch gradient descent 不能保证很好的收敛性:

  • learning rate 如果选择的太小,收敛速度会很慢,如果太大,loss function 就会在极小值处不停地震荡甚至偏离。
    有一种措施是先设定大一点的学习率,当两次迭代之间的变化低于某个阈值后,就减小 learning rate,不过这个阈值的设定需要提前写好,这样的话就不能够适应数据集的特点。

  • 此外,这种方法是对所有参数更新时应用同样的 learning rate,如果我们的数据是稀疏的,我们更希望对出现频率低的特征进行大一点的更新。

  • 另外,对于非凸函数,还要避免陷于局部极小值处,或者鞍点处,因为鞍点周围的error 是一样的,所有维度的梯度都接近于0,SGD 很容易被困在这里。

鞍点就是:一个光滑函数的鞍点邻域的曲线,曲面,或超曲面,都位于这点的切线的不同边。

例如这个二维图形,像个马鞍:在x-轴方向往上曲,在y-轴方向往下曲,鞍点就是(0,0)
这里写图片描述

为了应对上面的三点挑战就有了下面这些算法。

[应对挑战 1]

4. Momentum

SGD 在 ravines 的情况下容易被困住, ravines 就是曲面的一个方向比另一个方向更陡,这时 SGD 会发生震荡而迟迟不能接近极小值:
这里写图片描述

梯度更新规则:

Momentum 通过加入 γvt1 ,可以加速 SGD, 并且抑制震荡

这里写图片描述

当我们将一个小球从山上滚下来时,没有阻力的话,它的动量会越来越大,但是如果遇到了阻力,速度就会变小。

加入的这一项,可以使得梯度方向不变的维度上速度变快,梯度方向有所改变的维度上的更新速度变慢,这样就可以加快收敛并减小震荡。

超参数设定值:

一般 γ 取值 0.9 左右。

缺点:

这种情况相当于小球从山上滚下来时是在盲目地沿着坡滚,如果它能具备一些先知,例如快要上坡时,就知道需要减速了的话,适应性会更好。

5. Nesterov accelerated gradient

梯度更新规则:
这里写图片描述
θγvt1 来近似当做参数下一步会变成的值,则在计算梯度时,不是在当前位置,而是未来的位置上

超参数设定值:

γ仍然取值 0.9 左右。

效果比较:
这里写图片描述

蓝色是 Momentum 的过程,会先计算当前的梯度,然后在更新后的累积梯度后会有一个大的跳跃。

而 NAG 会先在前一步的累积梯度上(brown vector)有一个大的跳跃,然后衡量一下梯度做一下修正(red vector),这种预期的更新可以避免我们走的太快。

NAG 可以使 RNN 在很多任务上有更好的表现。

目前为止,我们可以做到,在更新梯度时顺应 loss function 的梯度来调整速度,并且对 SGD 进行加速。

我们还希望可以根据参数的重要性而对不同的参数进行不同程度的更新。

[应对挑战 2]

6. Adagrad

这个算法就可以对低频的参数做较大的更新,对高频的做较小的更新,也因此,对于稀疏的数据它的表现很好,很好地提高了 SGD 的鲁棒性,例如识别 Youtube 视频里面的猫,训练 GloVe word embeddings,因为它们都是需要在低频的特征上有更大的更新。

梯度更新规则:
这里写图片描述

其中 g 为:t 时刻参数 θi的梯度
这里写图片描述

如果是普通的 SGD, 那么θi在每一时刻的梯度更新公式为:

这里写图片描述
但这里的 learning rate η 也随 ti而变:
这里写图片描述

其中Gt是个对角矩阵, (i,i) 元素就是t 时刻参数θi的梯度平方和。

Adagrad 的优点是减少了学习率的手动调节

超参数设定值:

一般η就取 0.01。

缺点:

它的缺点是分母会不断积累,这样学习率就会收缩并最终会变得非常小。

7. Adadelta

这个算法是对 Adagrad 的改进,和 Adagrad 相比,就是分母的G换成了过去的梯度平方的衰减平均值,
这里写图片描述

这个分母相当于梯度的均方根 root mean squared (RMS) ,所以可以用 RMS 简写:
这里写图片描述

其中 E 的计算公式如下,t 时刻的依赖于前一时刻的平均和当前的梯度:
这里写图片描述

梯度更新规则:

此外,还将学习率 η换成了 RMS[Δθ],这样的话,我们甚至都不需要提前设定学习率了:
这里写图片描述

超参数设定值:

γ 一般设定为 0.9,

8. RMSprop

RMSprop 是 Geoff Hinton 提出的一种自适应学习率方法。

RMSprop 和 Adadelta 都是为了解决 Adagrad 学习率急剧下降问题的,

梯度更新规则:

RMSprop 与 Adadelta 的第一种形式相同:
这里写图片描述

超参数设定值:

Hinton 建议设定 γ为 0.9, 学习率η为 0.001。

9. Adam

这个算法是另一种计算每个参数的自适应学习率的方法。

除了像 Adadelta 和 RMSprop 一样存储了过去梯度的平方vt 的指数衰减平均值 ,也像 momentum 一样保持了过去梯度 mt的指数衰减平均值:

这里写图片描述

如果 mtvt被初始化为 0 向量,那它们就会向 0 偏置,所以做了偏差校正,
通过计算偏差校正后的 mtvt来抵消这些偏差:

这里写图片描述

梯度更新规则:

这里写图片描述

超参数设定值:

建议 β10.9β20.999ϵ10e8

实践表明,Adam 比其他适应性学习方法效果要好。

效果比较

下面看一下几种算法在鞍点和等高线上的表现:

SGD optimization on saddle point

SGD optimization on loss surface contours

上面两种情况都可以看出,Adagrad, Adadelta, RMSprop 几乎很快就找到了正确的方向并前进,收敛速度也相当快,而其它方法要么很慢,要么走了很多弯路才找到。

由图可知自适应学习率方法即 Adagrad, Adadelta, RMSprop, Adam 在这种情景下会更合适而且收敛性更好。

如何选择

如果数据是稀疏的,就用自适用方法,即 Adagrad, Adadelta, RMSprop, Adam。

RMSprop, Adadelta, Adam 在很多情况下的效果是相似的。

Adam 就是在 RMSprop 的基础上加了 bias-correction 和 momentum,

随着梯度变的稀疏,Adam 比 RMSprop 效果会好。

整体来讲,Adam 是最好的选择。

很多论文里都会用 SGD,没有 momentum 等。SGD 虽然能达到极小值,但是比其它算法用的时间长,而且可能会被困在鞍点。

如果需要更快的收敛,或者是训练更深更复杂的神经网络,需要用一种自适应的算法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246648.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【caffe-Windows】以mnist为例的hdf5单标签处理——matlab实现

前言 主要是想尝试看一下多标签的caffe是如何进行输入输出的,但是目前还未找到基于原始caffe做多标签输入的代码,大部分都是基于源码做了一部分修改实现多标签分类,caffe官网倒是有一个多标签的Python程序,这个我慢慢研究研究&am…

【caffe-Windows】基于Python多标签方法——VOC2012数据集

前言 按照上一篇博客所遗留的话题:多标签分类,进行初步探索,此篇博客针对caffe官网的多分类进行配置,只不过是Python接口的,不过官网在开头说明可以使用HDF5或者LMDB进行操作,只不过Python更加方便罢了 国…

【theano-windows】学习笔记一——theano中的变量

前言 因为目前需要搭建一些关于RBM或者其他之类的模型,感觉不太会折腾caffe,然而我发现了几个有趣网址,使用theano实现了各种各样的模型,所以,尝试学一下theano。主要以官方教程为主,所以博客会以译文的方…

【theano-windows】学习笔记二——theano中的函数和共享参数

前言 上一篇博客中学到了theano中的变量类型,也就是dscalar、dvector之类的, 然后还有一个theano.function和eval函数, 将我们所定义的操作转换成theano可执行的函数,类似于def, 还有就是简单的线性代数运算操作。 在神经网络(NN)中, 我们声明了权重、…

【theano-windows】学习笔记三——theano中的导数

前言 就一个NN而言,包含梯度、偏置、参数更新,而前面第一篇博客学习了theano中符号变量的定义, 第二篇博客学习了变量的随机初始化, 变量之间的互相操作(类似于sigmoid(w∗xb)), 但是参数更新还应涉及到损失函数的偏导计算,这一章节就是看看…

【theano-windows】学习笔记四——theano中的条件语句

前言 按照官网教程,学习条件语句Switch和ifelse的使用 参考地址: conditions 性能对比 ifElse是将布尔变量和两个变量当做输入 Switch是将张量和两个变量当做输入. 因为Switch是元素级操作,所以比ifElse更具一般性 Switch需要对所有输出变量进行评…

【theano-windows】学习笔记五——theano中张量部分函数

前言 至此感觉应该可以写出一个logistic回归程序了,但是为了达到对theano中张量的更灵活的使用, 还是先看一下thenao.tensor对变量都提供了哪些操作,最全的文档戳这里或者这里, 这里就稍微摘取一点自我感觉以后可能用得多的函数 基本张量函数 创建张量…

【theano-windows】学习笔记六——theano中的循环函数scan

前言 Scan是Theano中最基础的循环函数, 官方教程主要是通过大量的例子来说明用法. 不过在学习的时候我比较习惯先看看用途, 然后是参数说明, 最后再是研究实例. 国际惯例, 参考网址 官网关于Scan的11个例子 官网更全面的介绍 简介 用途 递归的一般形式, 可以被用于循环s…

多标签分类、多任务分类、多输出回归概念

前言 虽然不是搞分类的,但是还是看看多标签和多分类的区别。为了避免自己的错误理解, 当然是选择原谅他啊…….找正规文档看哇. 以下翻译分别来自scikit-learn.org和 维基 喂鸡百科 国际惯例,贴上来源: Multiclass and multilabel algorithms Multi-…

【theano-windows】学习笔记七——logistic回归

前言 前面只是学了最基本的theano操作,但是theano中还有很多其他的东西,比如图结构,自定义函数等,这些暂时没有用到就先不看了,后续学啥用啥,没必要一口气吃个胖子,免得消化不良还把前面吃的东…

【theano-windows】学习笔记八——预备知识

前言 按照上一个博客所说的,直接按照深度学习0.1文档进行学习,当然在此之前我们需要了解这一系列教程所需要的数据集,以及一些概念性的东西 国际惯例,参考博客网址: 深度学习0.1文档 深度学习0.1文档-中文翻译 基…

【theano-windows】学习笔记九——softmax手写数字分类

前言 上一篇博客折腾了数据集的预备知识, 接下来按照官方的Deep learning 0.1 documentation一步步走, 先折腾softmax, 关于softmax和logistic回归分类的联系, 我在之前写过一个小博客 国际惯例, 参考博客走一波: Classifying MNIST digits using Logistic Regression soft…

【theano-windows】学习笔记十——多层感知机手写数字分类

前言 上一篇学习了softmax, 然后更进一步就是学习一下基本的多层感知机(MLP)了. 其实多层感知机同时就是w*xb用某个激活函数激活一下, 得到的结果作为下一层神经元的输入x, 类似于 output⋯f3(f2(f1(x∗w1b2)∗w2b2)∗w3b3)⋯output=\cdots f^3(f^2(f^1(x*w^1+b^2)*w^2+b^2)*…

【theano-windows】学习笔记十一——theano中与神经网络相关函数

前言 经过softmax和MLP的学习, 我们发现thenao.tensor中除了之前的博客【theano-windows】学习笔记五——theano中张量部分函数提到的张量的定义和基本运算外, 还有一个方法称为nnet, 如果自己实现过前面两篇博客中的代码就会发现用到了theano.tensor.nnet.sigmoid和thenao.te…

【caffe-windows】全卷积网络特征图分析

前言 突然就想分析一下全卷积网络的转置卷积部分了, 就是这么猝不及防的想法, 而且这个网络对图片的输入大小无要求,这么神奇的网络是时候分析一波了,我个人的学习方法调试代码,然后对照论文看理论 本次分析主要针对每层的权重大小和特征图…

【theano-windows】学习笔记十二——卷积神经网络

前言 按照进度, 学习theano中的卷积操作 国际惯例, 来一波参考网址 Convolutional Neural Networks (LeNet) 卷积神经网络如何应用在彩色图像上? 卷积小知识 三大特性:局部感知(稀疏连接), 权值共享, 池化 上图很重要, 描述的是前一个隐层m-1具有四…

【theano-windows】学习笔记十三——去噪自编码器

前言 上一章节学习了卷积的写法,主要注意的是其实现在theano.tensor.nnet和theano.sandbox.cuda.dnn中都有对应函数实现, 这一节就进入到无监督或者称为半监督的网络构建中. 首先是自编码器(Autoencoders)和降噪自编码器(denoising Autoencoders) 国际惯例, 参考网址: Denoi…

梯度优化算法Adam

前言 最近读一个代码发现用了一个梯度更新方法, 刚开始还以为是什么奇奇怪怪的梯度下降法, 最后分析一下是用一阶梯度及其二次幂做的梯度更新。网上搜了一下, 果然就是称为Adam的梯度更新算法, 全称是:自适应矩估计(adaptive moment estimation) 国际惯例, 参考博文: 一文看…

读写bin

前言 工程中经常将参数文件存储为bin格式, 但是实际中为了分析其参数, 也不好用C去读取调试它, 所以可以用matlab或者python去读取它, 但是还是蛮坑的 Matlab中的读取和写入 写入文件 比较坑的是, 一定要注意自己的文件存储的类型, 比如数值是float还是double之类的, 不然很…

【theano-windows】学习笔记十四——堆叠去噪自编码器

前言 前面已经学习了softmax,多层感知器,CNN,AE,dAE,接下来可以仿照多层感知器的方法去堆叠自编码器 国际惯例,参考文献: Stacked Denoising Autoencoders (SdA) Greedy Layer-Wise Training of Deep Networks 理…