Simplestory's Blog

深度学习优化

Word count: 1.9kReading time: 8 min
2018/11/03

最优化是一个十分困难的问题,通常要精心设计一个目标函数及相关约束,同时还要确保所要优化的问题为凸函数,但现实中的问题大多为非凸函数,针对非凸优化问题,这里有一些基本的优化方法:SGD、Momentum、AdaGrad、RMSProp及Adam等

随机梯度下降(Stochastic Gradient Descent, SGD)


// 随机梯度下降

给定数据集\(X=\\{x^{(1)},x^{(2)},...,x^{(n)}\\}\), 数据集标记\(Y=\\{y^{(1)}, y^{(2)},...,y^{(n)}\\}\)

学习器\(f(x;w)\), 学习率(步长)\(\alpha\)

For 迭代足够多次

{

随机选择数据: \(\\{x^{(j)}, y^{(j)}\\}\)

计算损失梯度: \(\nabla\mathbf{w}=\frac{\partial{L(y^{(j)},f(x^{(j)};w))}}{\partial{w}}\)

修改权重: \(\mathbf{w_i}=\mathbf{w_i}-\alpha\nabla\mathbf{w}\)

}


以上是从数据集中随机选择一条数据进行梯度下降,故在训练过程中会出现很强的随机现象,为了避免这种随机性,可以选择多条数据进行梯度计算,之后再取平均值。

对于学习率,在上面的算法中,学习率一直保持不变,这在训练后期会造成算法在最优解附近振荡的现象,为了消除或缓解这种情况,我们可以在靠近最优解周围时尽可能地减小学习率

综合以上可得以下梯度下降算法


// 学习率衰减最小批量梯度下降

给定数据集\(X=\\{x^{(1)},x^{(2)},...,x^{(n)}\\}\), 数据集标记\(Y=\\{y^{(1)}, y^{(2)},...,y^{(n)}\\}\)

随机采样\(m\)条数据,训练周期\(k\),学习率衰减最低值\(b\),学习器\(f(x;w)\)

初始学习率(步长)\(\alpha_0\)

For \(i <= k\)

{

随机采样\(m\)条数据: \(\\{(x^{(i)},y^{(i)}),...,(x^{(m)},y^{(m)})\\}\)

计算采样数据平均损失值梯度: \(\nabla \mathbf{w} = \frac{1}{m}\sum^m_{j=1}\frac{\partial{L(y^{(j)},f(x^{(j)};w)})}{\partial{\mathbf{w}}}\)

计算衰减学习率: \(a_i=(i-\frac{i}{k})a_0+\frac{i}{k}b\)

修改网络权重: \(\mathbf{w}_i=\mathbf{w}_i-\alpha\nabla\mathbf{w}\)

}


动量学习法(Momentum)

上面的算法虽然解决了在最优解附近振荡以及随机性的问题,但却不能保证算法找到的解为全局最优解,算法随后有可能找到的是局部最优解,即为鞍点。

为了跳出鞍点,可以借助物理上的概念——动量,冲出鞍点,故有以下动量随机梯度下降法


// 动量学习法

给定数据集\(X=\\{x^{(1)},x^{(2)},...,x^{(n)}\\}\), 数据集标记\(Y=\\{y^{(1)}, y^{(2)},...,y^{(n)}\\}\)

初始速度\(v\),随机采样数据大小\(m\),训练周期\(k\)

学习器\(f(x;w)\),初始学习率\(\alpha\),初始动量参数\(\beta\)

For \(i <= k\)

{

随机采样\(m\)条数据: \(\\{(x^{(i)},y^{(i)}),...,(x^{(m)},y^{(m)})\\}\)

计算采样数据平均损失值梯度: \(\nabla \mathbf{w} = \frac{1}{m}\sum^m_{j=1}\frac{\partial{L(y^{(j)},f(x^{(j)};w)})}{\partial{\mathbf{w}}}\)

更新速度: \(v=\beta v-\alpha\nabla\mathbf{w}\)

更新参数: \(\mathbf{w}=\mathbf{w}+v\)

}


在实践中,常用的\(\beta\)取值可为0.5,0.9或0.99,根据具体问题进行调试,但对于\(\beta\)的调整,并没有\(\alpha\)的调整重要,因此不太需要作为超参数进行选择,一般取值适当即可。动量学习法在训练后期会出现轻微振荡。

NAG(Nesterov accelerated gradient)

为了解决动量学习法会出现轻微振荡的问题,NAG用\(\mathbf{w}-\beta v_{t-1}\)近似作为参数下一步会变成的值,故计算梯度时是在未来的位置上,在稀疏数据上表现很好。更新速度表示如下:

\[ v_t = \beta v_{t-1}+\alpha\nabla_\mathbf{w} J(\mathbf{w}-\beta v_{t-1}) \]

其中\(J(\cdot)\)为损失函数。NAG在梯度方向将要改变时,可提前预知,从而减弱这个过程,减少无用迭代。

AdaGrad、Adelta和RMSProp

以上的算法都使用一个全局学习率,所有的参数都是统一步伐整齐向前,但网络中的参数可能不会同时有一致的下降梯度和方向,以下算法针对每个参数单独配置学习率

AdaGrad

该算法其实就是将每一维各自的历史梯度的平方叠加起来,然后在更新的时候除以该历史梯度即可(使用平方的原因是去除梯度的符号,只对梯度的量进行累加)

\[cache_i = cache_i+(\nabla\mathbf{w}_i)^2\]

更新参数:

\[\mathbf{w}_i=\mathbf{w}_i-\frac{\alpha}{\sqrt{cache_i}+\delta}\nabla\mathbf{w}_i\]

其中\(\delta=10^{-7}\), 防止除零导致数值溢出

AdaGrad使得参数在累积的梯度量较小时(<1),放大学习率,使得网络的训练更加快速,在梯度的累积量较大时(>1),缩小学习率,延缓网络训练

但AdaGrad随着epoch的增长,学习率降低得很快,即该算法很容易过分降低学习率

Adelta

该方法对Adgard方法中随迭代次数的增多,学习率会变得非常小的情况进行了改进,主要是将\(cache\)更换为过去梯度平方的衰减平均值。参数更新公式如下:

\[ \begin{aligned} \mathbf{w}_t &= \mathbf{w}_{t-1} - \frac{\alpha}{\sqrt{E[g^2]_t}+\delta}g_t \\ E[g^2]_t &= \frac{1}{t}\sum_{i=1}^t g_i^2 \\ g_t &= \nabla\mathbf{w}_t \end{aligned} \]

这个分母相当于梯度的均方根(数理统计中,均方根为数据平方的平均值再开方)。故可简写为下式:

\[ \mathbf{w}_t = \mathbf{w}_{t-1}-\frac{\alpha}{RMS[g]_t}g_t \]

求平均值部分可以更换为增量式,并引入超参数\(\gamma\)(一般设定为0.9)来衡量过去与现在梯度的重要性:

\[ E[g^2]_t = \gamma E[g^2]_{t-1}+(1-\gamma)g_t^2 \]

还可将学习率更换为\(RMS[\Delta\mathbf{w}]\),这样就不需要预设学习率。

\[ \begin{aligned} \Delta\mathbf{w}_t &= -\frac{RMS[\Delta\mathbf{w}]_{t-1}}{RMS[g]_t}g_t \\ \mathbf{w}_t &= \mathbf{w}_{t-1}+\Delta\mathbf{w}_t \\ \end{aligned} \]

RMSProp

为了解决AdaGrad学习率衰减过快的问题,RMSProp算法引入了衰减因子,在进行梯度累积时会对“过去”和“现在”做一个权衡,通过\(\beta\)来调节衰减量,常用的取值有0.9或0.5

\[cache_i=\beta cache_i+(1-\beta)(\nabla \mathbf{w}_i)^2\]

在参数更新阶段,和AdaGrad相同

\[\mathbf{w}_i=\mathbf{w}_i-\frac{\alpha}{\sqrt{cache_i}+\delta}\nabla\mathbf{w}_i\]

Adam

该算法是Momentum+RMSProp的微调版本,默认情况下,推荐使用这种优化方法

在开始时梯度会非常小,\(r\)\(v\)经常会接近于0,因此我们还需要对\(r\)\(v\)进行调整

\[ \begin{aligned} vb=\frac{v}{1-\beta^t_1} \\ rb=\frac{r}{1-\beta^t_2} \end{aligned} \]

其中\(t\)表示训练次数,因此该算法仅在训练的前几轮中根据衰减因子来放大各自值,很快\(vb\),\(rb\)会衰减为\(v\)\(r\)


// Adam

给定数据集\(X=\\{x^{(1)},x^{(2)},...,x^{(n)}\\}\), 数据集标记\(Y=\\{y^{(1)}, y^{(2)},...,y^{(n)}\\}\)

初始速度\(v\),随机采样数据大小\(m\),训练周期\(k\)

学习器\(f(x;w)\),初始学习率\(\alpha\),初始动量参数\(\beta_1\)

学习率衰减参数\(\beta_2\), \(\delta=10^{-7}\)

For \(i <= k\)

随机采样\(m\)条数据: \(\\{(x^{(i)},y^{(i)}),...,(x^{(m)},y^{(m)})\\}\)

计算当前采样数据梯度: \(g = \frac{1}{m}\sum^m_{j=1}\frac{\partial{L(y^{(j)},f(x^{(j)};w)})}{\partial{\mathbf{w}}}\)

更新当前速度: \(v=\beta_1 v+(1-\beta_1)g\)

更新当前学习率: \(r=\beta_2 r+(1-\beta_2)g^2\)

更新训练次数: \(t=t+1\)

\[ \begin{aligned} vb=\frac{v}{1-\beta^t_1} \\ rb=\frac{r}{1-\beta^t_2} \end{aligned} \]

更新新参数:

\[w=w-\frac{\alpha}{\sqrt{rb}+\delta}vb\]

CATALOG
  1. 1. 随机梯度下降(Stochastic Gradient Descent, SGD)
  2. 2. 动量学习法(Momentum)
  3. 3. NAG(Nesterov accelerated gradient)
  4. 4. AdaGrad、Adelta和RMSProp
    1. 4.1. AdaGrad
    2. 4.2. Adelta
    3. 4.3. RMSProp
  5. 5. Adam