深度学习问题需要一个损失函数,我们的目标就是通过优化算法来最小化损失,即最小化目标(损失)函数。
需要注意的是,优化和深度学习的本质目标有差异:优化关注的是最小(最大)化目标函数,深度学习更关注模型的泛化能力。比如说,训练阶段的目标是最小化训练误差,但深度学习真正关心的是减小泛化误差,也就是推理阶段的误差。
最小化目标函数
最小化目标函数时,优化过程容易在梯度接近 0 的位置停滞。下述几种情况都可能导致这一问题。
-
局部最小值:某点的函数值小于其附近所有点的函数值,为局部最小值;整个函数域内的最小值为全局最小值。当目标函数接近局部最优时,梯度会接近 0。使用一定程度的噪声(SGD)可以让参数跳出局部最优。
-
鞍点(saddle point):一个不是局部极值点的驻点称为鞍点。此时函数的梯度为 0,但该点既非局部最小值、也非局部最大值。这种情况下优化同样会停滞。多元函数 f(x,y)=x^2-y^2 在原点处就是典型的鞍点;一元函数 f(x)=x^3 在 x=0 处则是驻点,同时也是拐点。
- 驻点(stationary point):函数的一阶导数为零的点。
- 拐点(inflection point):在一条连续曲线上,曲线的凹凸性发生改变的点。
凸 Convex
英文的逆天性在凹(concave) 凸(convex) 这两个单词上得到了极大体现。凹进去的函数是凸函数,凸出来的函数是凹函数。
凸函数最重要的一个特性就是:局部极小值就是全局极小值。也就是说,在最小化损失函数时,如果损失函数是凸函数,就不必担心陷入局部最小值的问题。
此外,凸优化的另一个特性是能有效处理约束。先明确什么是约束优化问题:
比如在训练中,我们的目标是最小化损失函数 f(x),同时要求 x 落在由 c_i(x) 定义的可行域内。
理论核心:拉格朗日函数
直接求解带约束的优化问题较难。拉格朗日函数通过引入拉格朗日乘数,将约束条件融入目标函数,把约束优化问题转化为无约束的鞍点优化问题。
公式中,\alpha_i 是拉格朗日乘数,非负实数。
- 若约束未激活,c_i(x)<0,参数在可行域内部,则 \alpha_i=0,该约束对最优解不起作用。
- 若约束激活,c_i(x)=0,参数在可行域边界,则 \alpha_i>0,约束在最优解处被收紧。
无论哪种情况,都满足 \alpha_i c_i(x)=0,这被称作互补松弛条件。互补松弛条件帮助我们在优化过程中判断哪些约束是活跃的,哪些是松弛的。
拉格朗日函数的最优解是鞍点。
- 对 x 最小化 L:等价于在约束条件下最小化目标函数 f(x)
- 对 \alpha_i 最大化 L:等价于找到最合适的约束力度
实践方法
深度学习的损失函数并不总是凸函数,精确求解鞍点也不一定可行。
- 惩罚方法:直接保留拉格朗日函数中的 \alpha_i c_i 项,加入到原损失函数中,获得新的优化目标。
经典的惩罚方法例子包括权重衰减(Weight Decay,L2 正则化)。
权重衰减的约束函数为:
权重衰减的惩罚项及最终优化目标为:
- 投影方法
惩罚方法属于软约束,投影方法属于硬约束。无论参数优化到哪里,都被强制投影回可行域内,确保约束被严格满足。
典型方法包括梯度截断 (Gradient Clipping)。
梯度下降 Gradient Descent
GD 每次迭代使用全部训练样本计算梯度,然后统一更新参数,计算量巨大。因此有人提出了随机梯度下降(SGD)。SGD 是对 GD 的无偏估计,二者数学期望一致:
SGD 每次迭代随机选取一个样本计算梯度,然后更新参数。
不过 SGD 收敛不稳定,更新路径震荡比较大,对学习率也比较敏感,因此引入了动态学习率的概念:
为了平衡 GD 的稳定性和 SGD 的高效性,有人提出了 MiniBatch GD,即小批量梯度下降。这是目前 DL 的主流选择。GD 和单样本 SGD 在工程中使用极少;如果提到了 SGD,除非特别说明,否则一般指的是 MiniBatch GD。算法库中 API 的 SGD 实际上使用的也是 MiniBatch GD。下文中 SGD 如不加说明,均指 MiniBatch GD。
| 特性 | GD | SGD | MiniBatch GD |
|---|---|---|---|
| 数据使用量 | 全部训练样本 | 单个随机样本 | 一批样本(如 32、64) |
| 计算效率 | 低(计算量大) | 高(计算量最小) | 中等 |
| 收敛稳定性 | 高(路径平滑) | 低(路径震荡大) | 中等 |
| 内存需求 | 高(需加载全部数据) | 低(加载一个样本) | 中等(需加载小批量) |
动量法 Momentum
核心是利用过去梯度的加权平均替代瞬时梯度。
动态学习率解决的是训练过程中如何调整学习率的问题,动量法主要解决梯度噪声导致下降方向不稳定的问题。
SGD 本身通过平均 Batch 内的梯度以减小方差;动量法的泄漏平均值(Leaky Ave)则是在时间维度上对过去梯度做加权平均,以进一步降低方差。
其中:
- v_t:动量,梯度的累计
- \beta:动量系数,表示对过去梯度的记忆程度
- g_{t,t-1}:t-1 时刻的瞬时梯度(SGD 梯度)
公式递归展开可以得到:
大的 \beta 说明对过去梯度记忆久,相当于长期平均;小的 \beta 说明仅关注近期梯度。
AdaGrad
全称 Adaptive Gradient,即自适应梯度算法,是梯度下降算法的一种改进。在一般的 SGD 中,学习率是统一的;AdaGrad 认为不同的参数需要不同的学习率。
最终目的是在凸函数优化上能够快速收敛。
梯度平方的累积量更新:
参数更新:
其中:
- g_i:参数 x_i 的梯度
- s_i:初值为 0,g_i 的累计平方和
- \eta:学习率
- \epsilon:极小常数,避免分母为 0
自动调整的方式,就是将学习率 \eta 除以 \sqrt{s_i+\epsilon} 来实现的。
RMSProp
均方根传播,全称 Root Mean Square Propagation。是 AdaGrad 的改进:
梯度平方的累积量更新:
参数更新:
加入了一个衰减系数 \gamma,取值范围 [0, 1]。衰减系数可以避免 s_i 无限增大,从而缓解 AdaGrad 学习率过早消失的问题。
AdaDelta
改进的 RMSProp,去掉了全局学习率,完全不需要手动设置学习率。
梯度平方的累计量更新:
修正后的梯度计算:
参数值更新:
参数变化量平方的累计量更新:
这里的 \rho 为衰减系数。
太复杂的公式不用记,只需要知道 AdaDelta 用 \sqrt{\Delta x_i + \epsilon} 与 \sqrt{s_i + \epsilon} 的比值来替代原本的学习率,让每一步更新幅度更加自适应。
Adam
全称 Adaptive Moment Estimation,整合了 RMSProp 和 Momentum 方法。
Adam 可以说是目前 DL 中使用频率最高的优化方法了。
融合 Momentum 的惯性特性,即梯度的指数移动平均:
参考 RMSProp 自适应学习率,梯度平方的指数移动平均:
一般将 \beta_1 和 \beta_2 分别设为 0.9 和 0.999。
为了避免初始偏差过大,对上述 m_i 和 v_i 进行修正:
参数最终更新:
PyTorch 中已经对上述优化方法提供了直接的参数实现:
# 1 带动量的 SGD (Momentum)
model_momentum = LinearModel()
optimizer_momentum = optim.SGD(model_momentum.parameters(), lr=lr, momentum=0.9) # momentum=0.9 是常用值
loss_momentum = train_model(model_momentum, optimizer_momentum, epochs)
# 2 Adagrad
model_adagrad = LinearModel()
optimizer_adagrad = optim.Adagrad(model_adagrad.parameters(), lr=lr) # 自适应学习率,无需手动调 momentum
loss_adagrad = train_model(model_adagrad, optimizer_adagrad, epochs)
# 3 RMSprop
model_rmsprop = LinearModel()
optimizer_rmsprop = optim.RMSprop(model_rmsprop.parameters(), lr=lr, alpha=0.99) # alpha 是移动平均系数
loss_rmsprop = train_model(model_rmsprop, optimizer_rmsprop, epochs)
# 4 Adam
model_adam = LinearModel()
optimizer_adam = optim.Adam(model_adam.parameters(), lr=lr, betas=(0.9, 0.999)) # betas 是两个动量系数
loss_adam = train_model(model_adam, optimizer_adam, epochs)
参考文章
[2] 11. 优化算法 — 动手学深度学习 2.0.0 documentation
[3] Anderson, S. (n.d.). Lecture 5 Optimisation for Training Deep Networks [Lecture]. In ACS61011 Deep Learning. University of Sheffield.
评论