趋近智
虽然优化器和学习率调度器引导训练过程趋向最小值,但正则化 (regularization)技术对于确保所学模型能够很好地泛化到未见过的数据,从而防止过拟合 (overfitting)非常重要。基本的 L1 或 L2 权重 (weight)衰减虽然有用,但有时会显得不足,尤其是在处理复杂架构和大型数据集时。这里将讨论 PyTorch 生态系统中更高级的正则化方法。
在 Adam 等自适应优化器中,L2 正则化 (regularization)的常见实现通常将权重衰减项与梯度计算耦合。这意味着衰减效果受到优化器计算的自适应学习率的影响(具体来说是梯度平方的历史记录 )。这种耦合可能导致次优性能,尤其是在出现大梯度时,因为有效的权重衰减可能比预期小。
AdamW 优化器由 Loshchilov 和 Hutter (2019) 提出,它通过将权重衰减与梯度更新解耦来解决这个问题。AdamW 不会将衰减项添加到梯度中,而是在主要优化步骤之后直接对权重施加衰减。
带有 L2 正则化的标准 Adam 更新如下:
而 AdamW 执行如下操作:
(注意:这里的 代表可能被 Adam 自适应组件修改过的学习率)。重要的区别在于,衰减项 是单独应用的,并且不受 AdamUpdate 中自适应学习率项的缩放。
在 PyTorch 中,使用 AdamW 很简单:
import torch
import torch.optim as optim
# 假设模型已定义
model = ...
# 使用 AdamW 代替 Adam
optimizer = optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-2)
# 训练循环保持不变
# ...
# optimizer.zero_grad()
# loss.backward()
# optimizer.step()
# ...
为 AdamW 选择合适的 weight_decay 值通常需要进行实验,但 1e-2 到 1e-1 之间的值是常见的起始值,通常高于标准 Adam 耦合 L2 正则化所用的值。AdamW 已成为训练许多现代架构(尤其是 Transformer)的标准选择。
分类模型通常使用交叉熵损失和独热编码的目标标签(例如 [0, 0, 1, 0])进行训练。这鼓励模型对正确类别产生极高的置信度,而对不正确类别产生非常低的置信度。虽然这促使模型完美拟合训练数据,但它可能导致过度自信和泛化能力差。模型可能对训练数据中的特定特征过于敏感,未能捕捉更广泛的模式。
标签平滑正则化 (regularization)(LSR)通过稍微软化目标标签来解决这个问题。它不是要求模型对正确类别预测为 1、对其他类别预测为 0,而是鼓励模型为不正确的类别分配一个小的概率质量 (epsilon)。
对于一个有 个类别的分类问题,如果样本的原始独热标签是 (真实类别为 1,否则为 0),则平滑后的标签 变为:
其中, 在 是真实类别索引时为 1,否则为 0。项 将正确类别的目标概率从 1.0 降低到 。项 将剩余的概率质量 均匀地分布到所有 个类别中(包括正确类别,尽管其主要作用是增加不正确类别的概率)。
例如,当 个类别且 时,独热标签 [0, 0, 1, 0, 0] 变为:
[0.02, 0.02, 0.9, 0.02, 0.02]
这鼓励模型的输出对数(在最终 softmax 之前)对于正确类别而言,相对于不正确类别的对数不那么极端。它通过防止模型变得过度自信来充当正则化器。
PyTorch 的 torch.nn.CrossEntropyLoss 通过 label_smoothing 参数 (parameter)直接支持标签平滑:
import torch
import torch.nn as nn
# 示例用法
num_classes = 10
smoothing_factor = 0.1
criterion = nn.CrossEntropyLoss(label_smoothing=smoothing_factor)
# 在训练循环中
# outputs = model(inputs) # 形状: [batch_size, num_classes]
# targets = ... # 形状: [batch_size],包含类别索引
# loss = criterion(outputs, targets)
# loss.backward()
的常见值通常很小,通常在 0.05 到 0.1 之间。
Dropout 是一种广泛使用的正则化 (regularization)技术,它在训练期间随机将单个神经元激活设置为零。随机深度,也称为 DropPath,提供了一种不同的方法,在具有残差连接的网络(如 ResNets 或 Transformer)中特别有效。随机深度不是丢弃单个神经元,而是在训练期间随机丢弃整个残差块或层。
考虑一个残差块,其输出为 。使用随机深度时,此变换在训练期间进行修改:
其中, 是一个伯努利随机变量,取值可为 0 或 1。它以 的概率取值 0(丢弃块),以 的概率取值 1(保留块)。概率 是块 的生存概率。
通常,网络中较深层的生存概率会线性降低。对于一个有 个块的网络,块 (其中 的范围从 1 到 )的生存概率可以设置为:
其中, 是最终块的目标生存概率。这种方案意味着较早的层(更接近输入)更可能被保留,而较深的层更可能被丢弃。
在推理 (inference)时,所有块都被保留,但它们的输出可能按其各自的生存概率 进行缩放,以补偿它们在训练期间出现频率较低的事实。然而,许多实现隐式处理此缩放或认为其没有必要。
随机深度的优点包括:
实现随机深度通常涉及使用专门的层。像 timm(PyTorch 图像模型)这样的库提供了方便的 DropPath 模块:
# 使用 timm 的 DropPath 示例
# 确保已安装 timm:pip install timm
from timm.models.layers import DropPath
class MyResidualBlock(nn.Module):
def __init__(self, dim, drop_prob=0.):
super().__init__()
self.norm1 = nn.LayerNorm(dim)
self.linear1 = nn.Linear(dim, dim * 4)
self.activation = nn.GELU()
self.linear2 = nn.Linear(dim * 4, dim)
# 随机深度层
self.drop_path = DropPath(drop_prob) if drop_prob > 0. else nn.Identity()
def forward(self, x):
shortcut = x
x = self.norm1(x)
x = self.linear1(x)
x = self.activation(x)
x = self.linear2(x)
# 将 DropPath 应用于残差函数的输出
x = shortcut + self.drop_path(x)
return x
# 在大型模型中的使用示例
# drop_probabilities = torch.linspace(0, 0.1, num_layers) # 线性衰减
# block = MyResidualBlock(dim=embed_dim, drop_prob=drop_probabilities[i].item())
传递给 DropPath 的 drop_prob 对应于 。选择丢弃概率的范围(例如,从 0 线性增加到 0.1 或 0.2)是另一个需要调整的超参数 (parameter) (hyperparameter)。
这些高级正则化技术通常结合使用,为提高使用 PyTorch 训练的深度学习 (deep learning)模型的稳健性和泛化能力提供了强大的方法。通常需要通过实验为特定任务和架构找到最佳组合和超参数。
这部分内容有帮助吗?
AdamW优化器的文档,详细说明了其用法和参数。CrossEntropyLoss模块的文档,包括对标签平滑的支持。© 2026 ApX Machine Learning用心打造