7. 从零训练 TinyGPT
学习目标
- 读懂最小 GPT 的完整前向路径
- 完成训练、保存、加载和生成
- 设计容量、上下文与采样对照
前置知识
- 完成 Tokenizer、语言模型和 Transformer 章节
本章产物可重载 checkpoint、训练日志、生成样例和对照实验报告。
资料包中的 code/04_tiny_gpt.py 包含:
- 字符 tokenizer。
- token embedding 与位置 embedding。
- 多头因果注意力。
- Transformer Block。
- LayerNorm、MLP 与残差。
- 权重共享。
- 交叉熵训练。
- AdamW、梯度裁剪。
- 自回归 top-k 采样。
- checkpoint 保存和加载。
7.1 第一次训练
python code/04_tiny_gpt.py train \
--data data/tiny_corpus.txt \
--steps 2000需要逐步观察模型结构和损失曲线时,可使用训练一个最小 GPT Notebook。
生成:
python code/04_tiny_gpt.py generate \
--prompt "注意力" \
--max-new-tokens 200该语料很小,模型主要会学习字符组合和局部句式,不会获得真正的知识能力。它的价值是让完整链路在几分钟内可观察。
7.2 读代码的正确顺序
build_char_vocab:文字如何变成整数。batch:输入和标签如何错一位。TinyGPT.forward:形状如何从[B,T]变成[B,T,V]。CausalSelfAttention:如何拆 head、做 attention、再拼回。loss.backward():梯度如何产生。optimizer.step():参数如何更新。generate:训练时并行预测与推理时逐 token 生成有何不同。
7.3 逐步实验
| 实验 | 修改 | 观察 |
|---|---|---|
| 模型宽度 | --width 64/128/256 | 参数量、速度、loss |
| 层数 | --layers 2/4/8 | 深度与训练稳定性 |
| 上下文 | --block-size 32/128/256 | 可学习依赖与计算量 |
| 去掉残差 | 临时修改 Block | 深层训练是否更难 |
| 去掉缩放 | 手写 attention 实验 | softmax 是否更尖锐 |
| 不使用 causal mask | 仅做错误实验 | loss 是否异常下降 |
| 生成温度 | 0.2/0.8/1.5 | 重复性与随机性 |
7.4 参数共享
代码中:
self.lm_head.weight = self.token_embedding.weight输入 embedding 把 token ID 映射为向量,输出头把隐藏向量投影回 token 空间。权重共享能减少约 V × C 参数,也建立输入与输出表示之间的联系。
7.5 这份 TinyGPT 没有实现什么
为了可读性,它没有:
- RoPE、RMSNorm、SwiGLU、GQA。
- KV Cache。
- 混合精度和分布式训练。
- 高效数据流、文档级去重和生产 checkpoint。
- 学习率 warmup/cosine schedule。
- Flash Attention 的专门控制与性能剖析。
这不是缺陷隐藏,而是学习顺序:先理解最小闭环,再逐项加入现代组件。
7.6 动手:完成第一个可复查的训练闭环
实验 04|TinyGPT 资源:CPU/MPS/CUDA;时间:快速验收约 1~5 分钟,正式小实验约 5~30 分钟;产物:checkpoint、训练日志、两组生成和实验报告。
第一步只做冒烟测试,目的是尽快发现路径、设备和形状错误:
python code/04_tiny_gpt.py train \
--data data/tiny_corpus.txt \
--checkpoint artifacts/checkpoints/tiny-gpt-smoke.pt \
--steps 20 \
--batch-size 4 \
--block-size 32 \
--layers 2 \
--heads 2 \
--width 64 \
--log-every 5成功信号:
- 首行打印
device、vocab和参数量。 - 每个日志点的 loss、perplexity 和 elapsed 都是有限数。
artifacts/checkpoints/tiny-gpt-smoke.pt能被生成命令重新加载。
python code/04_tiny_gpt.py generate \
--checkpoint artifacts/checkpoints/tiny-gpt-smoke.pt \
--prompt "注意力" \
--max-new-tokens 40冒烟测试不要求文本有意义。之后再做正式基线:
python code/04_tiny_gpt.py train \
--data data/tiny_corpus.txt \
--checkpoint artifacts/checkpoints/tiny-gpt-base.pt \
--steps 2000 \
--batch-size 32 \
--block-size 128 \
--layers 4 \
--heads 4 \
--width 128 \
--log-every 100 \
--seed 42至少保留两类对照:
| 对照 | 固定项 | 改变项 | 观察指标 |
|---|---|---|---|
| 容量对照 | 数据、step、seed、batch | width 64 → 128 | 参数量、loss、耗时 |
| 上下文对照 | 数据、参数量近似、step | block size 32 → 128 | loss、显存/内存、耗时 |
| 采样对照 | 同一 checkpoint 与 prompt | temperature 0.2 → 1.2 | 重复性、多样性、错误率 |
故障定位:
| 现象 | 最可能的层级 | 检查 |
|---|---|---|
输入超过 block_size | 数据/生成输入 | prompt 长度与 checkpoint 配置 |
| loss 立即 NaN | 优化与数值 | 学习率、输入范围、梯度范数 |
| loss 完全不变 | 训练循环 | backward、step、梯度是否为零 |
| 生成全是重复字符 | 数据/训练/采样 | 语料多样性、训练程度、temperature |
| checkpoint 无法加载 | 实验管理 | 配置、词表、权重是否来自同一次训练 |
验收不是生成出流畅中文,而是:训练目标正确、loss 有下降趋势、checkpoint 可重载、相同 seed 的实验可复现,并且你能解释小语料模型为什么只会模仿局部形式。
本章依据
原理性结论以原始论文、官方文档或公开教材为依据。论文中的实验结果只适用于其声明的模型、数据、硬件和评估设置。
GPT 的 decoder-only 预训练与下游适配框架。
GPT-2 的自回归训练、模型规模和零样本任务行为。
TinyGPT 中注意力、残差、归一化和前馈层的架构依据。