阶段:S2-数据处理 | 预计耗时:60 分钟 | 前置:S2-01 Dataset 与 DataLoader 代码:本篇代码要你自己敲成
model-learn/s2_data_split.py
学习目标
- 说清 train / val / test 三份数据各自的用途,以及为什么 test 只准用一次
- 亲手做一次数据泄漏实验,亲眼看到"用测试集调参"怎么把指标做虚高
- 掌握本机可行的划分写法(
torch.utils.data.random_split)
核心知识
1. 三份数据的角色(考试类比)
| 数据 | 角色 | 用途 | 用几次 |
|---|---|---|---|
| 训练集 train | 平时练习题 | 训练参数 | 反复用 |
| 验证集 val | 模拟考 | 调参、选模型、早停 | 反复用 |
| 测试集 test | 正式高考 | 最终汇报成绩 | 只准一次 |
经典比例 6:2:2 或 8:1:1;数据少时验证集太小不可靠 → 用交叉验证(S6-02)。
2. 数据泄漏:成绩虚高的三大经典姿势
- 拿 test 调参——相当于考前偷看考卷(本篇实验就做这个)
- 归一化统计量用了全体数据——均值/方差只能从 train 算
- 时间序列随机打乱后划分——拿未来预测过去
泄漏的可怕之处:指标很高,上线就崩,而且你查不出 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 数据增强:数据不够时怎么"无中生有"。