本节摘要:十三节课,一个模型,没有捷径。你已经读了每一篇论文,实现了注意力、多头切分、位置编码、编码器和解码器块、BERT 和 GPT 损失、MoE、KV 缓存——现在让它们在一个真实任务上协同工作。毕业项目:端到端训一个小的 decoder-only Transformer,做字符级语言建模。它读莎士比亚,生成新的莎士比亚;小到笔记本上 10 分钟内能训完,正确到换上更大数据集和更长训练就能得到一个真正的语言模型。这是本课程的「nanoGPT」——不原创,Karpathy 2023 的 nanoGPT 教程是每个学生至少写一次的参考实现,我们沿用它的形状,按本系列覆盖的内容重新打磨。本节用 PyTorch 把第 04(位置)、05(RMSNorm/SwiGLU/pre-norm)、03(多头)、07(因果掩码、shift-by-one 损失)节的积木拼成一个能跑的 GPT,在
tinyshakespeare.txt上训 2000 步,看训练损失从约 4.2(随机)降到约 1.5,采样输出是「莎士比亚形状」的——古体词、换行、ROMEO:之类的专名涌现。读完本节,你拥有一个 80 万参数的 GPT,以及把它放大到 1.25 亿参数、生成流畅英语的清晰路径。
阅读完本节,你应当能够:
tinyshakespeare.txt 上训 2000 步,把验证损失压到 2.0 以下,采样出「莎士比亚形状」的文本。你已经实现了每一个组件,现在让它们协同。毕业项目:训一个小的 decoder-only Transformer,字符级语言建模,读莎士比亚、生成莎士比亚。
GPTConfig——一处配置所有超参。MultiHeadAttention——因果、批处理,可选 Flash 风格通路(PyTorch 的 scaled_dot_product_attention)。SwiGLUFFN——现代 FFN。Block——pre-norm、残差包裹的注意力 + FFN。GPT——嵌入、堆叠块、LM 头、generate()。F.scaled_dot_product_attention。Mac M2 笔记本上,4 层、4 头、d_model=128 的 GPT 在 tinyshakespeare.txt 上训 2000 步:
ROMEO: 之类的专名涌现。💡 为什么选 Shakespeare:约 1.1 MB、65 个唯一字符、词汇表小到塞进 4 字节,没有 BPE 和分词器折腾,却能产生肉眼可辨的「像语言」输出——是字符级语言建模教学的标准玩具语料,2015 年以来每个 LM 教程都用它。
本节用 PyTorch,装 torch(CPU 版即可)。完整代码见原课程 phases/07-transformers-deep-dive/14-build-a-transformer-capstone/code/main.py,脚本负责:缺失时下载 tinyshakespeare.txt、字节级字符分词器、90/10 训练验证划分、支持硬件上的 bf16 autocast、训练完成后采样。
text = open("tinyshakespeare.txt").read() chars = sorted(set(text)) stoi = {c: i for i, c in enumerate(chars)} itos = {i: c for c, i in stoi.items()} encode = lambda s: [stoi[c] for c in s] decode = lambda xs: "".join(itos[x] for x in xs)
65 个唯一字符,小词表,塞进 4 字节 vocab_size,无 BPE、无分词器折腾。
块就是第 05 节的教科书版——pre-norm、RMSNorm、SwiGLU、因果 MHA。4/4/128 配置约 80 万参数。
取随机批量(长 256 的 token 窗口)→ 前向 → shift-by-one 交叉熵 → 反向 → AdamW 步 → 记录 → 重复:
for step in range(max_steps): x, y = get_batch("train") logits = model(x) loss = F.cross_entropy(logits.view(-1, vocab_size), y.view(-1)) loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0) # 防爆 opt.step() opt.zero_grad()
给定提示,反复前向、从 top-p logits 采样、追加、继续,500 token 后停。
2000 步后:
ROMEO: Away and mild will not thy friend, that thou shalt wit: The chief that well shame and hath been his friends, ...
不是莎士比亚,但是莎士比亚形状的。对 80 万参数、笔记本 6 分钟而言,这是清晰的胜利。
设计要点:绑定嵌入(lm_head 权重 = token 嵌入矩阵的转置)既省一半参数,又让「读词」和「写词」共享同一套语义空间——这是 GPT-2 以来的标准技巧,在第 07 节已讲过,这里直接用。梯度裁剪到范数 1.0 是防止训练爆炸的廉价保险,几乎所有生产训练都开。
这个毕业项目是参考架构。把它变成真东西的三个扩展:
tiktoken.get_encoding("cl100k_base")),词表从 65 跳到约 5 万,模型容量要相应 scale。OpenWebText 或 fineweb-edu(HuggingFace),单张 A100 上 1.25 亿参数 GPT 训 100 亿 token 约 24 小时。最终得到一个 1.25 亿参数、生成流畅英语的 GPT。不是前沿模型,但同一条代码路径——只是更大——就是 Karpathy、EleutherAI、Allen Institute 在 2026 年训研究检查点用的。
原课程产出 outputs/skill-transformer-review.md:一个审查 Skill,对照前 13 节审查一个「从零实现 Transformer」实现的正确性。
code/main.py,验证训练模型末步验证损失低于 2.0。把 max_steps 从 2000 改到 5000,验证损失还在提升吗?MultiHeadAttention 内对 Q 和 K 施加旋转,训练并验证损失至少一样低。F.scaled_dot_product_attention)、MoE(单 FFN)——练习带你逐个加回。下一节,我们回头系统梳理注意力变体——滑动窗口、线性注意力、稀疏注意力、Mamba/SSM 等,看清
softmax(QKᵀ)V之外还有哪些选择,以及它们各自换掉了O(N²)的哪一部分。