训练过程--梯度下降算法(SGD、adam等)

SGD系列

1)Batch gradient descent(批量梯度下降)

  在整个数据集上
  每更新一次权重,要遍历所有的样本,由于样本集过大,无法保存在内存中,无法线上更新模型。对于损失函数的凸曲面,可以收敛到全局最小值,对于非凸曲面,收敛到局部最小值。
  随机梯度下降(SGD)和批量梯度下降(BGD)的区别。SGD 从数据集中拿出一个样本,并计算相关的误差梯度,而批量梯度下降使用所有样本的整体误差:「关键是,在更新中没有随机或扩散性的行为。」

2)stochastic gradient descent(SGD,随机梯度下降)

  可以在线学习,收敛的更快,可以收敛到更精确的最小值。但是梯度更新太快,而且会产生梯度震荡,使收敛不稳定。
  随机梯度下降(SGD)和批量梯度下降(BGD)的区别。SGD 从数据集中拿出一个样本,并计算相关的误差梯度,而批量梯度下降使用所有样本的整体误差:「关键是,在更新中没有随机或扩散性的行为。」

3)Mini-batch gradient descent(MBGD,小批量梯度下降)

  批量梯度下降算法和随机梯度下降算法的结合体。两方面好处:一是减少更新的次数,使得收敛更稳定;二是利用矩阵优化方法更有效。
  当训练集有很多冗余时(类似的样本出现多次),batch方法收敛更快。
  以一个极端情况为例,若训练集前一半和后一半梯度相同。那么如果前一半作为一个batch,后一半作为另一个batch,那么在一次遍历训练集时,batch的方法向最优解前进两个step,而整体的方法只前进一个step。

三种SGD的对比

  批量梯度下降法BGD:批量梯度下降法(Batch Gradient Descent,简称BGD)是梯度下降法最原始的形式,它的具体思路是在更新每一参数时都使用所有的样本来进行更新。
  随机梯度下降法SGD:
  小批量梯度下降法MBGD:有上述的两种梯度下降法,其各自均有优缺点,那么能不能在两种方法的性能之间取得一个折衷呢?即,算法的训练过程比较快,而且也要保证最终参数训练的准确率,而这正是小批量梯度下降法(Mini-batch Gradient Descent,简称MBGD)的初衷。

  最后可以总结为:

  • M 等于 N时(就是用了所有的样本), 就是所谓的batch GD
  • M 等于 1时 (就是用了其中的一个样本), 就是所谓的SGD
  • M 大于1, 小于 N时, 就是 mini-batch GD.
      所以从expected loss的角度看, 其实batch GD, mini-batch GD, SGD都可以看成SGD的范畴, 只不过区别在于每次取多少的样本了。

梯度下降优化算法(非SGD系列)

  AdaDelta, Ada-Grad, Adam, NAG, RMSprop
  参考资料:http://blog.csdn.net/luo123n/article/details/48239963

1)Momentum

  一般,动量项取0.9附近,学习率取0.01。
  作用是使收敛更快,减少震荡。梯度方向不变时,收敛更快,梯度方向改变时,减小震荡。收敛更稳定。
  SGD方法的一个缺点是,其更新方向完全依赖于当前的batch,因而其更新十分不稳定。解决这一问题的一个简单的做法便是引入momentum。

公式:Δx_t=ρ*Δx_(t-1)−η*g_t

  ρ 即momentum,表示要在多大程度上保留原来的更新方向,这个值在0-1之间,在训练开始时,由于梯度可能会很大,所以初始值一般选为0.5;当梯度不那么大时,改为0.9。

2)Nesterov accelerated gradient(NAG)

  即Nesterov Momentum
  一般动量项取0.9附近,学习率取0.01。
  Nesterov提出的加速的梯度下降方法,这是对传统momentum方法的一项改进。这种基于预测的更新方法,使我们避免过快地前进,并提高了算法地响应能力(responsiveness),大大改进了 RNN 在一些任务上的表现 。

  首先,按照原来的更新方向更新一步(棕色线),然后在该位置计算梯度值(红色线),然后用这个梯度值修正最终的更新方向(绿色线)。图中描述了两步的更新示意图,其中蓝色线是标准momentum更新路径。
在这里插入图片描述

3)Adagrad(针对稀疏数据集)

  自适应地为各个参数分配不同学习率的算法。
  优点:赋予更新频繁的梯度以较小的学习率,赋予更新不频繁的梯度以较大的学习率。尤其对于大型网络,可以提高SGD的鲁棒性。
  缺点:由于梯度平方和随着时间的会越来越大,造成训练后期的学习率会非常小,学习的提前停止。

4)Adadelta

  Adadelta 法是 Adagrad 法的一个延伸,它旨在解决它学习率不断单调下降的问题。相比计算之前所有梯度值的平方和,Adadelta 法仅计算在一个大小为t的时间区间内梯度值的累积和。

5) RMSprop

  建议学习率 取0.001为好。
  与AdaDelta方法类似(应该只是AdaDelta算法的特例)。

6)Adam

  计算效率较高,能够适应较大的数据集,能够较好的处理稀疏集。
  自适应学习率梯度下降方法中Adam方法的效果比较好,应用的也比较多。
  偏差修正项 很重要,尤其是当 β2趋近于1时,可以防止步长变得过大。
  adam是RMSprop和AdaGrad的更一般形式,对于RMSprop和AdaGrad能够处理的情形,一般都能处理,而且Adam算法所需内存较少,计算效率高,所以近几年优化算法以adam为主。

7)Nadam算法

  是adam算法的推广形式。
  一般情况下,针对adam算法可以处理的情形,Nadam都能适用。在深度网络中Nadam算法的表现一般要优于adam算法。keras框架中包含该算法。


Adam算法详解

  Adam是一种基于一阶梯度来优化随机目标函数的算法。是目前深度学习中使用最广泛的优化算法,适用于多种应用。
  Adam 这个名字来源于 adaptive moment estimation,自适应矩估计。概率论中矩的含义是:如果一个随机变量 X 服从某个分布,X 的一阶矩是 E(X),也就是样本平均值,X 的二阶矩就是 E(X^2),也就是样本平方的平均值。Adam 算法根据损失函数对每个参数的梯度的一阶矩估计和二阶矩估计动态调整针对于每个参数的学习速率。Adam 也是基于梯度下降的方法,但是每次迭代参数的学习步长都有一个确定的范围,不会因为很大的梯度导致很大的学习步长,参数的值比较稳定。

  Adam 计算了一个 ν dw^corr 的值,用于加快指数加权移动平均值的变化。它将通过增加它们的值来对它们进行标准化,与当前的迭代次数成反比。

  使用 Adam 时有一些很好的初始值可供尝试。它最好以 0.9 的 β_1 和 0.999 的 β_2 开头。
  通过实验发现,调低β2值,影响了Adam方法中过去平方梯度的指数移动平均值的贡献度。一般来说,β2的默认值为0.999,设置为0.99或0.9后,在不同任务中表现更好,这表明可能存在指数移动平均值的问题。

  Adam之流虽然说已经简化了调参,但是并没有一劳永逸地解决问题,默认的参数虽然好,但也不是放之四海而皆准。因此,在充分理解数据的基础上,依然需要根据数据特性、算法特性进行充分的调参实验。

SGD算法详解

  SGD是保证收敛的!
  使用Stochastic Gradient Descent或其变体训练深度神经网络需要仔细选择学习速率和批次大小。虽然较小的批量通常在较少的训练时期收敛,但较大的批量提供了更多的并行性,并因此提高了计算效率。

  我们试过一些其他方法,但是我们发现好像都和SGD差不多。在多机训练场景下,SGD会更加方便实现。

  一个代码上的细节,就是caffe的代码实现上选取一个batch的时候似乎是按着数据库的图片顺序选取输入图片的,所以在生成数据库的时候切记要shuffle一下图片顺序~
  caffe中ImageDataLayer有shuffle参数,生成lmdb时也有shuffle参数不必手动。


优化SGD的其他策略

  1)每个迭代周期完成后,打乱数据集的顺序(Shuffling and Curriculum Learning)
  为了使得学习过程更加无偏,应该在每次迭代中随机打乱训练集中的样本。
  另一方面,在很多情况下,我们是逐步解决问题的,而将训练集按照某个有意义的顺序排列会提高模型的性能和SGD的收敛性,如何将训练集建立一个有意义的排列被称为Curriculum Learning。
  Zaremba与Sutskever在使用Curriculum Learning来训练LSTMs以解决一些简单的问题中,表明一个相结合的策略或者混合策略比对训练集按照按照训练难度进行递增排序要好。

  2)Batch normalization;

  3)提前停止;

  4)在训练后期适当减小动量值能够使网络更稳定的收敛。

  5)在梯度更新时,给梯度添加噪音可以增加网络的泛化能力。即每次迭代计算梯度中加上一个高斯分布N(0,σ2t)的随机误差,高斯误差的方差需要进行退火。
  对梯度增加随机误差会增加模型的鲁棒性,即使初始参数值选择地不好,并适合对特别深层次的负责的网络进行训练。其原因在于增加随机噪声会有更多的可能性跳过局部极值点并去寻找一个更好的局部极值点,这种可能性在深层次的网络中更常见。


梯度下降的使用(指导性思路)

  1)当前最常用的是优化算法有:SGD(带动量),Adam, RMSprop;建议选择SGD和Adam。sgd是保证收敛的

  2)现在有论文不用梯度下降优化算法来训练神经网络;例如《Training Deep Neural Networks via Optimization Over Graphs》

  3)如果你的数据特征是稀疏的,那么你最好使用自适应学习速率SGD优化方法(Adagrad、Adadelta、RMSprop与Adam),因为你不需要在迭代过程中对学习速率进行人工调整。

  4)异步SGD方法。
  如果你处理的数据集非常大,并且有机器集群可以利用,那么并行或分布式SGD是一个非常好的选择,因为可以大大地提高速度。SGD算法的本质决定其是串行的(step-by-step)。因此如何进行异步处理便是一个问题。虽然串行能够保证收敛,但是如果训练集大,速度便是一个瓶颈。如果进行异步更新,那么可能会导致不收敛。下面将讨论如何进行并行或分布式SGD,并行一般是指在同一机器上进行多核并行,分布式是指集群处理。比如1-bit。

  5)各大算法孰优孰劣并无定论。如果是刚入门,优先考虑 SGD+Nesterov Momentum或者Adam.(Standford 231n : The two recommended updates to use are either SGD+Nesterov Momentum or Adam)

  6)选择你熟悉的算法——这样你可以更加熟练地利用你的经验进行调参。

  7)充分了解你的数据——如果模型是非常稀疏的,那么优先考虑自适应学习率的算法。

  8)根据你的需求来选择——在模型设计实验过程中,要快速验证新模型的效果,可以先用Adam进行快速实验优化;在模型上线或者结果发布前,可以用精调的SGD进行模型的极致优化。

  9)先用小数据集进行实验。有论文研究指出,随机梯度下降算法的收敛速度和数据集的大小的关系不大。(The mathematics of stochastic gradient descent are amazingly independent of the training set size. In particular, the asymptotic SGD convergence rates are independent from the sample size.)因此可以先用一个具有代表性的小数据集进行实验,测试一下最好的优化算法,并通过参数搜索来寻找最优的训练参数。

  10)考虑不同算法的组合。先用Adam进行快速下降,而后再换到SGD进行充分的调优。

  11)数据集一定要充分的打散(shuffle)。这样在使用自适应学习率算法的时候,可以避免某些特征集中出现,而导致的有时学习过度、有时学习不足,使得下降方向出现偏差的问题。

  12)训练过程中持续监控训练数据和验证数据上的目标函数值以及精度或者AUC等指标的变化情况。对训练数据的监控是要保证模型进行了充分的训练——下降方向正确,且学习率足够高;对验证数据的监控是为了避免出现过拟合。

  13)制定一个合适的学习率衰减策略。可以使用定期衰减策略,比如每过多少个epoch就衰减一次;或者利用精度或者AUC等性能指标来监控,当测试集上的指标不变或者下跌时,就降低学习率。

  14)在一些特定任务上,比SGD好的比比皆是。
  例如:随机加权平均(Stochasitc Average Gradient,SWA)是比SGD更广泛的最优化,但还是很新。


梯度下降的使用(具体参数设置)

  1)原文中输入的batch数目是256,应该Alex经过调节后的结果,我实际用到的机器性能比较低,内存8G,显存4G,所以不得不就将batch数目往下调到64,以免产生out of memory的错误。这样就需要调节其他的参数来保证数据的收敛。原因是batch比较小,导致本文开篇提到的样本覆盖面过低,产生了非常多的局部极小点,在步长和方向的共同作用下,导致数据产生了震荡,导致了不收敛。

  2)在这种情况下,把learning rate调节到了0.02,相当于加大了步长,这样可以在一定程度上避免震荡,可以越过局部极小点往比较大的极值点行走。

  3)对于每一层的bias从1设置为了0.1,在一定程度上限制了激活的大小,这样就限制了某一过大的误差的影响,这样可以避免迭代方向出现过大的变化。

  4)经过1)和2)后,系统终于收敛了,但带来的不良后果就是整个收敛速度变慢,因此还需要增加最大迭代次数,经过测试迭代次数成了从45w修改成了70w。

  5)在整个运行过程中,出现了几次平稳点,20w以及40w左右的时候,因此迭代的learning rate应该随着迭代的接近平稳点的时候有意的减小一些,目前是以每10w次减小为1/10,调参数用了5天,最后运行时间为15天。

  6)关于调参策略,上面只是按照一些简单的理解设置的,如果没有一个合理的解释,调参就变成了一个很low的工作。还好发现了好几篇关于调参的论文,主要是优化算法理论方面的,学习完再回来测试一下。

实际地用alexnet和googlenet训练

  1)针对AlexNet这种网络结构相对简单的网络,在epoch相同的情形下,SGD和其他算法的时间没有太多差别,但是SGD和NAG算法比其他算法收敛的要快,精度也要高。建议选择SGD算法。

  2)对于GoogleNet等网络结构较为复杂的网络,SGD也可以收敛到很高的精度,adam算法的收敛速度要快一点而且收敛更稳定;建议选择adam算法。

  3)建议参数设置(batchsize可以根据情况选择28,64和128)

  SGD:     学习率,  动量,学习规则设为step就好;  
  NAG:      学习率,动量,学习规则设为step就好;
  AdaGrad:  学习率=0.001,   学习规则为INV 参数设置power 0.75 gama0.5;
  AdaDelta:学习率=1 ,      学习规则fix
  RMSprop:学习率=0.001,   学习规则 INV or poly
  adam:   学习率=0.001,   学习规则 INV or poly, sgmoid

  4)在GoogleNet上对adam算法尝试不同的学习规则(INV,poly,exp,sigmoid),实验结果没有明显差别。原因有可能是训练集较小。

  5)在GoogleNet上尝试不同的优化方法和策略时,一般都可以收敛到较高的精度,影响算法收敛和精度的主要因素还是学习率。

  6)在训练网络时,建议先选择参数默认值,和step学习规则进行尝试,然后根据训练结果调整参数。

  ADD算法的初始学习率默认为1,SGD,NAG的默认学习率为0.01,其余算法的默认学习率为0.001;

  目前应用较多的优化算法为SGD和Adam算法。从在Alex-net上的结果看NAG要比SGD算法精度高近一个百分点;

  RMSprop算法对学习率十分敏感,比较难收敛,建议少用;

  当训练网络不稳定时,建议第一次epoch先用较小的学习率,然后再调大学习率;

  学习率的设置不仅要考虑网络结构,还要考虑batchsize的大小,batchsize变小,学习率相应要减小一点(论文中有这种变化,没有试验,不一定都是这样),随着硬件的提高,一般选择128和256;

  从论文来看,采用SGD时一般训练中会采用两个学习率的值,学习率变化太频繁可能也会对网络精度造成一定的影响;

  从算法出发,Adam算法能适用稀疏数据和非平稳目标数据,所以近两年论文多采用此方法;

  对于动量和weight-decay一般都为0.9和0.0005,,很少有实验改动这两个值;

  Alex就在2012年的AlexNet中,把所有Tanh/Logistic全换成了ReLu(卷积+隐层,Softmax要取概率没办法)

  对于使用ImageNet训练AlexNet模型,每个GPU的最佳批量大小为512。

实际地用alexnet和VGG16训练

  both AlexNet and VGG16 variants are trained for 30 epochs using the Adam optimizer with momentum of β1 = 0.9, β2 = 0.999, and weight decay of 0.0005. The learning rate is 0.0001 and is held constant during the pre-training stage.

猜你喜欢

转载自blog.csdn.net/wydbyxr/article/details/84822806
今日推荐