chapter 08 / llm-alignment · 预计学习时间 180 分钟
预训练结束你得到的不是 ChatGPT,是一个互联网文档模拟器:问它「中国的首都是哪里?」,它可能续写「日本的首都是哪里?韩国的首都是哪里?」——因为语料里这句话最常出现在试卷题目列表里。它有海量知识,但人格是「随机网页的下一行」。后训练(post-training)要解决三件事:格式(学会对话轮次)、有用(回答而不是续写)、无害(拒绝危险请求)。路线图就是 InstructGPT 三部曲:SFT → 奖励模型 → RL,外加 2023 年后的平替与升级(DPO、GRPO、RLVR)。
SFT 在机制上毫无新意——还是下一词预测交叉熵,只是数据从「随机网页」换成「精心编写的对话示范」,并且只对回答部分计算损失(prompt 部分 mask 掉)。对话先经 chat template 序列化:
<|im_start|>system
你是像素画生成器,只输出合法 JSON。<|im_end|>
<|im_start|>user
画一只 8x8 的橘猫<|im_end|>
<|im_start|>assistant
{"palette": ["#000", "#f80", ...], "pixels": [[0,1,...], ...]}<|im_end|> ← 只有这段算 loss
一个贯穿本章和第 13 章的真实案例:让 4B-9B 小模型稳定输出像素画 JSON(调色板+像素矩阵)。为什么这是聪明的任务设计?
闭环的标准方法论(每一步都不可省):
全量微调 8B 模型要 ~112GB 训练显存(权重+梯度+Adam 状态)。LoRA 的洞察:微调引起的权重变化 $\Delta W$ 是低秩的——任务适配只需在原能力上做小幅旋转。于是冻结 $W$,只训练一个低秩分解的旁路:
$$W' = W + \frac{\alpha}{r}\, B A, \qquad B \in \mathbb{R}^{d \times r},\ A \in \mathbb{R}^{r \times d},\ r \ll d$$$A$ 高斯初始化、$B$ 零初始化(保证 $t=0$ 时 $\Delta W = 0$,从基座无扰动出发)。$d{=}4096, r{=}16$ 时,一个 $d\times d$ 矩阵的可训练参数从 16.8M 降到 $r(d+d) = 131$K——0.8%。梯度和 Adam 状态只为这 0.8% 保存,显存从 14 字节/参数 暴跌到 2 字节/参数(冻结权重)+ 零头。训练完可把 $BA$ 合并回 $W$,推理零开销;或保留为独立 adapter(几十 MB),一个基座热插拔多个任务。
必做实验:① LLaMA-3 8B 默认配置——看全量 112GB vs LoRA 16GB 的断崖;② 把 70B 选上,看哪种硬件能跑 QLoRA;③ r 从 16 拉到 128——可训练参数增长 8 倍,但显存几乎不动(大头是冻结权重),理解「LoRA 的显存瓶颈不在 r」;④ 勾上 MLP 模块——参数翻几倍,知识注入型任务的标准操作。
显存为权重侧粗估(激活/batch 另加 10-20%)· Mac 统一内存按可用比例折算 · ✓=装得下
SFT 的天花板:示范者只能演示「好」,无法告诉模型「A 比 B 好多少」,而很多目标(有帮助、诚实、得体)写不成示范、只能比较。RLHF 把比较变成损失:
① 奖励模型(RM):收集人类对回答对的偏好 $(y_w \succ y_l)$,用 Bradley-Terry 模型把「偏好概率」与「分数差」挂钩并最大似然:
$$P(y_w \succ y_l) = \sigma\big(r_\phi(x, y_w) - r_\phi(x, y_l)\big), \qquad L_{RM} = -\log \sigma\big(r_\phi(x,y_w) - r_\phi(x,y_l)\big)$$② PPO 优化策略:让模型生成回答,RM 打分,但必须加 KL 惩罚锚住参考模型:
$$\max_\pi\ \mathbb{E}_{y \sim \pi}\Big[ r_\phi(x, y) \Big] - \beta\, \mathbb{D}_{KL}\big[\pi(y|x)\, \|\, \pi_{ref}(y|x)\big]$$RLHF-PPO 工程极重(同时伺候 4 个模型:策略/参考/RM/价值函数)。DPO(2023)发现了一条数学捷径,推导只有三步,值得完整走一遍:
第一步:上面的 KL 约束优化问题存在解析解(变分法标准结果):
$$\pi^*(y|x) = \frac{1}{Z(x)}\, \pi_{ref}(y|x)\, \exp\!\big(r(x,y)/\beta\big)$$第二步:反解出奖励——$r(x,y) = \beta \log \frac{\pi^*(y|x)}{\pi_{ref}(y|x)} + \beta \log Z(x)$。奖励可以用策略自身表示!
第三步:代入 Bradley-Terry 损失,配分函数 $Z(x)$ 在两个回答相减时恰好消掉:
$$L_{DPO} = -\log \sigma\Big( \beta \log \tfrac{\pi_\theta(y_w|x)}{\pi_{ref}(y_w|x)} - \beta \log \tfrac{\pi_\theta(y_l|x)}{\pi_{ref}(y_l|x)} \Big)$$不用训 RM、不用采样、不用 PPO——偏好数据直接梯度下降,像 SFT 一样简单,却隐式地在做同一个 RL 优化。代价:离线方法,不在自己生成的轨迹上学习(第 5 章曝光偏差的幽灵),上限通常低于在线 RL。实践常见组合:DPO 做第一轮便宜对齐,在线 RL(PPO/GRPO)做精修。
GRPO(DeepSeek)对 PPO 砍掉了最重的部件——价值网络(critic)。优势估计改用组内相对比较:同一个 prompt 采样 $G$ 个回答,各自的优势就是组内标准化的得分:
$$A_i = \frac{r_i - \text{mean}(r_1..r_G)}{\text{std}(r_1..r_G)}$$「比同组平均好就强化、差就抑制」——不需要学一个价值函数来当基线,省一半显存和全部 critic 调参玄学。
RLVR(可验证奖励的强化学习)解决另一头的问题:RM 是有损代理,但数学题可以对答案、代码可以跑测试——奖励是程序化的、不可 hack 的。配方(R1 路线):可验证任务集 + GRPO + 足够算力,模型自发涌现长思维链、反思、自我纠错(「等等,我重新检查一下」),无需人工示范推理过程。这就是 o1/R1 推理模型的引擎,也开辟了 test-time scaling 第二曲线(序章伏笔回收:想得越久越准)。
# 0) 评测先行:跑 base model 基线(假设 eval.py 校验 JSON/schema/调色板合规)
python eval.py --model Qwen/Qwen3-8B --suite pixel_art_v1
# → baseline: 0/12 pass ← 记住这个数字,它是一切结论的参照系
# 1) 数据:jsonl 每行一条 chat 格式样本(~几千条,质量>数量)
# {"messages":[{"role":"system","content":"你是像素画生成器…"},
# {"role":"user","content":"画一只8x8橘猫"},
# {"role":"assistant","content":"{\"palette\":[…],\"pixels\":[…]}"}]}
# 2) LoRA 训练(mlx-lm,600 步 ≈ 3 epoch 的管线验证跑)
python -m mlx_lm lora \
--model Qwen/Qwen3-8B \
--train --data ./data \
--num-layers 16 --batch-size 2 --iters 600 \
--learning-rate 1e-5 # SFT 学习率:比预训练小两个数量级
# 3) 训练后立刻评测对比基线(对照实验纪律)
python eval.py --model ./adapters --suite pixel_art_v1
# → 9/12 pass(0→9:管线有效;剩余3个失败案例逐个看,决定加数据还是改 schema)
# 4) 合并 adapter 导出部署(或保留 adapter 热插拔)
python -m mlx_lm fuse --model Qwen/Qwen3-8B --adapter-path ./adapters
规模感速查:~13M token 数据集、8B 模型、Apple Silicon 高端机型 ≈ 每 epoch 3-4 小时——完整 SFT 是一个过夜任务。这种「白天建数据集和评测、晚上跑训练、早上看分数」的节奏,就是垂直团队后训练的日常。
视频讲解:Karpathy 通览的后半段正好覆盖本章全部主题(你在第 7 章已经看了前半):