正则化与泛化(Dropout / BatchNorm / Label Smoothing)
先把结论放前面
正则化解决的是"训练误差低、测试误差高"的过拟合问题。深度学习的正则化和传统 ML 相比有两个特点:一是网络参数多到几乎必然过拟合,二是 BatchNorm 等技术同时有正则化效果。
三大核心手段:
- Dropout:训练时随机失活神经元,测试时关闭,类似模型集成
- BatchNorm:稳定每层输入分布,同时有隐式正则化效果
- Label Smoothing:软化标签,降低模型对错误标签的置信度
Dropout
核心机制
训练时,每个 Batch 随机让 p% 的神经元失活(输出置零),失活的神经元的梯度也停止传播:
# 训练时
if self.training:
mask = torch.rand_like(x) > self.p # p=0.5
x = x * mask / (1 - self.p) # 缩放保持期望
# 测试时:所有神经元使用完整权重
缩放的原因:训练时只有 (1-p)% 的神经元参与计算,激活值期望变小。缩放后保证训练和测试时的输出分布一致。
为什么 Dropout 是隐式集成
Dropout 在每个 Batch 相当于训练一个"子网络"。整个训练过程相当于训练了 2^N 个子网络(每个神经元的失活组合),测试时用完整网络,相当于对所有子网络的结果做平均。
这比手动训练多个模型然后集成要高效得多。
Dropout 的工程注意点
- Dropout rate:p=0.5 是标准默认值,太高会让网络欠表达,太低正则化不够
- 训练时间:每次只更新部分神经元,训练速度约为原来的 1/(1-p)
- 用在 FC 层:CV 里 Conv 层后通常不用 Dropout(特征少,参数少,不容易过拟合);NLP 里 Transformer 的 FFN 层后有时用 Dropout
BatchNorm(批归一化)
核心问题:Internal Covariate Shift
深层网络的每一层输入分布会随着前层参数变化而变化(Internal Covariate Shift)。这导致:
- 每层需要不断适应新的输入分布
- 学习率不能太大,否则参数小变化 → 输入分布大变化 → 梯度不稳定
- 网络越深,底层对顶层的影响越被放大
BatchNorm 的解决方案
在每个 Batch 上对每层输入做归一化:
μ_B = (1/B) Σ x_i # Batch 均值
σ²_B = (1/B) Σ (x_i - μ)² # Batch 方差
x̂_i = (x_i - μ_B) / √(σ²_B + ε) # 归一化
y_i = γ · x̂_i + β # 可学习的仿射变换(Scale + Shift)
γ 和 β 是可学习的参数,让网络自己决定归一化到哪个尺度。
BatchNorm 为什么有效
- 稳定梯度流:输入归一化到 N(0, 1),梯度更稳定
- 允许更高学习率:不再需要小学习率防止梯度爆炸
- 隐式正则化:Batch 统计量有噪声,噪声提供了类似 Dropout 的正则化效果
BatchNorm 的注意事项
- 训练 vs 推理:训练时用当前 Batch 的均值/方差;推理时用滑动均值/方差(整个训练集的近似)
- Batch Size:Batch Size 太小(< 8)时,Batch 统计量噪声大,BatchNorm 效果差
- RNN:RNN 的序列长度不一致,BatchNorm 需要对每个时间步分别归一化,实际很少用
- 替代方案:LayerNorm(归一化每个样本的特征维度,不依赖 Batch Size)、InstanceNorm(归一化每个样本的每个通道)
BatchNorm vs LayerNorm vs InstanceNorm
BatchNorm: 沿 Batch 维度归一化(N, C, H, W)→ (N, C, H, W)
LayerNorm: 沿特征维度归一化(N, C, H, W)→ (N, 1, 1, 1)
InstanceNorm: 沿每个通道的 H×W 归一化(N, C, H, W)→ (N, C, 1, 1)
| 归一化 | 适用场景 | 依赖 Batch |
|---|---|---|
| BatchNorm | CNN、图像分类 | ✅ |
| LayerNorm | Transformer、RNN、NLP | ❌ |
| InstanceNorm | 风格迁移 | ❌ |
| GroupNorm | 小 Batch 的 CNN | ❌ |
Label Smoothing(标签平滑)
硬标签 vs 软标签
硬标签:真实类是 1.0,其他类是 0.0(如 [0, 1, 0])
软标签:真实类是 0.90.99,其他类是 00.1(如 [0.01, 0.98, 0.01])
Label Smoothing 把硬标签平滑化:
# K 类分类,smoothing = ε
label_smooth = (1 - ε) * hard_label + ε / K
为什么 Label Smoothing 有用
- 防止对错误标签过拟合:真实数据有标注噪声,如果模型对噪声标签也给 1.0 的置信度,会放大噪声影响
- 让 logits 更分散:softmax 输出的概率分布更平滑,不那么"极端"
- 知识蒸馏的软标签等价:Teacher 模型输出软标签 ≈ Label Smoothing
适用场景
- 大模型预训练:LLM / BERT 训练几乎都用 Label Smoothing(ε = 0.1)
- 知识蒸馏:Teacher 的软标签天然是 Label Smoothing
- 不适用:小数据集、噪声极少的场景
集成学习:提高泛化的额外手段
Snapshot Ensembling
在训练过程中记录多个checkpoint(每个 learning rate cycle 的最低点),推理时对多个模型的结果做平均。
Stochastic Depth(随机深度)
训练时随机跳过某些 ResBlock,推理时用完整网络。类似于 Dropout,但作用在层级别而非神经元级别。
如果放到面试里怎么讲
"BatchNorm 为什么要在训练和推理时用不同的均值/方差?"
训练时用当前 Batch 的均值和方差,是因为网络在训练阶段一直在适应新的数据分布。如果用全局统计量(推理时),网络会发现每一步的输入分布都在剧烈变化,BatchNorm 反而会放大这种变化。推理时的滑动均值/方差是训练集真实统计量的近似,所以推理时才用这个固定值。
"Dropout 和 BatchNorm 都有正则化效果,它们的区别是什么?"
Dropout 是显式正则化,通过随机失活神经元让网络不能依赖任何单一路径,防止过拟合。BatchNorm 是隐式正则化,它通过 Batch 统计量的噪声提供了类似集成学习的效果,同时也稳定了梯度流。两者可以同时用,不冲突。
最后记几个点
- Dropout 是隐式集成,训练时随机失活,推理时关闭缩放,类似训练 2^N 个子网络
- BatchNorm 解决 Internal Covariate Shift,稳定梯度流,同时有隐式正则化效果
- BatchNorm 训练用 Batch 统计量,推理用滑动均值,两者必须分开
- LayerNorm 不依赖 Batch Size,适合 NLP 和 Transformer,是 LayerNorm 而不是 BatchNorm
- Label Smoothing 软化硬标签,防止对错误标签过拟合,LLM 训练推荐 ε=0.1
- 大模型训练的正则化组合:AdamW + Dropout + Label Smoothing + Warmup + Cosine Annealing
跨库关联
- 归一化与残差连接 — LLM 中的 RMSNorm vs LayerNorm 详解