从零训练一个小模型¶
这本小册子从一个空目录开始,在自己的电脑上训练一个会写《三国演义》的小语言模型:准备语料、训练分词器、写模型和训练循环、评估与生成,再把它训得更快、更大;接着做指令微调,让它按对话的格式回答,用 LoRA、DPO 和蒸馏走一遍后训练,并导出成现成推理框架能直接加载的格式;最后换到一张消费级显卡上看看一晚上能训出什么——文本模型和图像生成模型各一个。全部代码都真实运行过,主线在 CPU 上约 6 分钟跑完。真实的训练只是多了几个数量级的数据和算力,流程是同一个。
6 章2 道练习题六章接力运行,输出都来自真实运行
快速开始¶
先把它跑起来,再回头看每一步为什么这么做。只要 CPU,主线五个脚本一共约 6 分钟。
# ① 环境:CPU 版 PyTorch(2.4 以上)与 tokenizers
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install tokenizers
# ② 新建一个空目录,把各页里带文件名的代码块复制进去(每页右上角也能下载成 notebook)
mkdir mylm && cd mylm
# ③ 按顺序跑,前一个脚本的产出留给后一个
python prepare.py # (一)语料 → BPE 分词器 → token 序列
python train.py # (二)训练一个 1.8M 的小 GPT,它会写《三国演义》风格的句子
python chat_data.py # (四)从同一份语料造指令数据
python sft.py # (四)指令微调,它开始按对话的格式回答
python export.py # (五)导出成 LLaMA 的权重布局
# ④ 跟它说句话
python talk.py
训完之后它是这样的——三问三答都是真实的,模型一共 1.8M 参数,只读过一本《三国演义》:
答得对不对另说,但它确实在按对话的格式回答、而且知道在哪停。真实的模型只是把数据和算力各放大几个数量级,流程是同一个。
其余脚本都是实验:量时间、验证等价性、比较几种做法。它们不产出主线要用的文件,挑着跑、或者只看页面上的输出都可以。
| 脚本 | 章 | 做什么 | 耗时 | 产出 |
|---|---|---|---|---|
prepare.py |
一 | 下载语料、训练 BPE 分词器、切训练/验证集 | 4 秒 | tokenizer.json、tokens.pt |
model.py |
二 | 模型定义(后面每一章都 import 它) | — | — |
sizes.py |
二 | 词表、深宽、KV 头的账 | 2 秒 | — |
train.py |
二 | 完整的训练循环,存 checkpoint、采样 | 2.5 分钟 | ckpt.pt |
resume.py |
二 | 验证中断续训和不中断完全一致 | 6 秒 | — |
sampling.py |
二 | 温度与 top-k 的影响 | 2 秒 | — |
speed.py |
三 | 一步的时间花在哪里、MFU 是多少 | 20 秒 | — |
grad_accum.py |
三 | 梯度累积与大 batch 等价 | 2 秒 | — |
ddp_train.py |
三 | 两个进程的 DDP,结果与单进程一致 | 8 秒 | — |
scaling.py |
三 | 四个尺寸的模型各训 400 步 | 2.6 分钟 | — |
budget.py |
三 | 推到 GPU 和大模型上的时间与成本 | 瞬间 | — |
chat_data.py |
四 | 从语料造三类指令数据 | 不到 1 秒 | sft_*.jsonl |
chat.py |
四 | 聊天模板与掩码(后面要 import) | 1 秒 | — |
sft.py |
四 | 指令微调,只在助手的回答上算 loss | 3.2 分钟 | sft.pt、tokenizer_chat.json |
lora.py |
五 | 只训练 1.34% 的参数,换一个回答格式 | 1 分钟 | — |
dpo.py |
五 | 用偏好对直接优化策略 | 1.7 分钟 | — |
distill.py |
五 | 把 1.8M 老师的分布蒸进 0.62M 的学生 | 3.3 分钟 | — |
export.py |
五 | 导出成 LlamaForCausalLM 的权重布局 |
2 秒 | minisanguo/ |
耗时是在一台 Intel Xeon Platinum 8336C 上按 OMP_NUM_THREADS=2 实测的,只用来给个量级(全书跑完 15 分钟);需要 GPU 的脚本(train_gpu.py 和最后一章)不在表里。
这本书适合谁¶
- 读过 Transformer 的结构、会写 PyTorch,但还没有亲手训练过一个语言模型;
- 想能说"我从零训过一个模型",并且讲得清每一步在干什么、时间花在哪里;
- 手上只有一台笔记本或一张消费级显卡,想知道这点算力能做到什么。
读完并跟着做完,你应该能:
- 从一份纯文本开始训练 BPE 分词器,解释词表大小怎么权衡;
- 写出一个 pre-norm 的小 GPT 和完整的训练循环(学习率调度、梯度裁剪、验证、checkpoint、续训、生成);
- 测出一步的时间花在哪里、算力用上了多少,并用梯度累积、
torch.compile、混合精度、DDP 把它训得更快更大; - 写出聊天模板、把 loss 只算在助手的回答上,把基座模型微调成会按格式作答的小助手;
- 从零写出 LoRA、DPO 和白盒蒸馏,讲清每一件在改什么、代价是什么,并把模型导出给推理框架;
- 为一张 16 GB 的卡算出显存账本,知道能放下多大的模型、训一晚上能到什么程度。
六章的路线¶
| 章节 | 做什么 | 学完能做什么 | 建议用时 |
|---|---|---|---|
| (一)语料与分词器 | 准备《三国演义》语料,训练一个 BPE 分词器,切出训练集与验证集 | 知道词表大小怎么选、预切分为什么重要 | 半天 |
| (二)模型与训练循环 | 写一个小 GPT,写完整的训练循环,存 checkpoint、续训、采样生成 | 自己训出第一个会写文言文的模型 | 1 天 |
| (三)训得更快、更大 | 量时间与算力利用率,梯度累积、编译、多卡 DDP,再放大模型 | 知道训练慢在哪、放大时要算哪些账 | 1 天 |
| (四)从续写到对话 | 造指令数据、写聊天模板,只在助手的回答上算 loss,微调一遍 | 把基座模型变成会按格式作答的小助手 | 1 天 |
| (五)更省地调、对得更齐 | 从零写 LoRA、DPO 和白盒蒸馏,再导出成 LLaMA 的权重布局 | 讲清后训练各环节在做什么,并把模型交给推理框架 | 1 天 |
| 一张消费级卡能训出什么 | 换到 16 GB 的真卡:显存账本、文本模型一晚上、图像生成小模型 | 对"这张卡能做什么"有数量上的把握 | 1 天 |
六章的代码是接力的:前一章生成的语料、分词器和 checkpoint 留给后一章用,建议按顺序做,都放在同一个目录里。
接下来往哪走¶
| 想继续的方向 | 去哪本 |
|---|---|
| 不用现成的库,自己写 BPE、模型和 AdamW,并跑通评分脚本 | 大模型原理的大作业 |
| 一张卡放不下的时候:DDP、ZeRO、张量并行、流水线并行 | 分布式训练手册 |
| 模型的每个部件为什么这样设计 | 大模型原理 |
| 训好的模型怎么高效地服务 | 推理系统、手写 mini-sglang |
怎么验证的¶
- 所有标了文件名的脚本都在 CPU 版 PyTorch 上实际运行,页面上的输出与运行结果逐行一致;六章按顺序接力跑,共用一个工作目录,全部跑完约 15 分钟;
- 需要 GPU 的那一章(最后一章)只做语法检查,页面上的数字标明了测量它的卡(RTX 5070 Ti,16 GB)。
# 需要 CPU 版 PyTorch(2.4 以上)与 tokenizers
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install tokenizers
发现错误或有更好的写法?在 GitHub 上编辑此页提交问题