外观
实验手册:从第一条命令到可信报告
这一章把前面各章的知识变成可以完成和验收的实验。工作目录统一为仓库根目录,源码位于 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 步 |
|---|---|---|---|---|---|
| 字符 | 12064 | 1381 | 334 | 3.8988 → 0.7335 | 3.8612 → 1.2659 |
| 字节 BPE,32 次合并 | 28768 | 865 | 211 | 6.1311 → 0.6171 | 6.2240 → 1.7335 |
这是 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实测在线注意力与稠密参考的最大绝对误差约为
扩展数据实验时,制造空白变体与近似重复,检查 hash 和 shingle 的边界。扩展对齐实验时,先构造一批 response mask,验证 mask 外梯度为零;再构造正负优势,手算 clipping 后的值。把每个模块变成独立可检查函数,再连接大模型训练,是降低排错成本的有效方法。
从教学实现进入官方作业
| 官方部分 | 本地已经可执行 | 进一步需要完成 |
|---|---|---|
| A1 | BPE 原理、Transformer 前反向、AdamW、训练生成 | 官方 regex/tie-break/special token、PyTorch 接口、官方规模数据与训练实验 |
| A2 | 在线 softmax 与稠密注意力对照 | Triton 前反向内核、GPU profiling、DDP、optimizer sharding |
| A3 | 已知 floor 的幂律拟合数值例 | 历史 API 可用性核查或自建训练扫描、IsoFLOPs 与外推验证 |
| A4 | 规范化、精确去重、shingle/Jaccard | HTML 提取、分类过滤、行级去重、MinHash/LSH、受控训练 |
| A5 | response SFT loss、优势、clip 目标、DPO 数值 | Qwen 基线评测、SFT、Expert Iteration、GRPO;选做偏好对齐 |
实验报告模板
每份报告写清六件事:问题与预测;唯一改变的变量;固定配置与数据版本;正确性检查;结果表与未筛选样本;结论及可解释范围。失败也值得保留,例如“移除 RMSNorm 后梯度范数增大但 300 步仍收敛”,比预先认定一定崩溃更诚实。
训练集 loss 已很低,下一步最有信息量的实验是什么?
先看训练与验证差距及具体错误。若差距很大,可增加独立数据或减少训练步数;若两者都高,检查容量、优化和数据格式。若 NLL 不差但生成重复,固定模型比较采样策略与上下文长度。每次只改变一个有明确假设的因素。