实验管理与可复现性
实验管理把「跑一次训练」升级为「可复现、可对比、可回溯的科学流程」:固定全部随机性来源、配置与代码同版本管理、指标与曲线自动记录、最优检查点与其出生配置绑定保存。
一句话定义
实验管理把「跑一次训练」升级为「可复现、可对比、可回溯的科学流程」:固定全部随机性来源、配置与代码同版本管理、指标与曲线自动记录、最优检查点与其出生配置绑定保存。
直觉
没有实验管理的调参像「没有实验记录本的化学家」:做出好结果却说不清是哪一步的功劳,一周后自己都复现不了;有管理的实验像带编号的试剂瓶——任何一瓶结果都能追溯到完整的配方与流程。
为什么重要
深度学习结果的噪声水平(种子间差异常达 ±0.3~1%)与超参敏感度,使「不可复现的好结果」一文不值:没法对比、没法改进、没法交付。kp-027 的单变量原则必须落在本节的记录体系上才可执行;kp-021 的项目里程碑检查也依赖「同一基线可重跑」。
前置知识
- kp-016(训练循环——被管理的对象)、kp-027(单变量实验纪律)。
核心概念
- 随机性来源清单:权重初始化、数据增强、DataLoader shuffle、CUDA 算子、(序列任务)采样。
- 种子(seed):torch/numpy/random/DataLoader 四处都要固定,缺一处就漂。
- 配置即文档(config):超参数据集中在单一字典/yaml,训练产物与其绑定。
- 日志(logging):每 epoch 记录 train/val 损失与指标、学习率、梯度范数,落盘为结构化文件。
- 检查点(checkpoint):model.state_dict + 优化器状态 + epoch + 配置的打包保存。
- 确定性 vs 速度:torch.use_deterministic_algorithms(True) 会显著拖慢训练,实践上常折中(记录种子而非强制逐位一致)。
原理与机制
可复现性的机制在于「消灭隐式状态」:训练过程的状态 = 代码 × 配置 × 数据 × 随机流,前三者用版本管理(git/数据快照)与配置文件钉死,随机流用种子钉死。四处种子的原理:Python 内置 random 与 numpy 各有独立生成器管增强与打乱;PyTorch 的 CPU 与 CUDA 生成器相互独立;DataLoader 的 worker 进程还会再分叉生成器——所以完整固定需要 seed一切 + worker_init_fn + generator 三件套。哪怕全部钉死,GPU 浮点运算的归约顺序仍可能非确定(原子加法),这就是「确定性模式」存在的理由与代价——工程折中是「统计可复现」:固定种子 + 2~3 个种子重复,报告均值±标准差,比单次逐位复现更科学也更便宜。实验记录的最小完备集:一次实验 = {git commit、config 快照、数据版本、随机种子、每 epoch 指标、最终 checkpoint、一句话结论};对比实验的唯一纪律继承 kp-027 的单变量原则。工具谱系:轻量方案用「CSV/JSONL + matplotlib」即可满足本库项目;重型方案(wandb/mlflow/tensorboard)提供面板与对比视图,本库不绑定任何一种(保持零依赖),但记录字段的设计完全通用。
公式或模型
本节不适用——理由:本节为工程流程规范,不含新数学;种子固定的代码清单即其「公式」。
图示
一次实验的完备档案(最小完备集):
exp-021-baseline/
├─ config.json ← 学习率/批大小/增强/种子/epoch……(快照,勿改)
├─ git-hash.txt ← 代码版本
├─ metrics.jsonl ← {epoch, train_loss, val_loss, val_acc, lr, grad_norm}×N
├─ best.pt ← 最优检查点(含 model/optimizer 状态与 epoch)
└─ notes.md ← 一句话结论 + 与上一实验的唯一差异直观类比
配置快照与 git-hash 像「菜谱拍照 + 拍下厨房照片」:三个月后任何人(包括三个月后的你)都能按图复原同一道菜。
实例或案例
kp-016 训练循环的实验化改造(新增部分):
import random, numpy as np, torch, json, time
def set_seed(s=42):
random.seed(s); np.random.seed(s); torch.manual_seed(s)
torch.cuda.manual_seed_all(s) # ① 四处种子
torch.backends.cudnn.deterministic = True # ② 折中的确定性
torch.backends.cudnn.benchmark = False
cfg = dict(lr=1e-3, batch=128, epochs=5, seed=42, dropout=0.2)
set_seed(cfg['seed'])
run_dir = f"runs/{time.strftime('%m%d-%H%M')}-lr{cfg['lr']}"
# 每 epoch: 向 metrics.jsonl 追加一行 json;结束: 保存 config.json + best.pt对照实验模板:baseline 与 +dropout 两个 run 目录并排,metrics.jsonl 双曲线一画即知结论——kp-021 的「增强开关对照」就是这样执行的。种子间差异实验:同一 config 跑 seed 42/43/44,观察 val_acc 的 ±0.3% 漂移,亲身体会「单次结果不可尽信」。
常见误区
- 只固定 torch.manual_seed:增强与 shuffle 仍在漂,两次运行曲线不同还以为是 GPU 玄学。
- 「结果好就当场跑」:不落盘的日志在进程结束后蒸发,过拟合掉的 0.5% 永远说不清来源。
- checkpoint 只存模型权重:恢复训练或分析优化器动量状态时缺件,应整包保存。
- 用测试集「顺便看看」当记录习惯:每次查看都在消耗测试集的法律效力(kp-015 的闸门纪律)。
与其他知识点的关系
本节为 kp-027 的单变量实验提供载体、为 kp-021 的里程碑检查提供工具;种子固定是 kp-012/015 中随机性的总开关;「配置与数据版本化」在大规模训练中的升级形态(数据版本控制、分布式检查点)属于 kp-029 的延伸话题。
自测题
- 列出深度学习训练中至少四个需要固定种子的随机性来源。
答案要点:权重初始化、数据增强、DataLoader shuffle(含 worker)、CUDA 算子随机性。
- 「统计可复现」为什么优于「逐位确定性」?
答案要点:GPU 确定性模式显著拖慢训练;而科学结论本应以多种子均值±方差报告,统计口径更实用。
- 一个最小完备的实验档案应包含哪些文件?
答案要点:config 快照、git-hash、逐 epoch 指标流、最优检查点(含优化器状态)、结论笔记。
延伸阅读
- Pineau 等《Improving Reproducibility in Machine Learning Research»(JMLR 2021,可复现性检查表运动)。
- Karpathy《A Recipe for Training Neural Networks» 中「 obsess over reproducibility 」一节(与 kp-027 共读)。
学习状态
状态保存在浏览器本地,用于首页与路径页的进度统计。