6. 深度学习-优化器
- 有前面的知识,我们知道如何构建目标函数了,当目标函数构建出来后,如何求其参数使的目标函数最小化呢?这就是这一小节的针对目标函数的相关优化方法。依据惯例,优化算法通常只考虑最小化目标函数。其实,任何最大化问题都可以很容易地转化为最小化问题,只需令目标函数的相反数为新的目标函数即可。
- 深度学习中绝大多数目标函数都很复杂。因此,很多优化问题并不存在解析解,而需要使用基于数值方法的优化算法找到近似解,即数值解。为了求得最小化目标函数的数值解,我们将通过优化算法有限次迭代模型参数来尽可能降低损失函数的值。
1. 相关术语
- 优化方法在深度学习中有很多挑战。主要的是即局部最小值和鞍点两个挑战。
1.1 局部最小值和全局最小值
- 对于目标函数 ,如果 在上的值比在邻近的其他点的值更小,那么 可能是一个局部最小值(local minimum)。深度学习模型的目标函数可能有若干局部最优值。当一个优化问题的数值解在局部最优解附近时,由于目标函数有关解的梯度接近或变成零,最终迭代求得的数值解可能只令目标函数局部最小化而非全局最小化。
- 如果 在上的值是目标函数在整个定义域上的最小值,那么 是全局最小值(global minimum)。
- 图像展示局部最小值和全局最小值: 2019070201.png
1.2 鞍点
- 梯度接近或变成零可能是由于当前解在局部最优解附近造成的。事实上,另一种可能性是当前解在鞍点(saddle point)附近。
- 函数的鞍点图像: 2019070202.png
-
定义在二维空间的函数的鞍点图像:
2019070203.png -
对于,我们可以找出该函数的鞍点位置。该函数看起来像一个马鞍,而鞍点恰好是马鞍上可坐区域的中心。目标函数在 轴方向上是局部最小值,但在轴方向上是局部最大值。
-
假设一个函数的输入为 k 维向量,输出为标量,那么它的海森矩阵(Hessian matrix)有 k 个特征值。该函数在梯度为0的位置上可能是局部最小值、局部最大值或者鞍点。
- 当函数的海森矩阵在梯度为零的位置上的特征值全为正时,该函数得到局部最小值。
- 当函数的海森矩阵在梯度为零的位置上的特征值全为负时,该函数得到局部最大值。
- 当函数的海森矩阵在梯度为零的位置上的特征值有正有负时,该函数得到鞍点。
-
对于一个大的高斯随机矩阵来说,任一特征值是正或者是负的概率都是0.5 。那么,函数取得局部最小值或者局部最大值的概率为。由于深度学习模型参数通常都是高维的( k 很大),所以函数取得局部最小(大)值的概率很小。但是取得鞍点的概率就很大了(),因此目标函数的鞍点通常比局部最小值更常见。
2. 优化器
2.1 梯度下降法
- 梯度下降法(Gradient Descent)是比较常用的优化算法,其衍生的相关算法有随机梯度下降算法(Stochastic Gradient Descent),批量梯度下降算法(Batch Gradient Descent),小批量梯度下降算法(MIni Batch Gradient Descent)。
- 什么是梯度下降法呢?举个例子,假如有一座山,你在山的随机地方,你想要快速下山。如果面向你的前方坡度下降的,你就向前走一步;如果面向你的前方坡度上升的,你就后退走一步;如此重复下去,你会到达山脚,这个山脚不一定是山的底部,可能是山的山坳。这里面都可以和梯度下降法中的术语映射。此处的山就是损失函数+正则化项(目标函数),我们期望下山,对应我们期望求得目标函数的最小值。你在山的随机地方,相当于我们对目标函数的参数第一次初始化,一般都是随机的取标准正态分布的数。你想要快速下山,就相当于把目标函数的参数花费少量的时间,运行出来。坡度下降和上升相当于目标函数在当前点的梯度(可以理解为导数),我们知道凸函数的最小值点在端点,极小值点。一个函数有多个极小值点,如果我们任选一个极小值点最为函数的最小值,这时容易陷入局部最优,而不是全局最优。局部最优相当于山坳,全局最优相当于山脚。为了不陷入局部最优,我们需要在山的不同点,选择下山,多次后选择一个最低的点,那么该点一定是山脚。这也就是为什么我们初始化参数的时候,多次初始化,为了就是求得目标函数的全局最优。
2.1.1 一维梯度下降法
-
为什么梯度下降算法可能降低目标函数值。假设连续可导的函数 的输入和输出都是标量。给定任意小的正数 ,根据泰勒展开公式,有
-
这里是函数 在 处的梯度。一维函数的梯度是一个标量,也称导数。我们希望找到一个常数 ,使得足够小,那么可以将替换为并得到
-
如果导数,那么 ,所以我们通过不断地迭代,来逼近。函数 f(x) 的值可能会降低。因此在梯度下降中,我们先选取一个初始值和常数 ,然后不断来迭代,直到达到停止条件,例如的值已足够小或迭代次数已达到某个值。
-
正数 通常叫作学习率。这是一个超参数,需要人工设定。如果使用过小的学习率,会导致更新缓慢从而需要更多的迭代才能得到较好的解。如果使用过大的学习率, 可能会过大从而使一阶泰勒展开公式不再成立,这时我们无法保证迭代 会降低 的值。
2.2 批量梯度下降法(Batch Gradient Descent)
- 批量梯度下降法,是梯度下降法最常用的形式,具体做法也就是在更新参数时使用所有的样本来进行更新,也就是说梯度下降算法就是指批量梯度下降法。
2.3 随机梯度下降法(Stochastic Gradient Descent)
- 在处理大量的数据时,梯度下降法就有些力不从心了。梯度下降法求参数时,会使用全部的训练数据,这样计算的代价很大,计算量大,耗时很长。而随机梯度法是每次仅仅随机均匀采样的一个样本来求梯度。
2.4 小批量梯度下降法(Mini-batch Gradient Descent)
-
批量梯度下降法和随机梯度下降法是两个极端,一个采用所有数据来梯度下降,一个用一个样本来梯度下降。自然各自的优缺点都非常突出。对于训练速度来说,随机梯度下降法由于每次仅仅采用一个样本来迭代,训练速度很快,而批量梯度下降法在样本量很大的时候,训练速度不能让人满意。对于准确度来说,随机梯度下降法用于仅仅用一个样本决定梯度方向,导致解很有可能不是最优。对于收敛速度来说,由于随机梯度下降法一次迭代一个样本,导致迭代方向变化很大,不能很快的收敛到局部最优解。小批量梯度下降法是批量梯度下降法和随机梯度下降法的折衷,也就是对于个样本,我们采用个样本来迭代,。
-
在每一次迭代中,梯度下降使用整个训练数据集来计算梯度,因此它有时也被称为批量梯度下降(batch gradient descent)。而随机梯度下降在每次迭代中只随机采样一个样本来计算梯度。我们还可以在每轮迭代中随机均匀采样多个样本来组成一个小批量,然后使用这个小批量来计算梯度。
-
设目标函数。在迭代开始前的时间步设为0。该时间步的自变量记为,通常由随机初始化得到。在接下来的每一个时间步中,小批量随机梯度下降随机均匀采样一个由训练数据样本索引组成的小批量。我们可以通过重复采样(sampling with replacement)或者不重复采样(sampling without replacement)得到一个小批量中的各个样本。前者允许同一个小批量中出现重复的样本,后者则不允许如此,且更常见。对于这两者间的任一种方式,都可以使用
来计算时间步的小批量上目标函数位于处的梯度。这里代表批量大小,即小批量中样本的个数,是一个超参数。同随机梯度一样,重复采样所得的小批量随机梯度也是对梯度的无偏估计。给定学习率(取正数),小批量随机梯度下降对自变量的迭代如下:
-
基于随机采样得到的梯度的方差在迭代过程中无法减小,因此在实际中,(小批量)随机梯度下降的学习率可以在迭代过程中自我衰减,例如(通常或者)、(如)或者每迭代若干次后将学习率衰减一次。如此一来,学习率和(小批量)随机梯度乘积的方差会减小。而梯度下降在迭代过程中一直使用目标函数的真实梯度,无须自我衰减学习率。
-
小批量随机梯度下降中每次迭代的计算开销为。当批量大小为1时,该算法即为随机梯度下降;当批量大小等于训练数据样本数时,该算法即为梯度下降。当批量较小时,每次迭代中使用的样本少,这会导致并行处理和内存使用效率变低。这使得在计算同样数目样本的情况下比使用更大批量时所花时间更多。当批量较大时,每个小批量梯度里可能含有更多的冗余信息。为了得到较好的解,批量较大时比批量较小时需要计算的样本数目可能更多,例如增大迭代周期数。
-
小批量随机梯度每次随机均匀采样一个小批量的训练样本来计算梯度。
-
在实际中,(小批量)随机梯度下降的学习率可以在迭代过程中自我衰减。
-
通常,小批量随机梯度在每个迭代周期的耗时介于梯度下降和随机梯度下降的耗时之间。
2.5 Momentum 算法
2.5.1 指数加权移动平均
- 指数加权移动平均(exponentially weighted moving average)。给定超参数 ,当前时间的变量 是上一时间 的变量和当前时间步另一变量 的线性组合:。
- 我们可以对上面的 展开:
-
-
令,那么 。
-
因为
-
所以当 时,,如 。如果把 当作一个比较小的数,我们可以在近似中忽略所有含 和比 更高阶的系数的项。例如,当 时,
-
因此,在实际中,我们常常将 看作是对最近 个时间步的 值的加权平均。例如,当 时,可以被看作对最近20个时间步的 值的加权平均;当 时,可以看作是对最近10个时间步的 值的加权平均。而且,离当前时间步 越近的 值获得的权重越大(越接近1)。
-
2.5.2 动量法
-
在小批量梯度下降法时,我们在训练深度神经网络的时候把数据拆解成一小批一小批地进行训练,然而虽然这种算法能够带来很好的训练速度,但是在到达最优点的时候并不能够总是真正到达最优点,而是在最优点附近徘徊。另一个缺点就是这种算法需要我们挑选一个合适的学习率,当我们采用小的学习率的时候,会导致网络在训练的时候收敛太慢;当我们采用大的学习率的时候,会导致在训练过程中优化的幅度跳过函数的范围,也就是可能跳过最优点。我们所希望求解目标函数时,有一个很好的收敛速度同时又不至于摆动幅度太大。
- 在下图,我们可以看出随机梯度下降法会使得函数发生震荡,同一位置上,目标函数在竖直方向( x2 轴方向)比在水平方向( x1 轴方向)的斜率的绝对值更大。因此,给定学习率,梯度下降迭代自变量时会使自变量在竖直方向比在水平方向移动幅度更大。那么,我们需要一个较小的学习率从而避免自变量在竖直方向上越过目标函数最优解。然而,这会造成自变量在水平方向上朝最优解移动变慢。 2019070204.png
- 我们试着将学习率调得稍大一点,此时自变量在竖直方向不断越过最优解并逐渐发散。见下图。 2019070205.png
-
设时间步t的自变量为 ,学习率为 ,梯度为 。 在时间步0,动量法创建速度变量 ,并将其元素初始化成。在时间步 ,动量法对每次迭代的步骤做如下修改:
其中,动量超参数满足。当时,动量法等价于小批量随机梯度下降。 - 在使用动量法后的迭代轨迹如下图,我们能够观察到,动量法在竖直方向上的移动更加平滑,且在水平方向上更快逼近最优解。使用较大的学习率,此时自变量也不再发散。 2019070206.png
2.5.3由指数加权移动平均理解动量法
-
现在,我们对动量法的速度变量做变形:
由指数加权移动平均的形式可得,速度变量 实际上对序列 做了指数加权移动平均。换句话说,相比于小批量随机梯度下降,动量法在每个时间步的自变量更新量近似于将前者对应的最近 个时间步的更新量做了指数加权移动平均后再除以 。所以,在动量法中,自变量在各个方向上的移动幅度不仅取决当前梯度,还取决于过去的各个梯度在各个方向上是否一致。在本节之前示例的优化问题中,所有梯度在水平方向上为正(向右),而在竖直方向上时正(向上)时负(向下)。这样,我们就可以使用较大的学习率,从而使自变量向最优解更快移动。 -
动量法使用了指数加权移动平均的思想刚好可以解决我们所面临的问题,。它将过去时间步的梯度做了加权平均,且权重按时间步指数衰减。
-
动量法使得相邻时间步的自变量更新在方向上更加一致。
-
动量法主要是提高收敛速度。
2.6 AdaGrad算法
2.6.1 动量法的缺陷
- 通过动量法我们知道目标函数自变量的每一个元素在相同时间步都使用同一个学习率来自我迭代。举个例子,假设目标函数为 ,自变量为一个二维向量,该向量中每一个元素在迭代时都使用相同的学习率。例如,在学习率为 的梯度下降中,元素 和 都使用相同的学习率来自我迭代:
当 和 的梯度值有较大差别时,需要选择足够小的学习率使得自变量在梯度值较大的维度上不发散。但这样会导致自变量在梯度值较小的维度上迭代过慢。这时我们该如何确定学习率呢?而AdaGrad算法,它根据自变量在每个维度的梯度值的大小来调整各个维度上的学习率,从而避免统一的学习率难以适应所有维度的问题。
2.6.2 AdaGrad算法
-
AdaGrad算法会使用一个小批量随机梯度 按元素平方的累加变量 。在时间步0,AdaGrad将 中每个元素初始化为0。在时间步 ,首先将小批量随机梯度 按元素平方后累加到变量 :
其中 是按元素相乘。接着,我们将目标函数自变量中每个元素的学习率通过按元素运算重新调整一下:
其中 是学习率, 是为了维持数值稳定性而添加的常数,如 。这里开方、除法和乘法的运算都是按元素运算的。这些按元素运算使得目标函数自变量中每个元素都分别拥有自己的学习率。 -
在小批量随机梯度按元素平方的累加变量 出现在学习率的分母项中。因此,如果目标函数有关自变量中某个元素的偏导数一直都较大,那么该元素的学习率将下降较快;反之,如果目标函数有关自变量中某个元素的偏导数一直都较小,那么该元素的学习率将下降较慢。然而,由于 一直在累加按元素平方的梯度,自变量中每个元素的学习率在迭代过程中一直在降低(或不变)。所以,当学习率在迭代早期降得较快且当前解依然不佳时,AdaGrad算法在迭代后期由于学习率过小,可能较难找到一个有用的解。
-
观察下图AdaGrad算法对自变量的迭代轨迹。可以看到,自变量的迭代轨迹较平滑。但由于 的累加效果使学习率不断衰减,自变量在迭代后期的移动幅度较小。
2019070207.png - 我们使用更大的学习率,下图可以看到自变量更为迅速地逼近了最优解。 2019070208.png
2.7 RMSProp 算法
2.7.1 AdaGrad算法的缺陷
- AdaGrad算法最明显的缺陷是收敛速度慢。因为调整学习率时,分母上的变量 一直在累加按元素平方的小批量随机梯度,所以目标函数自变量每个元素的学习率在迭代过程中一直在降低(或不变)。因此,当学习率在迭代早期降得较快且当前解依然不佳时,AdaGrad算法在迭代后期由于学习率过小,可能较难找到一个有用的解。为了解决这一问题,RMSProp算法对AdaGrad算法做了一点小小的修改。
2.7.2 RMSProp
-
RMSProp(Root Mean Square Prop) 算法是一种自适应学习率的优化算法,其核心思想是通过统计相似梯度的平均值的方式来自动的调整学习率。
-
我们知道“动量法”依据指数加权移动平均。不同于AdaGrad算法里状态变量 是截至时间步 所有小批量随机梯度按元素平方和,RMSProp算法将这些梯度按元素平方做指数加权移动平均。具体来说,给定超参数 ,RMSProp算法在时间步计算
和AdaGrad算法一样,RMSProp算法将目标函数自变量中每个元素的学习率通过按元素运算重新调整,然后更新自变量
其中 是学习率,是为了维持数值稳定性而添加的常数,如 。因为RMSProp算法的状态变量 是对平方项的指数加权移动平均,所以可以看作是最近 个时间步的小批量随机梯度平方项的加权平均。如此一来,自变量每个元素的学习率在迭代过程中就不再一直降低(或不变)。
- 我们知道AdaGrad算法,自变量在迭代后期的移动幅度较小。但在同样的学习率下,RMSProp算法可以更快逼近最优解。见下图 2019070209.png
- RMSProp算法和AdaGrad算法的不同在于,RMSProp算法使用了小批量随机梯度按元素平方的指数加权移动平均来调整学习率。一般会在RNN中使用RMSProp算法。
2.8 AdaDelta算法
-
除了RMSProp算法以外,另一个常用优化算法AdaDelta算法也针对AdaGrad算法在迭代后期可能较难找到有用解的问题做了改进。有意思的是,AdaDelta算法没有学习率这一超参数。
-
AdaDelta算法也像RMSProp算法一样,使用了小批量随机梯度 按元素平方的指数加权移动平均变量 。在时间步0,它的所有元素被初始化为0。给定超参数 (对应RMSProp算法中的),在时间步,同RMSProp算法一样计算
与RMSProp算法不同的是,AdaDelta算法还维护一个额外的状态变量 ,其元素同样在时间步0时被初始化为0。我们使用来计算自变量的变化量:
其中是为了维持数值稳定性而添加的常数,如。接着更新自变量:
最后,我们使用来记录自变量变化量按元素平方的指数加权移动平均:
可以看到,如不考虑的影响,AdaDelta算法与RMSProp算法的不同之处在于使用来替代超参数。 -
AdaDelta算法没有学习率超参数,它通过使用有关自变量更新量平方的指数加权移动平均的项来替代RMSProp算法中的学习率。
2.9 Adam算法
-
Adam(adaptive moment estimation)算法在RMSProp算法基础上对小批量随机梯度也做了指数加权移动平均 。
-
Adam算法使用了动量变量 和RMSProp算法中小批量随机梯度按元素平方的指数加权移动平均变量 ,并在时间步0将它们中每个元素初始化为0。给定超参数 (算法作者建议设为0.9),时间步 的动量变量 即小批量随机梯度 的指数加权移动平均:
和RMSProp算法中一样,给定超参数 (算法作者建议设为0.999), 将小批量随机梯度按元素平方后的项 做指数加权移动平均得到 :
由于我们将 和 中的元素都初始化为0, 在时间步 我们得到 。将过去各时间步小批量随机梯度的权值相加,得到 。需要注意的是,当 较小时,过去各时间步小批量随机梯度权值之和会较小。例如,当 时,。为了消除这样的影响,对于任意时间步 ,我们可以将 再除以 ,从而使过去各时间步小批量随机梯度权值之和为1。这也叫作偏差修正。在Adam算法中,我们对变量 和 均作偏差修正:
接下来,Adam算法使用以上偏差修正后的变量 和 ,将模型参数中每个元素的学习率通过按元素运算重新调整:
其中 是学习率, 是为了维持数值稳定性而添加的常数,如 。和AdaGrad算法、RMSProp算法以及AdaDelta算法一样,目标函数自变量中每个元素都分别拥有自己的学习率。最后,使用 迭代自变量:
-
Adam算法在RMSProp算法的基础上对小批量随机梯度也做了指数加权移动平均。
-
Adam算法使用了偏差修正。
-
Adam算法是RMSProp算法与动量法的结合。