Skip to content

实验手册:从第一条命令到可信报告 ​

这一章把前面各章的知识变成可以完成和验收的实验。工作目录统一为仓库根目录,源码位于 labs/llm/。先跑已有实现,再通过小改动验证预测;不要一开始同时换模型、tokenizer、数据与学习率,否则即使结果改变也很难解释原因。

实验 0:环境与正确性 ​

代码需要 Python 3.10 或更新版本及 NumPy。可以使用已有环境,也可新建隔离环境:

sh
python3 -m venv labs/llm/.venv
labs/llm/.venv/bin/python -m pip install -r labs/llm/requirements.txt
labs/llm/.venv/bin/python -m unittest discover -s labs/llm -p 'test_*.py' -v

后续命令中的 python3 可替换为这个 venv 的 Python。当前工作区已安装 NumPy,验证时没有安装 PyTorch 或申请 GPU。测试涵盖 UTF-8 往返、非重叠 BPE 合并、文档边界、因果性、训练移位、稳定交叉熵、全部参数种类的有限差分、固定 batch 过拟合、checkpoint 重载、在线注意力等价、数据/拟合和对齐目标。

预期是 15 个测试全部通过,而不是某个固定测试耗时。先故意去掉 causal mask,确认因果性测试失败;还原后再改错目标移位,确认对应测试失败。这种“让测试抓到已知错误”的练习,能防止把一串绿色输出误当作充分证明。修改实验用单独副本或及时还原,避免将故障演示混入基线。

实验 1:训练、保存、再生成 ​

sh
python3 labs/llm/train.py --steps 300 --seed 7 --out labs/llm/runs/char-seed7
python3 labs/llm/generate.py --checkpoint labs/llm/runs/char-seed7/model.npz --prompt "the fox " --tokens 120
python3 labs/llm/generate.py --checkpoint labs/llm/runs/char-seed7/model.npz --prompt "the owl " --tokens 40 --temperature 0

模型默认一层、宽度 32、4 个头、FFN 宽度 64、上下文 24;词表由训练部分构建。40 行原创语料前 32 行训练、后 8 行验证,固定评测窗口分别从两者抽样。默认字符词表共 27 项,总参数量 12064;prompt 必须使用词表已有字符。日志每 50 步输出固定窗口 NLL,并保存配置与 tokenizer。

本次在 Python 3.14.8、NumPy 2.5.3、CPU float64 上实测:

tokenizer参数量训练 token 数验证 token 数初始训练 NLL → 300 步初始验证 NLL → 300 步
字符1206413813343.8988 → 0.73353.8612 → 1.2659
字节 BPE,32 次合并287688652116.1311 → 0.61716.2240 → 1.7335

字符与 BPE 模型的独立学习曲线,蓝色为训练、橙色为验证

这是 2026-10-04 的本地结果,完整机器可读记录位于 labs/llm/reports/。两个 tokenizer 的 NLL 单位不同,不能据此宣布字符优于 BPE。它们的词表、输出层参数量、每步覆盖的字节数也不同;表格的目的在于验证两套流水线能运行,而非公平模型排名。

字符模型一次真实采样开头是 the fox stone ane.,之后出现 the book beside 等片段,也有拼写错误和重复。这是合理的教学观察:小模型已学习局部词形与句式,但远非语言理解成功。未经筛选的样本保存在报告中,没有用较好的手写文本替代生成结果。

实验 2:把 BPE 接入相同训练器 ​

sh
python3 labs/llm/train.py --tokenizer bpe --merges 32 --steps 300 --seed 7 --out labs/llm/runs/bpe-seed7
python3 labs/llm/generate.py --checkpoint labs/llm/runs/bpe-seed7/model.npz --prompt "the rabbit " --tokens 80

检查生成 checkpoint 保存的 tokenizer kind、merge 表与模型 vocab size 是否一致。然后只改 --merges 16,记录压缩率与参数量。若要公平比較语言建模效果,应对相同验证文档计算总 NLL/原始字节数;当前固定数量 token 窗口的指标不足以完成这个比较。

实验 3:系统、数据与对齐的数值基础 ​

sh
python3 labs/llm/algorithms.py

实测在线注意力与稠密参考的最大绝对误差约为 3.33×10−16;合成幂律恢复 a≈3,α≈0.4;中性 DPO loss 为 log⁡2。这些结果验证公式,不是 GPU benchmark、真实 scaling law,也不是对齐训练成绩。修改块大小为 1、3、8、32 后仍应保持数值一致,不能由 NumPy 循环耗时推断 GPU 内核快慢。

扩展数据实验时,制造空白变体与近似重复,检查 hash 和 shingle 的边界。扩展对齐实验时,先构造一批 response mask,验证 mask 外梯度为零;再构造正负优势,手算 clipping 后的值。把每个模块变成独立可检查函数,再连接大模型训练,是降低排错成本的有效方法。

从教学实现进入官方作业 ​

官方部分本地已经可执行进一步需要完成
A1BPE 原理、Transformer 前反向、AdamW、训练生成官方 regex/tie-break/special token、PyTorch 接口、官方规模数据与训练实验
A2在线 softmax 与稠密注意力对照Triton 前反向内核、GPU profiling、DDP、optimizer sharding
A3已知 floor 的幂律拟合数值例历史 API 可用性核查或自建训练扫描、IsoFLOPs 与外推验证
A4规范化、精确去重、shingle/JaccardHTML 提取、分类过滤、行级去重、MinHash/LSH、受控训练
A5response SFT loss、优势、clip 目标、DPO 数值Qwen 基线评测、SFT、Expert Iteration、GRPO;选做偏好对齐

实验报告模板 ​

每份报告写清六件事:问题与预测;唯一改变的变量;固定配置与数据版本;正确性检查;结果表与未筛选样本;结论及可解释范围。失败也值得保留,例如“移除 RMSNorm 后梯度范数增大但 300 步仍收敛”,比预先认定一定崩溃更诚实。

训练集 loss 已很低,下一步最有信息量的实验是什么?

先看训练与验证差距及具体错误。若差距很大,可增加独立数据或减少训练步数;若两者都高,检查容量、优化和数据格式。若 NLL 不差但生成重复,固定模型比较采样策略与上下文长度。每次只改变一个有明确假设的因素。

来源范围与提交锁定见 课程首页。下一章:综合复盘。