- 示例工程
【免费下载链接】NYU-DLSP20
NYU Deep Learning Spring 2020
本篇文章围绕 NYU Deep Learning Spring 2020 课程第 14 周第 3 讲(docs/ja/week14/14-3.md,对应英文原文 docs/en/week14/14-3.md)展开,系统讲解过拟合(オーバーフィッティング)的成因、直接正则化方法(权重衰减 / L1 / Dropout / 早期停止)、间接正则化手段(BatchNorm、数据扩充、迁移学习),并延伸到用 Dropout 估计预测不确定性的贝叶斯神经网络思想。读完本文,你将掌握在 PyTorch 中配置weight_decay、Dropout、BatchNorm1d等关键 API 的完整姿势,并能借助仓库中的 12-regularization.ipynb 与 13-bayesian_nn.ipynb 复现全部实验。
一、过拟合:模型太强也是一种问题
1.1 欠拟合、正常拟合与过拟合
考虑一个回归问题。根据模型复杂度与数据复杂度之间的关系,模型可以处于三种状态:
- 欠拟合(過少適合 / underfit):模型的表达能力不足以刻画数据中的真实模式,训练误差与泛化误差都偏高;
- 正常拟合(right-fit):模型既能学到数据背后的规律,又不至于记住噪声;
- 过拟合(過剰適合 / overfit):模型表达能力超过数据所需——深度神经网络正是典型情况——它有能力同时拟合"真实数据"和"噪声",从而在当前任务上给出糟糕的解。
我们真正想要的是:让模型拟合数据背后的分布,而不是拟合噪声。尤其希望在不降低模型容量(power)的前提下做到这一点。深度学习模型往往比"严格必要"的能力强得多,这种余量让训练更轻松,但也带来了过拟合风险,因此需要用正则化手段来"对冲"。
1.2 用"故意过拟合"来调试网络
过拟合并非总是坏事。在调试阶段,它可以成为有力的工具:
取训练数据的一小部分子集(哪怕只是一个 batch,甚至是一组随机噪声张量),训练网络并确认它能够在这份小数据上过拟合。如果连这份数据都学不进去,往往说明代码里存在 bug。
这是一个非常实用的工程技巧:先用极小数据集验证"网络具备学习能力、梯度链路通畅",再去排查数据管线或模型结构问题。仓库中的 12-regularization.ipynb(第 28 号 cell 定义FeedforwardNeuralNetModel,第 31 号 cell 实现训练循环)正是可以在 IMDB 文本分类任务上逐一"开/关"正则化开关的完整实验台。
二、正则化:给模型注入先验知识
2.1 什么是正则化
正则化(正則化 / regularization)通过向模型注入先验知识来对抗过拟合:为参数指定一个先验分布,等价于在"可学习的函数集合"上施加限制。正则化强度直接决定验证性能:
- 正则化太弱 → 无法解决过拟合;
- 正则化太强 → 模型效果大打折扣。
Ian Goodfellow 给出的经典定义是:
正则化是我们对学习算法所做的任何修改,其目的在于降低泛化误差(generalization error),而非降低训练误差(training error)。
这句话点出了关键:判断一种手段是否是正则化,看它是否只致力于缩小"训练误差与验证误差之间的鸿沟"。
2.2 初始化技巧:把先验"种"进权重
我们可以按照特定分布初始化权重,从而为网络参数"选择先验"。一个经典选项是Xavier 初始化(PyTorch 中对应torch.nn.init.xavier_normal_/torch.nn.init.xavier_uniform_)。恰当的初始化让各层信号在前向、反向传播中保持尺度稳定,间接帮助训练更平稳、降低对正则化的依赖。
三、直接正则化方法
3.1 权重衰减(Weight Decay):L2 / 岭回归 / 高斯先验
权重衰减是第一种正则化技术,在传统机器学习中广泛使用,但在神经网络中常被低估。PyTorch 中它直接作为优化器的参数出现,例如 SGD 或 Adam 的weight_decay:
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3, weight_decay=0.005)它还有几个等价称呼,揭示了同一件事的不同视角:
- L2 正则化(惩罚项形式);
- Ridge / 岭回归(统计学习视角);
- 高斯先验(贝叶斯视角:等价于对参数施加零均值高斯分布先验)。
从目标函数看,未加正则化时参数上的训练目标与更新式为:
$$J_{\text{train}}(\theta) = J^{\text{old}}_{\text{train}}(\theta)$$
$$\theta \gets \theta - \eta \nabla_{\theta} J^{\text{old}}_{\text{train}}(\theta)$$
加入权重衰减后,在目标函数上添加罚项:
$$J_{\text{train}}(\theta) = J^{\text{old}}_{\text{train}}(\theta) + \underbrace{\frac\lambda2 {\lVert\theta\rVert}2^2}{\text{penalty}}$$
对应更新式变为:
$$\theta \gets \theta - \eta \nabla_{\theta} J^{\text{old}}{\text{train}}(\theta) - \underbrace{\eta\lambda\theta}{\text{decay}}$$
新增项-ηλθ会在每次更新时把参数 θ 向零"拉"一点,这就是"权重衰减(decay)"名称的由来。超参数 λ 控制衰减强度。注意一个实现细节:在 PyTorch 的 SGD/Adam 等优化器中,weight_decay直接作用于参数更新项(等价于上式的 decay 项),而不是把 L2 项并入 loss 再求梯度——两者在大多数优化器(尤其是带动量的)下并不严格等价。
3.2 L1 正则化:LASSO / 拉普拉斯先验 / 稀疏先验
L1 正则化在 PyTorch 优化器中同样可以作为选项使用,别名包括:
- LASSO(Least Absolute Shrinkage Selector Operator);
- 拉普拉斯先验(Laplacian prior);
- 稀疏先验(Sparsity prior)。
从贝叶斯视角看,L1 等价于对参数施加拉普拉斯分布先验;与高斯先验相比,拉普拉斯分布在零点附近集中了更多的概率质量,因此更容易把参数"压"到恰好为零。
同样从原始更新出发,L1 添加的罚项是:
$$J_{\text{train}}(\theta) = J^{\text{old}}_{\text{train}}(\theta) + \underbrace{\lambda{\lVert\theta\rVert}1}{\text{penalty}}$$
更新式变成:
$$\theta \gets \theta - \eta \nabla_{\theta} J^{\text{old}}{\text{train}}(\theta) - \underbrace{\eta\lambda\cdot\mathrm{sign}(\theta)}{\text{penalty}}$$
与 L2 的关键区别:L2 均匀地缩短参数向量的长度,而 L1 会"杀死"(置零)那些靠近参数空间坐标轴的成分。直观结果是 L1 产生稀疏权重,天然适合做特征选择。
PyTorch 实现提示:PyTorch 优化器的weight_decay默认是 L2 形式;要实现 L1,通常需要像 12-regularization.ipynb 第 31 号 cell 中注释代码所示,把 L1 范数手动加到 loss 上再反向传播:
# Toggle 1: L1 norm, add to original loss # fc1_params = torch.cat([x.view(-1) for x in model.fc1.parameters()]) # loss += 0.001 * torch.norm(fc1_params, 1)在 12-regularization.ipynb 中,模型的三个正则化"开关"分别对应:Toggle 1是 L1 罚项(作用于fc1参数)、Toggle 2是优化器的weight_decay=0.005(L2)、Toggle 3是torch.dropout(out, 0.8)。每打开一个开关,训练循环与权重直方图(第 37 号 cell)都会给出可对比的分布结果。
3.3 Dropout:训练无数个"子网络"的集成
Dropout 的思想是在训练过程中随机把一定比例的神经元置零,从而阻止网络学习从输入到输出的单一固定通路。深度网络参数量巨大,有可能把输入"背"下来;而有了 Dropout,每次前向都是在一个"不同的网络"上进行的——它等价于同时训练了无数个彼此不同的子网络,让记忆输入变得极其困难。因此 Dropout 是控制过拟合、增强对输入微小扰动鲁棒性的有力手段。
PyTorch 中通过nn.Dropout(p)设置随机丢弃率:
import torch.nn as nn model = nn.Sequential( nn.Linear(64, 128), nn.ReLU(), nn.Dropout(p=0.5), # 训练时以 50% 概率随机置零神经元 nn.Linear(128, 10), )也可以用函数式接口:torch.dropout(out, 0.8)(见 12-regularization.ipynb 第 28 号 cell 的 Toggle 3 注释)。
推理阶段如何处理:训练结束后,推理时不再使用 Dropout。为了构造最终的推理网络,需要对 Dropout 期间产生的所有子网络做"平均";在实现上等价于把所有权重乘以缩放因子 $1/(1-p)$(p 为丢弃率)——这正是 PyTorch 在model.eval()时自动完成的事(训练时激活值被除以 $1-p$ 以保持期望一致)。
3.4 早期停止(Early Stopping)
训练过程中一旦验证损失开始上升,就可以停止训练,并采用此前找到的"最佳权重"。这能防止权重继续增大到损害验证性能的程度。实践中的常见做法是:每隔固定间隔计算一次验证性能,当验证误差连续若干次不再下降时即停止,并保留最佳检查点。
12-regularization.ipynb 第 31 号 cell 给出了朴素版早期停止的实现骨架——每次评估验证集时,若当前准确率超过历史最佳,就保存模型:
if accuracy > best_accuracy: best_accuracy = accuracy # 之后可以加载这个验证集上的最佳模型 torch.save(model.state_dict(), 'best_model.pth')四、间接正则化:副作用带来的正则效果
有些技术本身并不是正则化器,却带有正则化参数的"副作用",值得一并掌握。
4.1 批归一化(Batch Normalization)
问:批归一化如何让训练更高效?答:应用批归一化后,可以使用更大的学习率。
BatchNorm 的设计初衷是抑制神经网络的内部协变量偏移(internal covariate shift),尽管学界对其真实机理仍有大量争论。其本质是把"对网络输入做归一化"的逻辑扩展到每一层隐层的输入:在每层之前计算当前 batch 的均值与方差,用这批统计量归一化流入值,从而让后续每层都接收到分布更稳定的输入。
正则化副作用:由于每个 batch 都不同,同一个样本在不同 batch 中会被略微不同的统计量归一化,网络因而看到同一输入的多种"轻微变体",这促使网络对输入的细微扰动更鲁棒、从而帮助抑制过拟合。附带的好处是训练明显更快。
PyTorch 用法(13-bayesian_nn.ipynb 第 4 号 cell 展示了同类模型结构,此处以 1D 特征为例):
nn.Sequential( nn.Linear(20, 20), nn.BatchNorm1d(20), nn.ReLU(), )4.2 更多数据与数据扩充
- 收集更多数据是防止过拟合最直接的办法,但往往代价高昂甚至不可行;
- 数据扩充(Data Augmentation):使用 Torchvision 的变换(翻转、旋转、裁剪、颜色扰动等)教网络"对扰动不敏感",同样具有正则化效果。
4.3 迁移学习(Transfer Learning)与微调(Fine-Tuning)
- 迁移学习(TF):仅在预训练网络之上训练最终分类器,通常用于数据量较少的情形;
- 微调(FT):同时训练预训练网络的部分或全部层,通常用于数据量较大的情形。
问:一般什么时候冻结预训练模型的层?答:当训练数据很少时。
针对"数据量 × 分布相似度"组合的四种一般情形:
- 数据少 + 分布相似:直接做迁移学习(只训分类头);
- 数据多 + 分布相似:做微调,让特征提取器也进一步优化;
- 数据少 + 分布不同:应移除特征提取器末尾若干层——这些层过度特化于源任务;
- 数据多 + 分布不同:可以训练全部部分。
另外,可以对不同层使用不同的学习率来进一步提升性能(例如特征提取器用小学习率、新分类头用大学习率)。
五、实验结果解读:Dropout 与 L1/L2 的真实效果
为了把过拟合与正则化的讨论落到实处,课程用 12-regularization.ipynb 在 IMDB 情感二分类上生成了三组可视化(原图位于 docs/images/week14/14-3)。
无 Dropout 的损失曲线(图 7):训练损失远低于验证损失,二者持续分离——这是教科书式的过拟合信号。
有 Dropout 的损失曲线(图 8):训练损失与验证损失几乎连续重叠,说明模型在验证集(作为样本外数据的代理)上泛化良好。当然,真正的样本外性能还需要独立的留出测试集来测量。
正则化对权重分布的影响(图 9):
- L1 正则化:红色直方图在零点出现尖峰,说明大多数权重被"压"成精确的零;零附近的小红点才是模型的非零权重——典型稀疏解;
- L2 正则化:紫色/蓝色峰值紧贴零,大多数权重"接近零但非零"——收缩而非稀疏;
- 无正则化:权重更自由,围绕零呈类似正态分布的散布。
这与 3.1、3.2 中的数学推导完全一致:L2 均匀收缩向量长度,L1 沿坐标轴"杀"权重。
早期停止示意图:验证损失先下降后回升,训练应在拐点(验证损失开始恶化)附近停止,并使用此前的最佳权重。
六、延伸:用 Dropout 估计预测不确定性(贝叶斯神经网络)
我们关心神经网络的不确定性,是因为网络需要"知道自己有多确信"。例如构建一个预测方向盘转向控制的网络时,必须知道预测的置信度。
6.1 从单点预测到置信区间
利用带 Dropout 的网络(丢弃率为 r),通常做法是:推理时切换到验证模式、用全部神经元得到单一预测,并对权重乘以 $1/(1-r)$ 以补偿训练期丢弃。但这只能给出一个预测值。
要得到置信区间,需要对同一输入做多次预测:推理时保持训练模式(继续随机丢弃神经元),多次前向后,由于每次丢弃的神经元不同,同一输入会得到不同的预测;用这批预测估计均值与置信区间。这正是MC Dropout(蒙特卡洛 Dropout)的核心思想。
13-bayesian_nn.ipynb 完整实现了该流程:训练一个带nn.Dropout(p=0.05)与nn.Linear的小网络(y = x·sin(x)回归任务),然后对密集输入xx做 100 次前向,计算均值与标准差并绘制置信带:
net.train() # 推理时保持训练模式,保留 Dropout y_hat = list() with torch.no_grad(): for t in range(100): y_hat.append(net(xx.view(-1, 1)).squeeze()) y_hat = torch.stack(y_hat) mean = y_hat.mean(0) std = y_hat.std(0) # 绘图:mean ± std 即置信区间红色线代表预测均值,紫色阴影区表示不确定性(预测方差)。从图 10、图 11 可观察到:
- 这些不确定性估计并未校准,且随激活函数(ReLU / Tanh)不同而变化;
- 数据点附近的不确定性较低(有监督信号约束);
- 所观察到的方差是可微函数,因此可以对它做梯度下降最小化,从而获得更自信的预测。
七、正则化超参数与 EBM 损失项的实用问答
7.1 多个损失项如何相互作用(EBM 模型)
在基于能量的模型(EBM)中,总损失可以由不同项直接求和估计。一个常见损失项是惩罚潜在变量长度的项:向量长度大致与其维度数成正比,减小维度会让向量变短、编码信息变少。在自编码器设置中,这能确保模型保留最重要的信息——因此,对潜在空间做信息瓶颈的一种方式就是降低潜在空间的维度。
7.2 如何确定正则化超参数(正则化强度)
实践中确定最优正则化强度,通常采用:
- 贝叶斯超参数优化(Bayesian hyper-parameter optimization);
- 网格搜索(Grid Search);
- 随机搜索(Random Search)。
一个省时的经验:这类搜索中,前几个 epoch 通常就足以判断正则化是否在起作用,因此不必把模型完整训练到收敛——先用短训练快速筛选超参数,再对少数候选做完整训练即可。
八、总结与动手建议
| 方法 | PyTorch 入口 | 效果 | 备注 |
|---|---|---|---|
| 权重衰减 (L2) | 优化器参数weight_decay,如Adam(lr=1e-3, weight_decay=0.005) | 权重均匀收缩、接近零但不为零 | 即岭回归 / 高斯先验 |
| L1 正则化 | 手动把torch.norm(params, 1)加入 loss | 权重稀疏、精确置零 | LASSO / 拉普拉斯先验;优化器无内置 L1 |
| Dropout | nn.Dropout(p)或torch.dropout(x, p) | 打破固定通路、集成无数子网络 | eval()时自动补偿缩放 |
| 早期停止 | 训练循环中监测验证损失 + 保存最佳检查点 | 防止权重过度增长 | 见 12-regularization.ipynb cell 31 |
| BatchNorm | nn.BatchNorm1d/2d | 稳定层输入、允许大学习率、有正则副作用 | 见 13-bayesian_nn.ipynb cell 4 |
| 数据扩充 | Torchvisiontransforms | 教网络对扰动不敏感 | — |
| 迁移学习 / 微调 | 冻结层 + 不同层学习率 | 数据少用 TF、数据多用 FT | 四种数据×分布情形见 4.3 |
| MC Dropout 不确定性 | net.train()+ 多次前向 | 估计预测均值与置信区间 | 见 13-bayesian_nn.ipynb cell 9-11 |
建议的动手路径:打开 12-regularization.ipynb,依次切换三个 Toggle(L1、weight_decay、dropout),观察训练/验证损失曲线与第 37 号 cell 的权重直方图;再运行 13-bayesian_nn.ipynb,对比net.eval()与net.train()两种推理模式下预测曲线的差异。当你把"训练误差—验证误差的差距"作为第一性指标来审视每一种技术时,过拟合就不再是玄学,而是一套可以被量化、被调控的工程问题。
- 示例工程
【免费下载链接】NYU-DLSP20
NYU Deep Learning Spring 2020
相关推荐
NYU-DLSP20 课程笔记:深度学习的过拟合与正则化实战(Weight Decay、Dropout、早停与贝叶斯不确定性)
NYU DLSP20 课程笔记:深度学习的过拟合与正则化实战(Weight Decay、Dropout、早停与贝叶斯不确定性) 导读 本文基于 NYU DLSP
示例工程NYU-DLSP20 课程笔记:PPUU——基于不确定性正则化的密集交通驾驶策略学习
NYU DLSP20 课程笔记:PPUU——基于不确定性正则化的密集交通驾驶策略学习 导读 本文整理自 NYU Deep Learning Spring 202
示例工程PyTorch 深度学习中过拟合的对抗之道:NYU-DLSP20 第 14.3 讲正则化技术全景解析
PyTorch 深度学习中过拟合的对抗之道:NYU DLSP20 第 14.3 讲正则化技术全景解析 导读 本文是 NYU Deep Learning Spri
示例工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考