机器学习-最优化方法

1、简介

在机器学习特别是深度学习中,我们经常需要这些最优化算法来将我们的模型训练至一个局部/全局最优处,从而得到我们需要的网络参数。

目前为止:

  1. 由于每种算法都有其局限性,暂时还没有一种算法适用于大多数模型,因此还没有就使用哪种算法达成共识。
  2. 在对于模型了解不太深刻时,最好使用较为流行的算法,例如:SGD、动量SGD、RMSProp、动量RMSProp、AdaDelta 、Adam等,较少使用陈旧的如二阶近似的方法。
  3. 对于使用哪种算法主要取决于使用者对于不同算法的熟悉程度,各种算法效果相差不大,因此最好选用自己熟悉的方法。(便于调节,实际效果其实还是要看调参)

2、算法简介

2.1、基本方法

2.1.1、梯度下降法Gradient Descent

梯度下降法是最早最简单,也是最为常用的最优化方法。梯度下降法实现简单,当目标函数是凸函数时,梯度下降法的解是全局解。一般情况下,其解不保证是全局最优解,梯度下降法的速度也未必是最快的。梯度下降法的优化思想是用当前位置负梯度方向作为搜索方向,因为该方向为当前位置的最快下降方向,所以也被称为是”最速下降法“。最速下降法越接近目标值,步长越小,前进越慢。梯度下降法的搜索迭代示意图如下图所示:

梯度下降法的缺点:

  1. 靠近极小值时收敛速度减慢
  2. 直线搜索时可能会产生一些问题
  3. 可能会呈现锯齿状

在机器学习中,基于基本的梯度下降法发展了两种梯度下降方法,分别为随机梯度下降法和批量梯度下降法。

2.1.2、批量梯度下降法Batch Gradient Descent

批量梯度下降法是将整个训练集一次性跑完,它得到的是一个全局最优解,但是每迭代一步,都要用到训练集所有的数据,如果m很大,那么可想而知这种方法的迭代速度会相当的慢。所以,这就引入了另外一种方法——随机梯度下降。

2.1.3、随机梯度下降Stochastic Gradient Descent

随机梯度下降是通过每个样本来迭代更新一次,如果样本量很大的情况(例如几十万),那么可能只用其中几万条或者几千条的样本,就已经将theta迭代到最优解了,对比上面的批量梯度下降,迭代一次需要用到十几万训练样本,一次迭代不可能最优,如果迭代10次的话就需要遍历训练样本10次。随机梯度下降每次迭代只使用一个样本,随机梯度下降迭代一次的速度要远高于批量梯度下降方法。

但是,SGD伴随的一个问题是噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。

两者的关系可以这样理解:随机梯度下降方法以损失很小的一部分精确度和增加一定数量的迭代次数为代价,换取了总体的优化效率的提升。增加的迭代次数远远小于样本的数量。

对批量梯度下降法和随机梯度下降法的总结:

批量梯度下降---最小化所有训练样本的损失函数,使得最终求解的是全局的最优解,即求解的参数是使得风险函数最小,但是对于大规模样本问题效率低下。

随机梯度下降---最小化每条样本的损失函数,虽然不是每次迭代得到的损失函数都向着全局最优方向, 但是大的整体的方向是向全局最优解的,最终的结果往往是在全局最优解附近,适用于大规模训练样本情况。

缺点:

SGD 因为更新比较频繁,会造成 cost function 有严重的震荡。

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

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

2.1.3、批量梯度下降Mini-Batch Gradient Descent

MBGD 每一次利用一小批样本,即 n 个样本进行计算,这样它可以降低参数更新时的方差,收敛更稳定,另一方面可以充分地利用深度学习库中高度优化的矩阵操作来进行更有效的梯度计算,是介于BGD与SGD之间的方法,其和 SGD 的区别是每一次循环不是作用于每个样本,而是具有 n 个样本的批次。(也就是说将样本分成n份来进行训练,这样一次训练的数量就介于整个训练集和单个样本之间,n 一般取值在 50~256)

缺点:

  1. Mini-batch gradient descent 不能保证很好的收敛性,learning rate 如果选择的太小,收敛速度会很慢,如果太大,loss function 就会在极小值处不停地震荡甚至偏离。(有一种措施是先设定大一点的学习率,当两次迭代之间的变化低于某个阈值后,就减小 learning rate,不过这个阈值的设定需要提前写好,这样的话就不能够适应数据集的特点。)对于非凸函数,还要避免陷于局部极小值处,或者鞍点处,因为鞍点周围的error是一样的,所有维度的梯度都接近于0,SGD 很容易被困在这里。(会在鞍点或者局部最小点震荡跳动,因为在此点处,如果是训练集全集带入即BGD,则优化会停止不动,如果是mini-batch或者SGD,每次找到的梯度都是不同的,就会发生震荡,来回跳动。)
  2. SGD对所有参数更新时应用同样的 learning rate,如果我们的数据是稀疏的,我们更希望对出现频率低的特征进行大一点的更新。learning rate会随着更新的次数逐渐变小。

2.1.4、动量梯度下降法Momentum

SGD 在 ravines 的情况下容易被困住, ravines 就是曲面的一个方向比另一个方向更陡(简单来说就是移动一小步,在不同方向上产生的效果有很大不同),这时 SGD 会发生震荡而迟迟不能接近极小值:

有一个梯度下降法叫做动量梯度下降。动量梯度下降的参数更新公式如图:

我们可以看出,在这个公式中,并不是直接在梯度上计算,而是计算出了一个V_{dw}V_{db}。这又是什么呢?在此需要引入一个叫做指数加权平均的知识点。也就是上图中的前两行公式。使用这个公式,可以将之前的dW和db都联系起来,不再是每一次梯度都是独立的情况。

其中β是可以自行设置的超参数,一般情况下默认为0.9(也可以设置为其他数值)。β代表了现在的V_{dw}V_{db}与之前的1 / (1 - β)个vdW和vdb有关。0.9就是现在的V_{dw}V_{db}是平均了之前10天的V_{dw}V_{db}的结果。此时的梯度不再只是我现在的数据的梯度,之前的梯度也占有一定权重,就我个人认为,就像是把原本的梯度压缩一点,并且补上一个之前就已经存在的“动量”。

其实就相当于在每次梯度计算时,增加了之前方向的占比,从而使得梯度不能够任意地改变方向,因为不能随意地改变自己的方向所以震荡就会变小,就像阻尼一样控制了过于剧烈的变化,有一点拖后腿的感觉😀。

举个例子,如果你站在一个地方不动,让你立刻向后转齐步走,你可以迅速向后转然后就向相反的方向走了起来,批梯度下降和随机梯度下降就是这样,某一时刻的梯度只与这一时刻有关,改变方向可以做到立刻就变。而如果你正在按照某个速度向前跑,再让你立刻向后转,可以想象得到吧,此时你无法立刻将速度降为0然后改变方向,你由于之前的速度的作用,有可能会慢慢减速然后转一个弯。

动量梯度下降是同理的,每一次梯度下降都会有一个之前的速度的作用,如果我这次的方向与之前相同,则会因为之前的速度继续加速;如果这次的方向与之前相反,则会由于之前存在速度的作用不会产生一个急转弯,而是尽量把路线向一条直线拉过去。这就解决了文中第一个图的那个在普通梯度下降中存在的下降路线折来折去浪费时间的问题。

与Momentum的机制类似的,还有一种叫做RMSprop的算法,他们俩的效果也是类似,都解决了相同的问题,使梯度下降时的折返情况减轻,从而加快训练速度。因为下降的路线更接近同一个方向,因此也可以将学习率增大来加快训练速度。Momentum和RMSprop的结合,产生了一种权威算法叫做Adam,Adam结合了前两者的计算方式形成自己的优化方法,基本适用于所有的模型和网络结构。

2.1.5、加速梯度下降算法Nesterov Accelerated Gradient

在计算梯度时,不是在当前位置,而是未来的位置上(Nesterov先更新参数,再计算梯度 。)

一般 γ 仍取值 0.9 左右。

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

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

NAG本质上是多考虑了目标函数的二阶导信息,由此加速收敛了。其实所谓超前的说法,在牛顿法这样的二阶方法中也是经常提到的,比喻起来是说“往前看”,数学本质上则是利用了目标函数的二阶导信息来进行估计。

NAG 可以使 RNN 在很多任务上有更好的表现。目前为止,我们可以做到,在更新梯度时顺应 loss function 的梯度来调整速度,并且对 SGD 进行加速。我们还希望可以根据参数的重要性而对不同的参数进行不同程度的更新。

结论:在原始形式中,Nesterov Accelerated Gradient(NAG)算法相对于Momentum的改进在于,以“向前看”看到的梯度而不是当前位置梯度去更新。经过变换之后的等效形式中,NAG算法相对于Momentum多了一个本次梯度相对上次梯度的变化量,这个变化量本质上是对目标函数二阶导的近似。由于利用了二阶导的信息,NAG算法才会比Momentum具有更快的收敛速度。

2.2、自适应型算法

这类算法最大的特点就是,每个参数有不同的学习率,在整个学习过程中自动适应这些学习率。

2.2.1、自适应梯度算法Adaptive gradient algorithm

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

其中 g 为t 时刻参数 θ_i 的梯度

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

但这里的 learning rate η 也随 t 和 i 而变:

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

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

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

2.2.2、Adadelta

这个算法是对 Adagrad 的改进和 Adagrad 相比,就是分母的 G 换成了过去的梯度平方的衰减平均值,指数衰减平均值。γ 一般设定为 0.9。

这个分母相当于梯度的均方根 root mean squared (RMS),在数据统计分析中,将所有值平方求和,求其均值,再开平方,就得到均方根值 ,所以可以用 RMS 简写:

其中 E 的计算公式如下,t 时刻的依赖于前一时刻的平均和当前的梯度:

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

2.2.3、RMSProp

RMSprop 是 Geoff Hinton 提出的一种自适应学习率方法。RMSprop 和 Adadelta 都是为了解决 Adagrad 学习率急剧下降问题的,Hinton 建议设定 γ 为 0.9, 学习率 η 为 0.001。

RMSprop 与 Adadelta 的第一种形式相同:(使用的是指数加权平均,旨在消除梯度下降中的摆动,与Momentum的效果一样,某一维度的导数比较大,则指数加权平均就大,某一维度的导数比较小,则其指数加权平均就小,这样就保证了各维度导数都在一个量级,进而减少了摆动。允许使用一个更大的学习率η)

2.2.4、自适应矩估计Adaptive Moment Estimation

这个算法是另一种计算每个参数的自适应学习率的方法。相当于 RMSprop + Momentum。建议 β1 = 0.9,β2 = 0.999,ϵ = 10e−8。

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

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

参数更新公式:

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

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

SGD optimization on saddle point

上面两种情况都可以看出,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 虽然能达到极小值,但是比其它算法用的时间长,而且可能会被困在鞍点。

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

2.3、二阶近似的优化算法

作为早期处理神经网络的方法,我们需要理解他们的原理。

2.3.1、牛顿法NewtonMethod

牛顿法是通过在某点处,将函数按二阶泰勒级数进行展开,来近似函数的变化,从而得到迭代公式,当变量在迭代后变化在一个很小的范围内时,就可以近似认为其是方程的根。下面这张图很形象的描述了牛顿法的迭代求根步骤:

一般认为牛顿法可以利用到曲线本身的信息(牛顿法的二阶曲面相比于梯度法的一阶平面在拟合度上也具有优势),比梯度下降法更容易收敛(迭代更少次数),如下图是一个最小化一个目标方程的例子,红色曲线是利用牛顿法迭代求解,绿色曲线是利用梯度下降法求解。

高维情况的牛顿迭代公式是:

其中H是Hessian矩阵,定义为:

高维情况依然可以用牛顿迭代求解,由于Hessian矩阵包含多种偏导数引入很大的复杂度,所以会消耗很大的算力,使得牛顿迭代求解的难度大大增加,但是已经有了解决这个问题的办法就是Quasi-Newton methond,不再直接计算Hessian矩阵,而是每一步的时候使用梯度向量更新Hessian矩阵的近似。

值得注意 , 当初始点远离极小点时,牛顿法可能不收敛。原因之一是牛顿方向不一定是下降方向,经迭代,目标函数可能上升。此外,即使目标函数下降,得到的点也不一定是沿牛顿方向最好的点或极小点。因此,我们在牛顿方向上增加一维搜索,提出了阻尼牛顿法。

2.3.2、共轭梯度法Conjugate Gradient

梯度下降法中每次迭代的时候都以该点的负梯度方向(如果目标函数求最小值)进行精确一维搜索,每一步都是朝着局部最优的方向前进的,但是它在不同的迭代轮数中会选择非常近似的方向,说明这个方向的误差并没通过一次更新方向和步长更新完,在这个方向上还存在误差,因此参数更新的轨迹是锯齿状。可能刚开始下降很多,但到后面越来越慢,收敛速度很慢。

共轭梯度法是共轭方向法的一种,它在最速下降法的基础上对它进行了改良,初始点的下降方向仍是负梯度方向,但后面的迭代方向不再是该点的负梯度方向了,后面的迭代方向是该点的负梯度方向和前一次迭代方向形成的凸锥中的一个方向,同时,选择一个优化方向后,本次选择的步长能够将这个方向的误差更新完,在以后的优化更新过程中不再需要朝这个方向更新了。由于每次将一个方向优化到了极小,后面的优化过程将不再影响之前优化方向上的极小值,所以理论上对N维问题求极小只用对N个方向都求出极小就行了。为了不影响之前优化方向上的更新量,需要每次优化方向共轭正交。这样有效地避免了“锯齿”现象。

共轭梯度法是介于最速下降法与牛顿法之间的一个方法,它仅需利用一阶导数信息,但克服了最速下降法收敛慢的缺点,又避免了牛顿法需要存储和计算Hesse矩阵并求逆的缺点,共轭梯度法不仅是解决大型线性方程组最有用的方法之一,也是解大型非线性最优化最有效的算法之一。 在各种优化算法中,共轭梯度法是非常重要的一种。其优点是所需存储量小,具有步收敛性,稳定性高,而且不需要任何外来参数。下图为共轭梯度法和梯度下降法搜索最优解的路径对比示意图:

2.3.3、BFGS

 NewtonMethod在计算时需要用到Hessian矩阵H,计算Hessian矩阵非常费时, 所以研究者提出了很多使用方法来近似Hessian矩阵,这些方法都称作准牛顿算法,BFGS就是其中的一种,以其发明者Broyden,Fletcher,Goldfarb和Shanno命名。

BFGS算法使用以下方法来近似Hessian矩阵:

 

其中D_k即是H^{-1}S_k=X_{k+1}-X_{k}y_k=g{k+1}-g{k}g{k}是原函数的导函数。初始时取B_0=I

我们要通过牛顿求驻点法和BFGS算法来求得一个函数的根,两个算法可以同步迭代,慢慢逼近函数根,经过k次迭代以后,所得到的解就是机器学习中目标函数导函数的根。

2.3.4、L-BFGS

在BFGS算法中,仍然有缺陷,比如当优化问题规模很大时,矩阵的存储和计算将变得不可行。为了解决这个问题,就有了L-BFGS算法。L-BFGS即Limited-memory BFGS。L-BFGS的基本思想是只保存最近的m次迭代信息,从而大大减少数据的存储空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值