首页 › S 模型训练 › S2 数据处理 › 02

S2-02 · 训练验证测试集划分:别拿考试题来练习

进阶阶段约 180 分钟阶段:S2 数据处理

阶段:S2-数据处理 | 预计耗时:60 分钟 | 前置:S2-01 Dataset 与 DataLoader 代码:本篇代码要你自己敲成 model-learn/s2_data_split.py

学习目标

  1. 说清 train / val / test 三份数据各自的用途,以及为什么 test 只准用一次
  2. 亲手做一次数据泄漏实验,亲眼看到"用测试集调参"怎么把指标做虚高
  3. 掌握本机可行的划分写法(torch.utils.data.random_split)

核心知识

1. 三份数据的角色(考试类比)

数据 角色 用途 用几次
训练集 train 平时练习题 训练参数 反复用
验证集 val 模拟考 调参、选模型、早停 反复用
测试集 test 正式高考 最终汇报成绩 只准一次

经典比例 6:2:2 或 8:1:1;数据少时验证集太小不可靠 → 用交叉验证(S6-02)。

2. 数据泄漏:成绩虚高的三大经典姿势

  1. 拿 test 调参——相当于考前偷看考卷(本篇实验就做这个)
  2. 归一化统计量用了全体数据——均值/方差只能从 train 算
  3. 时间序列随机打乱后划分——拿未来预测过去

泄漏的可怕之处:指标很高,上线就崩,而且你查不出 bug——因为没有 bug,只有错误的方法论。

3. 本机注意

random_split(n, [a, b, c], generator=torch.Generator().manual_seed(42))——带 generator 才可复现(呼应 S1 的种子实验)。

实验任务

任务 1:敲出脚本(25 分钟)

只训 500 条(小数据方差距明显),训 5 个 epoch,每个 epoch 后同时在 val 和 test 上各评一次:

# s2_data_split.py —— 泄漏实验:用 test 调参会发生什么
import torch, torch.nn as nn
from torchvision import datasets, transforms
from torch.utils.data import DataLoader, random_split

torch.manual_seed(42)
full = datasets.MNIST("data", train=True, download=False,
                      transform=transforms.ToTensor())
train_ds, val_ds, test_ds = random_split(full, [500, 5000, 5000],
    generator=torch.Generator().manual_seed(42))
train_dl = DataLoader(train_ds, batch_size=64, shuffle=True)

model = nn.Sequential(nn.Flatten(), nn.Linear(784, 128), nn.ReLU(), nn.Linear(128, 10))
opt = torch.optim.Adam(model.parameters(), lr=1e-3)
loss_fn = nn.CrossEntropyLoss()

@torch.no_grad()
def acc(ds):
    dl = DataLoader(ds, batch_size=256)
    n = ok = 0
    for x, y in dl:
        ok += (model(x).argmax(1) == y).sum().item(); n += len(y)
    return ok / n

for epoch in range(5):
    for x, y in train_dl:
        opt.zero_grad(); loss = loss_fn(model(x), y); loss.backward(); opt.step()
    print(f"epoch {epoch+1}: val={acc(val_ds):.4f}  test={acc(test_ds):.4f}")

任务 2:两种"汇报方式"对比(15 分钟)

  • 作弊版:挑 5 行里 test 最高的那个数,作为最终成绩(= 用 test 调参)
  • 规矩版:挑 val 最高的那个 epoch,报它对应的 test 成绩 两个数都写进观察记录表。差距可能不大(这是纪律问题不是数字问题),但你要能说清:数据多 100 倍、调参次数多 100 倍时,作弊版会虚高多少。

任务 3:找泄漏(10 分钟)

读回你机器上的 01_mnist_cnn.py:它把全量 60000 样本都拿来训练、只在官方 test 集上评——它有没有泄漏?为什么?(提示:它有没有"用测试结果改过任何超参数"?)

验收标准

衔接下一阶段

数据划分就位 → S2-03 数据增强:数据不够时怎么"无中生有"。

小测验(2 题)

答完立即判分,错题给解析;得分存本地。实验与实操题不上网测:回对话找老师验收。