news 2026/10/19 7:17:01

深度学习中的过拟合与正则化实战指南:基于 PyTorch 的 NYU DLSP20 课程笔记

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深度学习中的过拟合与正则化实战指南:基于 PyTorch 的 NYU DLSP20 课程笔记
  • 示例工程

【免费下载链接】NYU-DLSP20

NYU Deep Learning Spring 2020

项目地址:https://gitcode.com/gh_mirrors/pyt/pytorch-Deep-Learning
点击查看免费下载

本篇文章围绕 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):同时训练预训练网络的部分或全部层,通常用于数据量较大的情形。

问:一般什么时候冻结预训练模型的层?答:当训练数据很少时。

针对"数据量 × 分布相似度"组合的四种一般情形:

  1. 数据少 + 分布相似:直接做迁移学习(只训分类头);
  2. 数据多 + 分布相似:做微调,让特征提取器也进一步优化;
  3. 数据少 + 分布不同:应移除特征提取器末尾若干层——这些层过度特化于源任务;
  4. 数据多 + 分布不同:可以训练全部部分。

另外,可以对不同层使用不同的学习率来进一步提升性能(例如特征提取器用小学习率、新分类头用大学习率)。

五、实验结果解读: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
Dropoutnn.Dropout(p)或torch.dropout(x, p)打破固定通路、集成无数子网络eval()时自动补偿缩放
早期停止训练循环中监测验证损失 + 保存最佳检查点防止权重过度增长见 12-regularization.ipynb cell 31
BatchNormnn.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

项目地址:https://gitcode.com/gh_mirrors/pyt/pytorch-Deep-Learning
点击查看免费下载

相关推荐

上一篇:easy-vibe 生鲜电商微服务系统实战:从 PRD 需求拆分到网关联调上线的完整开发指南
下一篇:Sa-Token 轻量级 Java 权限认证框架实战指南:从一行代码登录到注解与路由拦截鉴权

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 12:45:26

tailwind-patterns - SKILL

name: tailwind-patterns description: “Tailwind CSS v4 principles. CSS-first configuration, container queries, modern patterns, design token architecture.” risk: none source: community date_added: “2026-02-27” Tailwind CSS 模式(v4 - 2025&…

作者头像 李华
网站建设 2026/10/17 11:29:34

teach - GLOSSARY-FORMAT

GLOSSARY.md 格式 GLOSSARY.md 是此教学工作区的规范语言。所有讲解、练习和学习记录都应遵循其术语。构建它本身就是学习的一部分:把一个概念压缩成精确定义,正是用户理解它的证据。 结构 # {主题} 术语表{一两句话描述此术语表涵盖的主题。}## 术语**肥…

作者头像 李华
网站建设 2026/10/16 8:17:22

swiftui-expert-skill - localization

SwiftUI 本地化参考 面向用户的文本指导:Text、Button、Label、导航/工具栏标题、alert 以及携带可本地化字符串的类型。关于单个 Text 上更窄的"verbatim 与本地化"决策,请参阅 references/text-patterns.md。 目录 SwiftUI 自动本地化字符…

作者头像 李华
网站建设 2026/10/15 20:42:17

自动化与脚本实战:语言选型到测试运维全指南

自动化与脚本,这两个词放在一起,多少有点江湖气。外行听起来像是黑客电影里的暗号,内行知道这就是把重复劳动交给机器的基本盘。我干了这么多年自动化相关的工作,从最早的按键精灵到现在的 pytest、Ansible、Playwright&#xff0…

作者头像 李华