03-训练核心 核心 预计 20 分钟

数据集划分、数据增强与 DataLoader

数据管道是把原始数据变成「模型可消费的小批次张量流」的完整流程:按训练/验证/测试三分数据、用增强扩充多样性、用 DataLoader 实现打乱与并行装载——它是 kp-016 训练循环的上游供给线。

一句话定义

数据管道是把原始数据变成「模型可消费的小批次张量流」的完整流程:按训练/验证/测试三分数据、用增强扩充多样性、用 DataLoader 实现打乱与并行装载——它是 kp-016 训练循环的上游供给线。

直觉

数据管道像餐厅的「备菜间」:原始食材(原始数据)先分库存放(三分数据集),洗切腌制(预处理与增强),最后由传菜员(DataLoader)按菜单节奏一小盘一小盘(batch)送上灶台(训练循环),灶台永远不用等菜。

为什么重要

「垃圾进,垃圾出」:同一模型在干净管道与脏管道上的差距常超过换架构。数据泄漏(测试信息混进训练)会让所有指标虚高且不可救药地误导决策;增强则是视觉任务最廉价有效的正则(kp-013 治本型手段)。kp-021 项目能否复现出 90%+ 准确率,一半取决于本知识点。

前置知识

  • kp-013(为什么需要干净验证协议与增强式正则)、kp-002(张量)。

核心概念

  • 训练集(train):模型学习所用的数据。
  • 验证集(val):调超参、选检查点、早停判据的专用数据,绝不能参与梯度更新。
  • 测试集(test):只在项目最终评估时启用一次的数据,是泛化的「最后法庭」。
  • 数据增强(data augmentation):对训练样本施加保标签的随机变换(翻转/裁剪/色彩抖动),扩充有效数据量。
  • Dataset / DataLoader:PyTorch 抽象——Dataset 定义「单条样本怎么取」,DataLoader 定义「怎么成批、打乱、并行」。
  • 归一化(normalization):用训练集统计量把输入压到零均值单位方差(注意与 kp-014 的 BN 是两回事)。

原理与机制

三分的逻辑是一条单向信息闸门:训练集信息可以流入模型,验证集信息只能流入人的决策(选 λ、选 epoch、选结构),测试集信息谁也不许碰、只做一次终审。违反顺序即「数据泄漏」——最隐蔽的形态是用测试集调参(kp-030 误区之首),最常见形态是用全量数据先做归一化统计或增强再切分(统计/增强规则应只从训练集学来)。增强的原理是「保标签不变性」的先验注入:水平翻转不改变「猫」这个标签,于是模型被迫学会对翻转不变的猫表示——等效于免费扩充数据;但增强必须匹配任务不变性,数字 6 竖直翻转成 9 就换了标签。归一化的作用是让各输入维度量级一致,初始参数(kp-012)与优化器(kp-010)的假设才能成立。DataLoader 的机制价值在工程侧:shuffle=True 消除样本顺序偏差,num_workers 多进程预取让 GPU(kp-029)不空转,drop_last 控制尾批大小以稳定 BN(kp-014)统计。批顺序的随机性由 RNG 驱动,固定种子即可复现(kp-028 的具体落点之一)。

公式或模型

归一化的标准式与增强组合的伪代码:

x_norm = (x − μ_train) / (σ_train + ε)      # 统计量只来自训练集
增强组合: x → 随机水平翻转(p=0.5) → 随机裁剪(32×32, padding=4)
         → Cutout/色彩抖动(可选) → ToTensor → Normalize

变量说明:μ_train、σ_train 为训练集逐通道统计量;ε 防除零。增强链的顺序影响语义(裁剪应在归一化前),公式体现「几何变换 → 张量化 → 数值归一」次序。

图示

原始数据 ──切分──► train ──► [增强+归一化] ──► DataLoader(shuffle, workers) ──► 训练循环
              │                                                          ▲
              ├──► val ──► [仅归一化] ──► DataLoader ──► 调参/早停/选检查点 ─┘
              │
              └──► test ──► [仅归一化] ──► 项目结束时一次性评估(禁入训练与调参)

直观类比

测试集像「密封的期末卷」:考前谁打开看过一眼,成绩就作废;验证集是「模拟卷」,可以反复考,用来决定复习策略;增强是「把一道题改数字改编很多遍」,逼你学通法而非记答案。

实例或案例

CIFAR-10 的标准管道代码骨架(kp-021 完整展开):

import torchvision.transforms as T
from torch.utils.data import DataLoader

train_tf = T.Compose([
    T.RandomCrop(32, padding=4),   # 随机裁剪
    T.RandomHorizontalFlip(),      # 随机水平翻转
    T.ToTensor(),
    T.Normalize((0.4914,0.4822,0.4465), (0.2470,0.2435,0.2616)),  # 训练集统计量
])
test_tf = T.Compose([T.ToTensor(),
    T.Normalize((0.4914,0.4822,0.4465), (0.2470,0.2435,0.2616))])

train_loader = DataLoader(train_set, batch_size=128, shuffle=True, num_workers=2)
val_loader   = DataLoader(val_set,   batch_size=256, shuffle=False)

注意三点纪律:验证/测试变换不含随机增强;Normalize 参数用训练集统计;val 的 shuffle 必须关(保证指标可复现)。

常见误区

  • 先归一化/增强全量数据再切分:测试统计量泄漏进训练,指标虚高。
  • 验证集参与训练(哪怕一个 epoch 的学习率搜索用了梯度):验证指标失真。
  • 增强破坏标签:交通标志加高斯噪声、数字垂直翻转等「负增强」会教坏模型。
  • 测试集反复使用:每「看一次改一次模型」,测试集事实上退化成验证集,泛化估计失效。

与其他知识点的关系

本知识点是 kp-013 正则化的数据侧实现、kp-016 训练循环的直接上游、kp-021 项目的管道落点;统计量复现与种子管理衔接 kp-028;GPU 供给效率问题指向 kp-029。

自测题

  1. 训练/验证/测试三者的信息流向规则是什么?

答案要点:训练集→梯度;验证集→人的决策;测试集→一次性终审;任何逆向流动都是泄漏。

  1. 为什么水平翻转对 CIFAR-10 是好增强,对 MNIST 手写数字要谨慎?

答案要点:翻转保标签的前提是任务具备左右不变性;数字翻转可能改变类别(b/d、6/9)。

  1. Normalize 的统计量应从哪些数据计算?

答案要点:只从训练集计算,验证/测试复用同一套统计量。

延伸阅读

  • 李沐等《动手学深度学习》13.1 节「图像增广」。
  • Shorten、Khoshgoftaar «A survey on Image Data Augmentation for Deep Learning» 2019(增强方法综述)。

学习状态

状态保存在浏览器本地,用于首页与路径页的进度统计。