转载自:https://blog.csdn.net/u012151283/article/details/78154917

梯度下降沿着整个训练集的梯度方向下降。可以使用随机梯度下降很大程度地加速,沿着随机挑选的小批量数据的梯度下降。

批量算法和小批量算法

使用小批量的原因

  • n个样本均值的标准差是σn√σn,其中σσ是样本值真实的标准差。分母n−−√n表明使用更多的样本来估计梯度的方法的回报是低于线性的。
  • 另一个促使从小数目样本中获得梯度的统计估计的动机是训练集的冗余。大量样本可能对梯度做出了非常相似的贡献。
  • 可能是由于小批量在学习过程中加入了噪声,它们会有一些正则化效果。

其他

  • 鲁棒性
    不同的算法使用不同的方法从小批量中获取不同的信息。有些算法对采样误差比其他算法更敏感,这通常有两个原因。一个是它们使用了很难在少量样本上精确估计的信息,另一个是它们以放大采样误差的方式使用了信息。
    基于梯度gg的更新方法通常相对鲁棒,并能使用较小的批量获得成功,如100。使用Hessian矩阵HH,计算如H−1gH−1g更新的二阶方法通常需要更大的批量,如10000。

  • 随机顺序
    小批量是随机抽取的这点也很重要。从一组样本中计算出梯度期望的无偏估计要求这些样本是独立的。在数据集中的顺序有很大影响的情况下,有必要在抽取小批量样本前打乱样本顺序。
    不以某种方式打乱样本顺序会极大地降低算法的性能。

  • 异步并行
    在计算小批量样本XX上最小化J(X)J(X)的更新时,同时可以计算其他小于样本上的更新。
  • 无重复样本,遵循真实泛化误差的梯度
    很多小批量随机梯度下降方法的实现都会打乱数据顺序一次,然后多次遍历数据来更新参数。第一次遍历,每个小批量样本都用来计算真实泛化误差的无偏估计。第二次遍历,估计将会是有偏的,因为重新抽取了已经用过的样本,而不是从和原先样本相同的数据生成分布中获取新的无偏的样本。
  • 在线学习中的SGD
    在线学习中,样本永远不会重复,每次更新的样本是从分布中采样获得的无偏样本。
  • 实际使用
    在实际使用中,除非训练集特别大,通常还是多次遍历训练集,额外的遍历会由于减小训练误差而得到足够的好处,以抵消其带来的训练误差和测试误差差距的增加。

基本算法

随机梯度下降SGD

SGD及其变种是深度学习中应用最多的优化算法。按照数据生成分布抽取m个小批量(独立同分布)样本,通过计算它们的梯度均值,我们可以得到梯度无偏估计。

SGD算法中的一个关键参数是学习率。在实践中,有必要随着时间的推移逐渐降低学习率。
将第k步迭代的学习率记作ϵkϵk。一般会线性衰减学习率直到第ττ次迭代:
ϵk=(1−α)ϵ0+αϵτϵk=(1−α)ϵ0+αϵτ
其中α=kτα=kτ。在ττ次迭代之后,一般使ϵϵ保持常数。
通常ϵτϵτ应设为大约ϵ0ϵ0的1%。
对于足够大的数据集,SGD可能会在处理整个训练集之前就收敛到最终测试集误差的某个固定容差范围内。
批量梯度下降在理论上比随机梯度下降有更好的收敛率。可以在学习过程中逐渐增大批量大大小,以此权衡批量梯度下降和随机梯度下降两者的优点。

带动量的SGD

指数加权平均数
vt=βvt−1+(1−β)θtvt=βvt−1+(1−β)θt
该公式利用过去11−β11−β项的θθ的加权平均来计算当前的vtvt
偏差修正
使用vt1−βtvt1−βt来对进行修正,当t比较大的时候,分母接近于1。
在机器学习中,一般不进行偏差修正,人们一般不使用初期的参数。

另一种形式

在实践中,动量参数一般取值为0.5,0.9和0.99。和学习率一样,αα也会随着时间不断调整。一般初始值是一个较小的值,随后会慢慢变大。随着时间调整αα没有收缩ϵϵ重要。

Nesterov动量

Nesterov动量中,梯度计算在施加当前速度之后。因此,Nesterov动量可以解释为往标准动量方法中添加了一个校正因子。

标准的动量方法(由Nesterov在1983年提出)是在当前位置计算梯度,然后在累积的更新梯度方向上做一个大的跳跃。下面给出了一种更好地动量方法(由IIya Sutskever在2012年提出),其先在先前累积的梯度方向上做一个大的跳跃,再计算新的梯度并修正错误。
下面对两种方法做了比较,图中蓝色箭头是做两次标准动量方法得到的;而图中棕色箭头是改进动量方法先做的一次大跳跃得到的,红色箭头是修正,绿色箭头是进行一次改进动量方法得到的。可以看到,改进的比标准的要快很多。

自适应学习率算法

习率算法

AdaGrad

AdaGrad独立地适应所有模型参数的学习率,缩放每个参数反比于其所有梯度历史平方值总和的平方根


在凸优化中,AdaGrad算法具有一些令人满意的理论性质。然而,经验上对于训练深度神经网络模型而言,从训练开始时积累梯度平方会导致有效学习率过早和过量减小。

AdaDelta

AdaGrad主要存在三个问题

  • 其学习率是单调递减的,训练后期学习率非常小
  • 其需要手工设置一个全局的初始学习率
  • 更新θθ时,左右两边的单位不同一

我们令每一个时刻的rr随之时间按照ρρ指数衰减,这样就相当于仅使用离当前时刻比较近的gg信息,不会使得rr增加过快,分母过大而导致参数更新减缓。在AdaDelta中,累积平方梯度定义为
r←ρr+(1−ρ)g⊙gr←ρr+(1−ρ)g⊙g
在计算更新时,用梯度历史该变量平方值期望的平方根代替学习率ηη,则得到Adadelta更新规则:

由此看出,甚至不需要设定缺省学习率,因为更新规则已经不受它影响了

RMSProp

RMSProp算法修改AdaGrad以在非凸设定下效果更好,改变梯度累积为指数加权的移动平均
AdaGrad旨在应用于凸问题时快速收敛。AdaGrad根据平方梯度的整个历史收缩学习率,可能使得学习率在达到这样的凸结构前就变得太小了。
RMSprop使用指数衰减平均来丢弃遥远过去的历史,使其在找到凸结构后快速收敛,就像一个初始化于该碗装结构的AdaGrad算法实例。
相比于AdaGrad,使用移动平均引入了一个新的超参数ρρ,用来控制移动平均的长度范围。

Adam

派生自短语”adaptive moments”
Adam被看作结合RMSProp和具有一些重要区别的动量的变种。
首先,Adam中动量直接并入梯度一阶矩(指数加权)的估计。
其次,Adam包括偏置修正,修泽和那个从原点初始化的一阶矩(动量项)和(非中心的)二阶矩的估计。RMSProp也采用了(非中心的)二阶矩估计,然而缺失了修正因子。因此,RMSProp二阶矩估计可能在训练初期有很高的偏置。

Adam通常被认为对超参数的选择相当鲁棒,尽管学习率有时需要遵从建议的默认参数0.001

二阶近似方法

牛顿法

牛顿法是基于二阶泰勒级数展开在某点θ0θ0附近来近似J(θ)J(θ)的优化方法,其忽略了高阶导数
J(θ)≈J(θ0)+(θ−θ0)T∇θJ(θ0)+12(θ−θ0)TH(θ−θ0)J(θ)≈J(θ0)+(θ−θ0)T∇θJ(θ0)+12(θ−θ0)TH(θ−θ0),
其中HH是JJ相对于θθ的Hessian矩阵在θ0θ0处的矩估计。通过求解这个函数的临界点,得到牛顿参数更新规则:
θ∗=θ0−H−1∇θJ(θ0)θ∗=θ0−H−1∇θJ(θ0)
因此,对于局部的二次函数(具有正定的H),用H−1H−1重新调整梯度,牛顿法会直接跳到极小值。如果目标函数是凸的但非二次的(有高阶项),该更新是迭代的。

共轭梯度

共轭梯度是一种通过迭代下降的共轭方向以有效避免Hessian矩阵求逆计算的方法。
在共轭梯段法中,我们寻求一个和先前线性搜索方向共轭的搜索方向,即它不会撤销该方向上的进展。在训练迭代t时,下一步的搜索方向dtdt的形式如下:
dt=∇θJ(θ)+βtdt−1dt=∇θJ(θ)+βtdt−1
其中,系数βtβt的大小控制我们应沿方向dt−1dt−1加回多少到当前搜索方向。
如果dTtHdt−1=0dtTHdt−1=0,其中HH是Hessian矩阵,则两个方向dtdt和dt−1dt−1被称为共轭的。

BFGS

Broyden-Fletcher-Goldfarb-Shanno(BFGS)算法具有牛顿法的一些优点,但没有牛顿法的计算负担。
http://blog.csdn.net/u012151283/article/details/78148890#t3
拟牛顿法采用矩阵MtMt近似逆,迭代地低秩更新精度以更好地近似H−1H−1。
当Hessian逆近似MtMt更新时,下降方向ρtρt为ρt=Mtgtρt=Mtgt。该方向上的线性搜索用于决定该方向上的步长ϵ∗ϵ∗。参数的最后更新为:
θt+1=θt+ϵ∗ρtθt+1=θt+ϵ∗ρt

相比于共轭梯度,BFGS的优点是其花费较少的时间改进每个线性搜索。在另一方面,BFGS算法必须存储Hessian逆矩阵M,需要O(n2)O(n2)的存储空间,使BFGS不适用于大多数具有百万级参数的现代深度学习模型。

L-BFGS

L-BFGS算法就是对拟牛顿算法的一个改进。L-BFGS算法的基本思想是:算法只保存并利用最近m次迭代的曲率信息来构造海森矩阵的近似矩阵。
LBFGS,起始假设是G(t−1)G(t−1)是单位矩阵,而不是每一步都要存储近似矩阵。每步存储一些用于更新GkGk的向量,且每步存储代价为O(n)O(n)。

BFGS算法关于GkGk的迭代形式如下
Gk+1=(I−skyTkyTksk)Gk(I−yksTkyTksk)+sksTkyTkskGk+1=(I−skykTykTsk)Gk(I−ykskTykTsk)+skskTykTsk

令ρk=1yTkskρk=1ykTsk,Vk=I−ρkyksTkVk=I−ρkykskT,则有
Gk+1=VTkGkVk+ρksksTkGk+1=VkTGkVk+ρkskskT
对于给定的G0=IG0=I,可以迭代地计算GkGk,GkGk的计算只依赖于[si,yi]ki=0[si,yi]i=0k。
L-BFGS算法通过存储最近连续的m组si,yisi,yi向量,来近似地计算GkGk。

批标准化

批标准化是一种自适应重参数化的方法,试图解决训练非常深的模型的困难。批标准化主要解决的是训练极深网络时梯度消失的问题。

BN起作用的原因

  1. 通过使得批量数据归一化具有0均值1方差的统计分布,避免数据处于激活函数的饱和区,具有较大的梯度,从而加速网络的训练过程。
  2. 减少了网络输入变化过大的问题,使得网络的输入稳定,减弱了与前层参数关系之间的作用,使得当前层独立于整个网络

BN具有轻微正则化的效果,可以和dropout一起使用
主要是归一化激活值前的隐藏单元来加速训练,正则化是副作用

BN具有正则化效果的原因

  1. 每个批量的数据仅根据当前批量计算均值和标准差,然后缩放
  2. 这就为该批量的激活函数带来了一些噪音,类似于dropout向每一层的激活函数带来噪音
  3. 若使用了较大的batch_size如512,则减小了噪音,减少了正则化带来的效果

训练过程中的算法


由于BN在最后重参数化过程中会学习得到一个γγ,所以神经网络中的bias可以省略掉。

推断时算法

由于在推断的时,batch的大小不能确定,很有可能1次只有一个样本,不通过对当前批量的数据的归一化来加速训练。作者提出使用训练数据集上的全部数据来计算均值和方差。通常出与计算效率考虑,使用滑动平均的方法来计算

tensorflow实现

使用tf.layers.batch_normalization可以快速实现BN算法。注意使用该API时在优化器调用时要加入以下代码:

update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)with tf.control_dependencies(update_ops):train_op = optimizer.minimize(loss)

这里还有一个我看到知乎匿名用户的实现,感觉比较清晰

from tensorflow.python.training.moving_averages import assign_moving_averagedef batch_norm(x, train, eps=1e-05, decay=0.9, affine=True, name=None):with tf.variable_scope(name, default_name='BatchNorm2d'):params_shape = tf.shape(x)[-1:]moving_mean = tf.get_variable('mean', params_shape,initializer=tf.zeros_initializer,trainable=False)moving_variance = tf.get_variable('variance', params_shape,initializer=tf.ones_initializer,trainable=False)def mean_var_with_update():mean, variance = tf.nn.moments(x, tf.shape(x)[:-1], name='moments')with tf.control_dependencies([assign_moving_average(moving_mean, mean, decay),assign_moving_average(moving_variance, variance, decay)]):return tf.identity(mean), tf.identity(variance)mean, variance = tf.cond(train, mean_var_with_update, lambda: (moving_mean, moving_variance))if affine:beta = tf.get_variable('beta', params_shape,initializer=tf.zeros_initializer)gamma = tf.get_variable('gamma', params_shape,initializer=tf.ones_initializer)x = tf.nn.batch_normalization(x, mean, variance, beta, gamma, eps)else:x = tf.nn.batch_normalization(x, mean, variance, None, None, eps)return x

优化策略和元算法

  • 坐标下降

参考资料

《深度学习》第8章
LBFGS算法笔记
知乎匿名用户回答BN的实现

深度学习中的优化方法总结相关推荐

  1. introduction to deep learning--week1简单线性回归、梯度下降、模型正则化、和深度学习中的优化方法

    进阶课程需要一些基础知识: 1.机器学习基础知识 2.概率论知识 3.线性代数和微积分 4.python编程 我们需要知道的机器学习基础知识: 1.线性回归:均方误差(MSE).解析解 2.逻辑回归: ...

  2. 深度学习中的优化方法-AdaGrad

    码字不易,转载请注明出处~ tags: optimizer;AdaGrad 本文来源于下面博客: https://medium.com/konvergen/an-introduction-to-ada ...

  3. 深度学习笔记:优化方法总结(BGD,SGD,Momentum,AdaGrad,RMSProp,Adam)

    深度学习笔记(一):logistic分类  深度学习笔记(二):简单神经网络,后向传播算法及实现  深度学习笔记(三):激活函数和损失函数  深度学习笔记:优化方法总结  深度学习笔记(四):循环神经 ...

  4. nfa确定化 dfa最小化_深度学习中的优化:梯度下降,确定全局最优值或与之接近的局部最优值...

    深度学习中的优化是一项极度复杂的任务,本文是一份基础指南,旨在从数学的角度深入解读优化器. 一般而言,神经网络的整体性能取决于几个因素.通常最受关注的是网络架构,但这只是众多重要元素之一.还有一个常常 ...

  5. 深度学习 | 训练及优化方法

    ---------------------------- 原文发表于夏木青 | JoselynZhao Blog,欢迎访问博文原文. ---------------------------- 深度学习 ...

  6. 深度学习算法(第5期)----深度学习中的优化器选择

    欢迎关注微信公众号"智能算法" – 原文链接(阅读体验更佳): 深度学习算法(第5期)----深度学习中的优化器选择 上一期,我们一起学习了TensorFlow在训练深度网络的时候 ...

  7. 深度学习中的优化算法之Adam

    之前在https://blog.csdn.net/fengbingchun/article/details/124909910 介绍过深度学习中的优化算法Adadelta,这里介绍下深度学习的另一种优 ...

  8. 深度学习中的优化算法之RMSProp

    之前在https://blog.csdn.net/fengbingchun/article/details/124766283 中介绍过深度学习中的优化算法AdaGrad,这里介绍下深度学习的另一种优 ...

  9. 深度学习中的优化算法串讲

    Datawhale原创 作者:谢文睿,Datawhale成员 寄语:优化算法是一个超参数,一个优化算法不是适合所有损失函数的,没有哪个优化算法是绝对的好或绝对的坏,是要根据损失函数判断的 本文对深度学 ...

最新文章

  1. c语言节点导入数据编程,编程小白。用C语言计算SR E2E ARQ模式下节点的数据分析...
  2. VC++ MFC DLL动态链接库编写详解
  3. 个人微信订阅号自定义菜单空白
  4. MFC中的DC,CDC和HDC
  5. MATLAB统计与回归
  6. 磁盘配额超出 linux,使用linux的warnquota命令发送邮件给超出配额的用户
  7. httpclient java 异步_Java的异步HttpClient
  8. 远程win10系统桌面时提示凭证不工作问题的终极解决办法
  9. 闽院食堂管理系统分析
  10. 服务器行业深度解析:服务器未来需求知多少
  11. 案例 | 省去繁琐简历筛选,「微伴助手」选择 ShowMeBug 在线笔试提高人才精准度
  12. SQLServer 启动问题,服务器错误代码126 解决办法
  13. python中while循环只能用来实现无限循环的编程_while循环只能实现无限循环的编程...
  14. 微信支付宝个人收款方法
  15. 如何找到联盟营销人员:招募合适会员的10个方法
  16. FileStream写入文件
  17. Vue—单页面应用与多页面应用的区别
  18. java 简单的调用类_java 调用 C# 类库搞定,三步即可,可以调用任何类及方法,很简单,非常爽啊...
  19. JavaScript字符串方法汇总
  20. 诺贝尔奖你知道多少呢?

热门文章

  1. js导出excel(js-export-excel)
  2. 页面打印、打印预览、页面设置
  3. 一起看视频打开后显示服务器异常,VS调试异常问题解决(一)
  4. 都快投票了,尼日利亚大选也要推迟,是否是被操纵了?
  5. 基于PCA主成分分析的BP神经网络回归预测MATLAB代码
  6. ANSYS Workbench结构分析网格划分的总体控制和局部控制解析
  7. STM32HAL----红外遥控(NEC)
  8. 项目管理五大流程及各环节要点
  9. Jsp+mysql 制作留言板
  10. IDEA-Java注释模板设置