深度学习优化算法与正则化技术详解
1. 优化算法概述
在深度学习中,优化算法的目标是找到损失函数的最小值,从而使模型的性能达到最优。不同的优化算法在处理损失函数时具有不同的特点和优势。
1.1 无动量和有动量更新
在某些情况下,我们会使用不同的更新方式。对于图 9.9a,使用无动量的更新(方程 9.10);对于图 9.9b,使用有动量的更新(方程 9.11)。当损失等高线是以原点为中心的同心圆时,损失表面是一个顶点在原点的圆锥。随着我们接近最小值,优化过程会通过越来越小的圆形横截面沿着圆锥的内壁向下进行,全局最小值位于原点,对应零损失。在接近最小值时,无论有无动量,进展都会变慢(步长变小),这是因为接近最小值时梯度的大小会越来越小。然而,有动量时这种影响会在一定程度上得到缓解,因此达到较小半径的圆所需的步数会更少。
1.2 Nesterov 加速梯度(NAG)
动量梯度下降存在一个问题,即可能会越过最小值。如图 9.10a 所示,损失在一系列更新后下降,但接近最小值时,一次更新(红色箭头所示)可能会越过最小值,导致损失增加(红色圆圈所示)。Nesterov 加速梯度技术旨在解决这个问题,其具体步骤如下:
1. 估计本次更新将到达的位置(即目标点),通过将上一步的更新量加到当前点来实现。
2. 计算估计目标点的梯度,这与普通动量方法不同,普通动量方法是在当前点计算梯度。
3. 对估计目标点的梯度和上一步的更新量进行加权平均,得到当前步的更新量。
数学表达式如下:
[
\begin{align
}
\delta \vec{w}
t &= \gamma \delta \vec{w}
{t - 1} + \eta \nabla_{\vec{w}}L(\vec{w}
t - \gamma \delta \vec{w}
{t - 1}, \vec{b}
t - \gamma \delta \vec{b}
{t - 1})\
\delta \vec{b}
t &= \gamma \delta \vec{b}
{t - 1} + \eta \nabla_{\vec{b}}L(\vec{w}
t - \gamma \delta \vec{w}
{t - 1}, \vec{b}
t - \gamma \delta \vec{b}
{t - 1})
\end{align
}
]
其中,(\gamma) 和 (\eta) 是小于 1 的常数,权重和偏置将按照通常的方式使用方程 9.9 进行更新。
当远离最小值时,估计目标点的梯度与当前点的梯度大致相同,因此进展方式与动量梯度下降类似;但接近最小值且当前更新可能越过最小值时,估计目标点的梯度与上一步的梯度方向相反,加权平均后会使步长变小,从而减轻越过最小值的现象。
1.3 AdaGrad
动量优化方法(方程 9.11)和 Nesterov 方法(方程 9.13)都存在一个严重的缺点,即对参数向量 (\vec{w}) 和 (\vec{b}) 的所有维度一视同仁。但损失表面在各个维度上并不对称,某些维度的斜率可能较高,而其他维度的斜率可能较低。使用单一的学习率无法有效地控制所有维度的更新。
AdaGrad 试图为每个参数提供自适应的学习率,历史梯度较大的维度将有较小的学习率,而历史梯度较小的维度将有较大的学习率。为了跟踪梯度的历史大小,AdaGrad 维护一个状态向量 (\vec{s}
t),它累积了训练过程中到目前为止梯度向量每个维度的平方偏导数之和:
[
\vec{s}_t = |\nabla
{\vec{w}}L(\vec{w}
t, \vec{b}_t)|^2 + \vec{s}
{t - 1}
]
更新向量的表达式为:
[
\delta \vec{w}
t = \frac{\eta}{\sqrt{\vec{s}_t + \epsilon}} \circ \nabla
{\vec{w}}L(\vec{w}_t, \vec{b}_t)
]
其中,(\epsilon) 是一个非常小的常数,用于防止除零。偏置的更新有一组类似的方程,权重和偏置将按照通常的方式使用方程 9.9 进行更新。
1.4 RMSProp
AdaGrad 算法的一个显著缺点是,随着迭代次数增加,状态向量 (\vec{s}_t) 的大小会不断增大,导致所有维度的学习率越来越小。当迭代次数很高时,学习率接近零,更新几乎不起作用,向最小值的进展几乎停滞。
RMSProp 解决了这个问题,同时保留了 AdaGrad 的维度自适应特性。RMSProp 也维护一个状态向量,其方程为:
[
\vec{s}
t = (1 - \gamma) |\nabla
{\vec{w}}L(\vec{w}
t, \vec{b}_t)|^2 + \gamma \vec{s}
{t - 1}
]
与 AdaGrad 的状态向量方程相比,只是各项乘以了权重 ((1 - \gamma)) 和 (\gamma)((0 < \gamma < 1))。展开递归式后,(\vec{s}_t) 是过去项平方梯度幅度向量的加权和。随着迭代次数增加,权重之和趋近于 1,这意味着 RMSProp 状态向量实际上是过去项平方梯度幅度向量的加权平均。因此,随着迭代次数增加,权重会重新分配,旧的项会被弱化,但整体大小不会增加,从而消除了 AdaGrad 的学习率消失问题。
RMSProp 的更新方程为:
[
\delta \vec{w}
t = \frac{\eta}{\sqrt{\vec{s}_t + \epsilon}} \circ \nabla
{\vec{w}}L(\vec{w}_t, \vec{b}_t)
]
偏置的更新有一组类似的方程,权重和偏置将按照通常的方式使用方程 9.9 进行更新。
1.5 Adam 优化器
动量梯度下降随着迭代次数增加会不断放大下坡分量,而 RMSProp 会降低具有大梯度的维度的学习率,以平衡所有维度的进展速度。Adam 优化器结合了这两个理想特性,它维护两个状态向量:
[
\begin{align
}
\vec{v}
t &= (1 - \beta_1) \nabla
{\vec{w}}L(\vec{w}
t, \vec{b}_t) + \beta_1 \delta \vec{w}
{t - 1}\
\vec{s}
t &= (1 - \beta_2) |\nabla
{\vec{w}}L(\vec{w}
t, \vec{b}_t)|^2 + \beta_2 \vec{s}
{t - 1}
\end{align
}
]
其中,(0 < \beta_1 < 1) 和 (0 < \beta_2 < 1) 是两个常数。方程 9.16 本质上是方程 9.11 的动量方程,但权重改为 (\beta_1) 和 ((1 - \beta_1)),随着 (t \to \infty),状态向量将是所有过去梯度的加权平均,这是对原始动量方案的改进。第二个状态向量本质上与 RMSProp 的方程 9.15 相同。
Adam 创建更新向量的表达式为:
[
\delta \vec{w}
t = \frac{\eta \vec{v}_t}{\sqrt{\vec{s}_t + \epsilon}} \circ \nabla
{\vec{w}}L(\vec{w}_t, \vec{b}_t)
]
为了提高在较小 (t) 值时的近似效果,Adam 引入了偏差校正:
[
\begin{align
}
\hat{v}_t &= \frac{\vec{v}_t}{1 - \beta_1^t}\
\hat{s}_t &= \frac{\vec{s}_t}{1 - \beta_2^t}
\end{align
}
]
在方程 9.18 中使用校正后的 (\hat{v}_t) 和 (\hat{s}_t) 代替 (\vec{v}_t) 和 (\vec{s}_t)。
1.6 PyTorch 代码示例
以下是使用 PyTorch 实现各种优化器的代码:
from torch import optim
# 随机定义参数
params = [torch.randn(10, 10, requires_grad=True)]
sgd_optimizer = optim.SGD(params, lr=0.01)
sgd_momentum_optimizer = optim.SGD(params, lr=0.01, momentum=0.9)
sgd_nesterov_momentum_optimizer = optim.SGD(params, lr=0.01, momentum=0.9, nesterov=True)
adagrad_optimizer = optim.Adagrad(params, lr=0.001)
rms_prop_optimizer = optim.RMSprop(params, lr=1e-2, alpha=0.99)
adam_optimizer = optim.Adam(params, lr=0.001, betas=(0.9, 0.999))
优化算法对比表格
| 优化算法 | 优点 | 缺点 |
|---|---|---|
| 无动量更新 | 简单直接 | 接近最小值时进展慢 |
| 有动量更新 | 缓解接近最小值时进展慢的问题 | 可能越过最小值 |
| Nesterov 加速梯度 | 减轻越过最小值的现象 | 计算相对复杂 |
| AdaGrad | 自适应学习率 | 学习率可能消失 |
| RMSProp | 解决学习率消失问题,保留自适应特性 | 增加了超参数 |
| Adam 优化器 | 结合动量和自适应学习率的优点 | 超参数较多 |
优化算法选择流程图
graph TD;
A[选择优化算法] --> B{是否需要动量};
B -- 是 --> C{是否担心越过最小值};
C -- 是 --> D[Nesterov 加速梯度];
C -- 否 --> E[有动量更新];
B -- 否 --> F{是否需要自适应学习率};
F -- 是 --> G{是否担心学习率消失};
G -- 是 --> H[RMSProp];
G -- 否 --> I[AdaGrad];
F -- 否 --> J[无动量更新];
D --> K{是否需要结合更多优点};
K -- 是 --> L[Adam 优化器];
K -- 否 --> D;
2. 正则化技术
在深度学习中,我们不希望模型仅仅记住每一个训练实例,而是希望它能够形成抽象概念,以便在推理阶段能够识别那些在训练阶段未曾见过的对象实例。如果模型过于复杂,就可能会出现过拟合的问题,即模型在训练数据上表现良好,但在测试数据上表现不佳。正则化是一组用于防止过拟合的技术。
2.1 过拟合与欠拟合
过拟合和欠拟合是深度学习中常见的问题,它们对模型的性能有着重要影响。
-
过拟合
:当模型具有过多的表达能力(例如过多的神经元或权重),相对于训练实例的数量,模型会试图记住每一个训练实例,导致决策边界变得复杂,以适应训练数据中的噪声或异常值。这会使得模型在测试数据上的表现变差。例如,在图 9.11 中,填充的圆圈表示训练数据,未填充的圆圈表示测试数据。有两个异常的训练数据实例(绿色区域中的红色填充点),决策边界(实线)变得曲折以适应它们,导致许多测试点被错误分类。如果选择一个“更简单”的决策边界(虚线),虽然这两个异常训练点会被错误分类,但模型在测试中的表现会更好。
-
欠拟合
:当模型的表达能力不足,无法对训练数据进行有效建模时,就会出现欠拟合的问题。欠拟合的症状是模型在训练数据和测试数据上的表现都很差。如果出现欠拟合,我们应该尝试使用更复杂的网络,例如增加神经元的数量。
2.2 最小描述长度(MDL)与奥卡姆剃刀原理
在机器学习中,我们通常会有一组能够最小化损失的候选神经网络参数值(权重和偏置)。根据奥卡姆剃刀原理,我们应该选择其中“最简单”的一个。奥卡姆剃刀是一个哲学原则,其字面翻译为“如无必要,勿增实体”,在机器学习中通常被解释为:在能够最小化损失的候选参数值中,选择最简单的那个。
为了实现这一目标,我们在原始损失项中添加一个惩罚项,以惩罚偏离“简单性”的情况。因此,我们最小化的目标函数为:
[
L(\theta) + \lambda R(\theta)
]
其中:
- (L(\theta)) 是原始的损失函数,(\theta) 表示权重 (\vec{w}) 和偏置 (\vec{b}) 。
- (R(\theta)) 是一个衡量“非简单性”的指标,也称为正则化惩罚项。添加正则化惩罚项可以激励模型在最小化原始损失函数的同时,尽量减小 (R(\theta)) ,即最大化简单性。
- (\lambda) 是一个超参数,其值需要通过试验和错误来仔细选择。如果 (\lambda) 太小,模型几乎没有进行正则化,容易出现过拟合;如果 (\lambda) 太大,正则化惩罚项将主导目标函数,模型可能无法充分最小化实际的损失项。
2.3 L2 正则化
L2 正则化是最常用的正则化方法之一。在 L2 正则化中,我们假设简单性与 L2 范数(即欧几里得范数)的平方成反比。因此,正则化惩罚项为:
[
R(\theta) = (|\vec{w}|^2 + |\vec{b}|^2)
]
我们最小化的目标函数为:
[
L(\vec{w}, \vec{b}) = \sum_{i = 0}^{n - 1} L^{(i)}(\vec{y}^{(i)}, \bar{y}^{(i)}) + \lambda (|\vec{w}|^2 + |\vec{b}|^2)
]
在 PyTorch 中,超参数 (\lambda) 通常被称为权重衰减(weight decay)。权重衰减通常设置为一个较小的数,以确保方程 9.21 中的第二项(权重向量的范数)不会掩盖实际的损失项。以下是使用 PyTorch 实现 L2 正则化的代码示例:
from torch import optim
# 随机定义参数
params = [torch.randn(10, 10, requires_grad=True)]
optimizer = optim.SGD(params, lr=0.2, weight_decay=0.01)
2.4 L1 正则化
L1 正则化与 L2 正则化在原理上类似,但它将简单性定义为权重和偏置的绝对值之和:
[
R(\theta) = (|\vec{w}| + |\vec{b}|)
]
我们最小化的目标函数为:
[
L(\vec{w}, \vec{b}) = \sum_{i = 0}^{n - 1} L^{(i)}(\vec{y}^{(i)}, \bar{y}^{(i)}) + \lambda (|\vec{w}| + |\vec{b}|)
]
2.5 L1 与 L2 正则化的稀疏性
L1 正则化和 L2 正则化在产生稀疏模型方面具有不同的特点。
-
L1 正则化
:倾向于产生稀疏模型,即许多权重为 0。这是因为 L1 正则化的梯度在权重不为 0 时是一个常数,无论权重的大小如何,它都会以相同的步长将权重推向 0。例如,对于单个权重 (w),L1 正则化的损失函数为 (L(w) = |w|),其导数为:
[
\frac{\partial L(w)}{\partial w} = \begin{cases}
-1, & \text{if } w < 0 \
0, & \text{if } w = 0 \
1, & \text{if } w > 0
\end{cases}
]
-
L2 正则化
:倾向于产生具有较小(但非零)权重的模型。L2 正则化的梯度与权重的大小成正比,因此它会逐渐减小权重的大小,但不会将其精确地推向 0。
正则化方法对比表格
| 正则化方法 | 正则化惩罚项 (R(\theta)) | 特点 |
|---|---|---|
| L2 正则化 | ((|\vec{w}|^2 + |\vec{b}|^2)) | 常用,产生较小但非零的权重 |
| L1 正则化 | (( | \vec{w} |
正则化选择流程图
graph TD;
A[选择正则化方法] --> B{是否需要稀疏模型};
B -- 是 --> C[L1 正则化];
B -- 否 --> D[L2 正则化];
C --> E{是否需要更简单的实现};
E -- 是 --> F[使用 PyTorch 实现 L1 正则化];
E -- 否 --> C;
D --> G{是否需要更稳定的性能};
G -- 是 --> H[使用 PyTorch 实现 L2 正则化];
G -- 否 --> D;
综上所述,优化算法和正则化技术在深度学习中都起着至关重要的作用。选择合适的优化算法可以帮助模型更快地收敛到最优解,而正则化技术可以防止模型过拟合,提高模型的泛化能力。在实际应用中,我们需要根据具体的问题和数据特点,选择合适的优化算法和正则化方法。通过合理使用这些技术,我们可以构建出更加高效、准确的深度学习模型。
超级会员免费看
987

被折叠的 条评论
为什么被折叠?



