跳到主要内容

《Build a Reasoning Model (From Scratch)》通读笔记(第一批:前言 + 第 1 章)

这份笔记是给后面写大纲的人用的,不是正文。

怎么读出处: 形如 text/04-ch01-….txt:35 是省略掉的文件名中段 —— 认前两位数字就够:ls library/build-reasoning-model/text/ | grep '^04' 即可定位。 冒号后面是清洗文本里的真实行号,sed -n '35p' 直接跳过去。

这批行号已逐条机器核过(581 处,全部落在非空行)。 少数「范围终点」故意落在 )]\] 这类代码或输出块的收尾行上,那标的是块的末尾,不是笔误。 但写正文引用时仍要按标准补上「搜『原文短语』」 —— 重新转码会让行号漂移,短语不会。

零、体检结论

node scripts/book-health.mjs build-reasoning-model✓ OK,562k 字。无「坏」无「可疑」,可以动笔。

导航章清单(不读、不引): 01-fm-…(版权页,259 字符)、03-fm-brief-contents(目录)。 02-fm-welcome 是作者亲笔的 MEAP 前言,有信息量,可引

一、这本书的身份(影响怎么读)

依据
作者Sebastian Raschka(PhD)text/02-fm-….txt:60
出版Manning,epub 元数据日期 2026-03-17chapters.json
版本状态MEAP(Manning 早期试读版),不是定稿text/02-fm-….txt:12「Thank you for purchasing the MEAP for…」
前作同作者《Build a Large Language Model (From Scratch)》,本书不要求先读text/04-ch01-….txt:53text/04-ch01-….txt:325

MEAP 这件事必须在总纲里点明:早期试读版意味着文字可能还会改、章节可能还会增删。 但书里的代码路线是完整的(八章 + 七个附录都在)。

时代坐标(书里自己给的,不是我们加的):

  • OpenAI o1 发布:2024-09-12,书说它「让 reasoning 这个词进了公众视野」(text/04-ch01-….txt:339)
  • DeepSeek-R1 + 技术报告:2025-01,arxiv 2501.12948,书说它「不但开放了能打赢 o1 的模型,还公开了训练蓝图」(text/04-ch01-….txt:351)
  • Sam Altman 2025-02-12 的表态被整段引用:GPT-4.5 是「最后一个非思维链模型」(text/04-ch01-….txt:670)
  • 书里提到的当代推理模型:Anthropic Claude 4、xAI Grok 4、Google Gemini 2.5、DeepSeek R1、Alibaba Qwen3、OpenAI o1/o3/o4-mini/GPT-5(text/04-ch01-….txt:630)
  • 提到 agent 应用「OpenClaw」(text/04-ch01-….txt:41)—— 这是书里唯一一处具体 agent 产品名, 写的时候要核一下这是什么(见「缺口清单」)。

二、第 1 章:全书的定义层与地图(text/04-ch01-…txt,35.4k 字符)

这一章没有代码,是整本书唯一的纯概念章。它干四件事:定义 reasoning、回顾常规训练管线、 把改进手段分成三类、把 reasoning 和「模式匹配」摆到一起对照。

2.1 全书最要紧的一个定义(text/04-ch01-….txt:89text/04-ch01-….txt:101)

reasoning = 模型在给出最终答案之前,先生成中间步骤。

  • 作者明说这是「工程意义上的,不是哲学意义上的」(text/04-ch01-….txt:89,搜「practical engineering sense」);
  • 中间步骤可以显示给用户,也可以裹在 <think>...</think> 这类标签里藏起来 —— 两种都算(text/04-ch01-….txt:95);
  • 核心是「让模型把 token 花在中间过程上,而不是直接跳到结论」(text/04-ch01-….txt:95);
  • reasoning model = 被(训练或提示)改造成会产出这种中间步骤的 LLM(text/04-ch01-….txt:101)。

这个定义是全书的地基:后面每一章都在回答「怎么让它多花 token 在中间步骤上、并且花得值」。

2.2 作者反复设的防线:LLM 的 reasoning 不是逻辑推理

这是第 1 章的主要论证,分三处递进,不是一句免责声明:

  1. text/04-ch01-….txt:120(边栏 Chain-of-Thought):作者说他用 reasoning / thinking 是「常见工程说法」, 不暗示 LLM 像人一样推理;
  2. text/04-ch01-….txt:172text/04-ch01-….txt:178:拿符号逻辑引擎 / 定理证明器做对照 —— 那种系统按固定规则走, 同样输入必然同样输出(书用了做菜的比方:照方子走一定得到同一道菜,text/04-ch01-….txt:172); 而 LLM 是自回归地一次吐一个 token、靠训练数据里的统计规律, 所以「它的推理步骤没有逻辑上正确的保证,哪怕看起来很有说服力」(text/04-ch01-….txt:178);
  3. 边栏「LLM versus human reasoning」(text/04-ch01-….txt:197text/04-ch01-….txt:209):人可以确定性地推理 (同样的事实 + 同样的步骤 = 同样的结论),LLM 是概率性的

2.3 常规 LLM 训练管线(1.2 节,text/04-ch01-….txt:217text/04-ch01-….txt:325)

书把它压成两段(明说把有些论文所谓的 mid-training 并进了预训练,text/04-ch01-….txt:235):

随机初始化的模型
│ 预训练:海量无标注文本(TB 级 / 万亿 token),目标 = 预测下一个 token
▼ 得到 base model —— 会写像人写的话,并冒出「涌现能力」(翻译、写代码等没专门教过的活)
│ 后训练之一:监督微调 SFT(= instruction tuning)→ 会听指令办事
│ 后训练之二:偏好微调(常用 RLHF 实现)→ 语气、风格合人心意
▼ 得到我们平时用的 LLM
  • 成本句:「几千块 GPU 跑几个月,花掉几百万美元」(text/04-ch01-….txt:281)—— 这是本章少数带量的句子;
  • 一个容易被跳过的细节:书特意说「哪怕做完指令微调,它也还不是 chatbot」—— 聊天界面是另一层:系统提示词、多轮历史管理、编排(text/04-ch01-….txt:312),并指向附录 G;
  • 「token / 词」的边栏(text/04-ch01-….txt:261text/04-ch01-….txt:273)给了具体切分例: "An LLM can be useful.""An", " L", "LM", " can", " be", " useful", "." —— 这是全书第一个可直接搬进正文的走查素材;
  • 书自己划的边界:这些阶段在前作里讲,本书不讲,直接加载已经训好的模型(text/04-ch01-….txt:325)。

2.4 三条改进路线(1.3 节,text/04-ch01-….txt:382text/04-ch01-….txt:391)—— 全书骨架

路线动不动权重干什么书里哪几章
推理时计算扩展(inference-time compute scaling,别名 test-time scaling)不动用户提问那一刻多花算力换正确率:思维链、各种采样法第 4、5 章
强化学习(RL)用奖励信号让模型试错学出推理策略第 6、7 章
蒸馏(distillation)拿强模型生成的高质量数据对小模型做 SFT第 8 章

作者特意标了一处术语陷阱(text/04-ch01-….txt:391):LLM 圈说的「蒸馏」和深度学习传统的知识蒸馏不是一回事—— 传统蒸馏里学生要同时学老师的输出和 logits,LLM 蒸馏只拿老师生成的文本做 SFT。 这条要在拆解里显式讲,否则读者出门会认错。

另一处术语陷阱(边栏,text/04-ch01-….txt:403text/04-ch01-….txt:415):推理用的 RL 和偏好微调用的 RLHF 底层是同一套 RL, 差别在奖励从哪来:RLHF 靠人打分/排序,推理 RL 靠自动验证器或环境给的可验证信号。 作者的评价很平衡:自动验证「更客观,但可能离人的偏好更远」(text/04-ch01-….txt:415)。

2.5 模式匹配 vs 逻辑推理(1.4–1.5 节,text/04-ch01-….txt:429text/04-ch01-….txt:644)

这是第 1 章的主走查素材,书自己走了一遍,我们可以直接用:

  • 例一(纯模式匹配):提示「The capital of Germany is…」→ 答「Berlin.」(text/04-ch01-….txt:448text/04-ch01-….txt:459)。 书的判词:这不是逻辑演绎,是回忆起一条很强的统计关联(text/04-ch01-….txt:467);
  • 例二(需要逻辑):「All birds can fly. A penguin is a bird. Can a penguin fly?」(text/04-ch01-….txt:491)。 书把它拆成两种读法:
    • 闭世界(只看提示里的前提):答案是「能飞」—— 因为两条前提逼出这个结论(text/04-ch01-….txt:502);
    • 开世界(允许用背景知识):「企鹅不会飞」这条外部事实和结论冲突, 合格的推理系统应当发现矛盾,要么反问澄清,要么把第一条前提削弱成 「大多数鸟会飞,企鹅等除外」(text/04-ch01-….txt:508);
  • 例三(打脸自己):GPT-4o —— 不是推理模型 —— 在 ChatGPT 里居然答对了(图 1.7,text/04-ch01-….txt:566text/04-ch01-….txt:591)。 书的解释才是重点:它没有做矛盾检测,是因为训练数据里「penguins cannot fly」出现得够多, 统计关联本身就把矛盾隐式修正了(text/04-ch01-….txt:591text/04-ch01-….txt:597)。
  • 书给出的失效条件(text/04-ch01-….txt:609text/04-ch01-….txt:618):这种靠模式匹配的「假推理」在两种场合会崩 —— ① 逻辑情形是新的(训练里没见过);② 推理层数多、关系复杂。

这一段的价值极高:它就是全书的「为什么需要后面七章」。三个例子从「明显是记忆」→ 「看着像推理」→「其实还是记忆,只是数据够多」,一步步把读者逼到「那怎么办」。

还有一条作者的态度(text/04-ch01-….txt:644):reasoning 是连续谱,不是开关。o1/R1 之前的 LLM 就已经会 生成中间步骤了;今天所谓「推理模型」只是这个能力的精修版。

2.6 为什么要从零手写(1.6 节)+ 成本账

书给了推理模型贵在哪的两条具体机制(text/04-ch01-….txt:695text/04-ch01-….txt:714),这是可直接用的量化素材:

  1. 输出更长:每个 token 都要走一遍完整的前向计算;答案长一倍,前向次数就约多一倍(text/04-ch01-….txt:701);
  2. 调用更多次:很多推理流程要跑模型好几遍 —— 采样多个候选、调工具、跑验证器(text/04-ch01-….txt:714)。

配套的判断(text/04-ch01-….txt:683text/04-ch01-….txt:689):推理不是越多越好。适合复杂任务(谜题、高等数学、难代码) 和 agent(任务分解、规划、选工具);不适合摘要、翻译、知识问答。书还点了 「overthinking(想太多)反而更容易错」这个失效模式(text/04-ch01-….txt:689)。

2.7 全书路线图(1.7 节,text/04-ch01-….txt:732text/04-ch01-….txt:776)

书自己画的四阶段(图 1.9):

阶段 1 拿一个常规 LLM 当基线(第 2 章)

阶段 2 先把「怎么量」做出来(第 3 章) ←──────┐
▼ │ 阶段 3、4 都要回到阶段 2 复测
阶段 3 不改权重,在推理时改进(第 4、5 章)──┤
阶段 4 改权重,靠训练改进(第 6、7、8 章)──┘

「先做评测再做改进」是这本书的方法论主张,作者写得很直白: 「阶段 2 做出判断某个方法到底有没有用的工具……阶段 3、4 之后都要回到阶段 2 量一次」(text/04-ch01-….txt:751)。 这一条在拆解里要提到总纲的高度 —— 它是这本书区别于「炫技型」教程的地方。

三、第一批读完后的初步判断(待后面几章验证)

  1. 全书真正的落点大概率是第 6–7 章(GRPO 训练),第 8 章(蒸馏)是「便宜替代路线」的收尾; 第 2、3 章是地基,第 4、5 章是「不训练也能拿到的收益」。
  2. 第 1 章是唯一的纯概念章,信息密度高但可读性好,适合当拆解的第 01 章底本, 但新词密度极高(reasoning / CoT / token / 预训练 / SFT / 偏好微调 / RLHF / 自回归 / 涌现 / 蒸馏 / logits / 推理时扩展 / 强化学习……),按配额必须拆成多节甚至多章。
  3. 第 1 章里 GPT-4o 那个企鹅例子是全书最好的开场素材 —— 先现象后原理,而且现象本身反直觉 (不是推理模型却答对了)。

第二批:第 2 章(拿一个现成模型跑起来)+ 第 3 章(先把尺子造出来)

四、第 2 章:基线模型与文本生成(text/0515,共 71k 字符)

这一章在全书里的位置:阶段 1「拿一个常规 LLM 当基线」。 它是全书唯一的「装机章」, 但里面有三样东西是后面每一章都要用的:分词、自回归生成循环、以及两招提速。

4.1 为什么从 base model 起步(而不是从助手模型起步)

书给了明确理由:从 base model 起步,才看得出后面的收益是「推理方法带来的」还是「后训练带来的」 (text/05-ch02-….txt:38,搜「which capabilities come from the reasoning methods themselves」)。 所以第 2 章加载的是没有做过指令微调、没有做过偏好微调的纯预训练模型。

4.2 选型:Qwen3 0.6B(text/10-ch02-05-….txt:26text/10-ch02-05-….txt:41)

模型Qwen3 0.6B(0.6B = 约 6 亿个权重参数)
为什么选它① 小到能在普通电脑上跑,权重公开可下载;② Qwen3 同时提供 base 版和官方推理版 —— 后者当参照系
实现作者自己用纯 PyTorch 重写的 Qwen3,不依赖任何第三方 LLM 库,但与官方权重完全兼容(text/10-ch02-05-….txt:61)
权重文件qwen3-0.6B-base.pth,1433 MiB;分词器文件 6 MiB(text/10-ch02-05-….txt:209text/09-ch02-04-….txt:53)
架构(PyTorch 打印出来的)嵌入层 151936×1024 → 28 个 TransformerBlock(分组查询注意力 + 前馈 + RMSNorm)→ 输出头 1024×151936(text/10-ch02-05-….txt:263text/10-ch02-05-….txt:286)
书的态度架构可以当黑盒,我们不改它,只在上面加推理方法」(text/10-ch02-05-….txt:298)

「官方推理版当参照系」这一手很重要 —— 它给了全书一个「天花板参考值」, 后面每次改进都可以问「离官方推理版还差多少」。

4.3 训练一个 base model 到底多贵(2.3 节,可直接用的量化素材)

书给的是有出处的真实数字,不是估算:

出处
头部公司训一个 base model低端 100–1000 万美元,高端 5000 万美元以上text/08-ch02-03-….txt:7
DeepSeek V3(R1 的底座)2048 张 Nvidia H800,跑约 11 周,约 550 万美元text/08-ch02-03-….txt:13
同上,总算力1480 万 GPU 小时text/08-ch02-03-….txt:19
同上,耗电约 620 兆瓦时 ≈ 一个美国普通家庭用 55 年的电text/08-ch02-03-….txt:19

书特意说 DeepSeek V3 是「少数几个把算力开销完全公开的模型之一」(text/08-ch02-03-….txt:13)—— 这句话本身就是一条判断,值得在拆解里点出来。

作者的比方(text/08-ch02-03-….txt:37):想搞懂汽车怎么工作,不该一上来就造法拉利,先造甲壳虫; 他甚至认为小车更好懂,因为「复杂的精细改良和细节都被拿掉了」。 —— 这是比喻,按行文第 7 条用完即拆,不许当术语反复用。

还有一条硬边界:第 2–5 章 CPU 就能跑,第 5–8 章「会受益于 GPU」(text/08-ch02-03-….txt:43text/08-ch02-03-….txt:91)。

利益相关必须写进总纲第 2 节:作者在 2.3 节主动披露 —— 他 2023 年参与创建了 Lightning AI 平台,现已无财务利益,不是赞助,自己付费用(text/08-ch02-03-….txt:144)。

4.4 分词:全书第一条可用的走查(2.4 节)

"Explain large language models."
│ tokenizer.encode()

840 → "Ex" 20772 → "plain" 3460 → " large"
4128 → " language" 4119 → " models" 13 → "."
│ tokenizer.decode()

"Explain large language models." ← 原样还原

出处:text/09-ch02-04-….txt:157text/09-ch02-04-….txt:162(六个 ID 的完整清单)、text/09-ch02-04-….txt:168(「split into six token IDs」)。

关键细节,拆解里必须讲的三条:

  1. "Explain" 被切成 "Ex" + "plain" 两块,因为分词器用的是字节对编码(BPE) —— 用整词和词片混着拼,常见词和罕见词都能表示(text/09-ch02-04-….txt:174);
  2. 空格常常被算进 token 里(比如 " large"),这样模型才分得清词的边界(text/09-ch02-04-….txt:174);
  3. Qwen3 的词表约 151,000 个 token;对照:早期 GPT-2 约 5 万,Llama 3 约 12.8 万(text/09-ch02-04-….txt:180)。 —— 这就是行文第 13 条要的参照物,书自己给了。

词表大小的权衡(text/09-ch02-04-….txt:186),这段是好素材: 词表大 → 嵌入层和输出层要存更多东西,模型变大、每个 token 的计算也更贵; 但词表大 → 更多词能一个 token 装下,序列更短。 书给的换算:序列 token 数翻一倍,计算成本大致也翻一倍。

4.5 自回归生成:一次前向出多少个预测(2.6 节,全书最重要的机制之一)

这一节讲清了一件读者普遍误解的事:

模型一次前向会给「每一个输入位置」都产出一个预测,但生成时只用最后一个。

具体走查(书自己走的,数都在):

prompt = "Explain large language models." → 6 个 token
│ 一次前向

输出张量形状 torch.Size([6, 151936])
│ 6 = 输入 token 数;151936 = 词表大小
│ 每一行 = 该位置对「下一个词是谁」的 151936 个打分

取最后一行 output[-1] → tensor([7.3750, 2.0312, 8.0000, …, -2.5469]) dtype=bfloat16
│ torch.argmax(...)

20286 → tokenizer.decode([20286]) → " Large"

出处:text/11-ch02-06-….txt:195text/11-ch02-06-….txt:196(形状)、text/11-ch02-06-….txt:254(打分向量原样)、text/11-ch02-06-….txt:287(argmax 得 20286)、text/11-ch02-06-….txt:313(解回 " Large")。

四个必须就地解释的点(书都解释了,我们照抄口径):

  • 书特意澄清:图里看着像「输入右移一位」,其实不是 —— 每个位置产出的是 「下一个 token 的一个分布」(text/11-ch02-06-….txt:60);
  • bfloat16:一种降精度的数字格式,用来省内存、提速(text/11-ch02-06-….txt:261);
  • argmax 就是贪心解码(greedy decoding)—— 永远挑分最高的那个, 书明说「后面会讲别的选法」(text/11-ch02-06-….txt:326)——这是通向第 4 章温度/top-p 的伏笔;
  • 边栏「inference」的一词两义(text/12-ch02-07-….txt:393text/12-ch02-07-….txt:411):神经网络说的 inference = 拿已经训好、参数固定的模型跑一次前向;统计学说的 inference = 从数据里估参数。 作者明说这两件事不是一回事。这是我们拆解里必须原样保留的辨析,中文「推理」二字更容易混。

4.6 生成循环与停止条件(2.7 节)

  • 循环体:out = model(token_ids)[:, -1]argmax → 拼回序列 → 再来(text/12-ch02-07-….txt:60text/12-ch02-07-….txt:69);
  • 不给停止条件会怎样:模型答完正事后吐出特殊 token <|endoftext|>(ID 151643), 然后继续往下瞎写(text/12-ch02-07-….txt:151text/12-ch02-07-….txt:172)。书把这个「跑飞」的输出原样印出来了 —— 很好的现象素材;
  • 传入 eos_token_id 之后,输出就干净地停在句号处(text/12-ch02-07-….txt:243text/12-ch02-07-….txt:252)。

4.7 两招提速:KV 缓存 + 编译(2.8–2.9 节)

KV 缓存(text/13-…txt):

  • 问题:每生成一个新 token,都要把整段序列重新算一遍,而除了新来的那个 token, 其余全都和上一轮一模一样(text/13-ch02-08-….txt:51);
  • 做法:把注意力里算出来的 key 和 value 存下来复用;第一轮喂全序列,之后每轮只喂新来的那一个 token(text/13-ch02-08-….txt:124text/13-ch02-08-….txt:130);
  • 代价函数:不缓存时生成 n 个 token 的总工作量约 O(n²)(工作量随输出长度的平方涨), 缓存后降到约 O(n)(与 token 数成正比)—— 书就地解释了这两个记号什么意思(text/13-ch02-08-….txt:57);
  • 明说 KV 缓存的内部机制超出本书范围,给了作者自己的免费文章链接(text/13-ch02-08-….txt:63)。

torch.compile(text/14-…txt): 分析模型的计算图,把一堆算子合成更优的核,减少 Python 开销(text/14-ch02-09-….txt:20)。 第一次跑反而更慢(要先编译),所以书跑三次、第一次标成「warm-up」(text/14-ch02-09-….txt:52)。

实测数(Mac Mini M4 CPU,生成 100 token,text/12-ch02-07-….txt:369text/13-ch02-08-….txt:178text/14-ch02-09-….txt:266):

配置tokens/秒耗时
朴素57.94 秒
只编译66.78 秒
只 KV 缓存291.40 秒
KV 缓存 + 编译680.60 秒

表 2.1 还给了跨硬件对照(text/14-ch02-09-….txt:325text/14-ch02-09-….txt:489):

硬件朴素朴素+编译KVKV+编译显存
Mac Mini M4 CPU562868
Mac Mini M4 GPU27434171
NVIDIA H10051164481411.81 GB

书自己解释了「为什么 H100 没有拉开更大差距」(text/14-ch02-09-….txt:498text/14-ch02-09-….txt:528),这段很诚实,值得引:

  1. 这个实现没有为 GPU 优化 —— GPU 优化版会预先分配到最大上下文长度(4 万 token)的 K/V 张量,省掉反复 torch.cat,但吃更多内存;作者选了「按需增长」这条更省内存的路, 因为「内存才是大多数读者的瓶颈」;
  2. 模型太小。模型越大,KV 缓存和 GPU 内存布局的收益越明显;
  3. 全部实验都是 batch size = 1(单条 prompt);批量推理在附录 E。

为什么第 2 章要花力气讲提速(text/13-ch02-08-….txt:19): 「评测和推理流程动辄要生成很多 token、很多候选答案,这里省下的一点会成倍放大」。 —— 这句话是第 2 章和第 3–7 章之间的桥,不讲这句,读者不明白装机章为什么讲性能。

五、第 3 章:先造尺子(text/1626,共 66k 字符)

这一章是全书方法论上的枢纽。 书自己说了两遍它的双重身份: ① 阶段 2「评测」;② 它造出来的验证器,到第 6 章会原样变成强化学习的奖励信号 (text/16-ch03-….txt:41text/22-ch03-06-….txt:13)。

5.1 四种评测法,书选了哪一种(3.1 节)

书把 LLM 评测分成两大类四小种(text/17-ch03-01-….txt:7text/17-ch03-01-….txt:13):

基准测试型(偏定量) 评判型(偏定性)
├─ 多选题 ├─ 排行榜(人类偏好投票)
└─ 验证器 ←── 本章选这个 └─ LLM 当裁判

为什么选验证器:数学题既需要一步步推理,又能自动判对错(text/17-ch03-01-….txt:19)。 代价书也写了(text/17-ch03-01-….txt:65):只能用在数学、代码这类能确定性验证的领域; 还会引入额外复杂度和依赖,并且把一部分评测负担从模型转移到了外部工具身上

其余三种在附录 F(35k 字符,是全书最大的附录)。

5.2 八步验证流水线(text/17-ch03-01-….txt:77,图 3.3)

① 加载预训练 LLM
② 让它生成答案
③ 抽出答案框 \boxed{...} ← 3.4 节
④ 归一化成标准写法 ← 3.5 节
⑤ 用符号数学引擎判等价 ← 3.6 节
⑥ 打分(处理元组等多段答案) ← 3.7 节
⑦ 加载 MATH-500 数据集 ← 3.8 节
⑧ 全量跑一遍,得出准确率 ← 3.9 节

这八步就是拆解「评测」那一章现成的主走查骨架。

5.3 走查用的那道题(全章贯穿,书自己选的)

已知 a+b=3ab=13/6,求 a²+b²。正确答案 14/3

模型(base 版)的输出是这样的(text/18-ch03-02-….txt:196text/18-ch03-02-….txt:215):用恒等式 a²+b² = (a+b)² - 2ab → 代入 → \boxed{\dfrac{14}{3}}

书在这里下了一个很重要的判断(text/18-ch03-02-….txt:227): base 模型居然给出了「像推理模型一样」的分步解释 —— 作者说这很可能是因为 Qwen3 团队在预训练阶段就掺了思维链数据(依据是他们的技术报告)。 这条要在拆解里保留,它说明「推理能力是连续谱」不是空话。

四步的具体中间结果(可直接搬):

输入输出出处
抽框...\boxed{\dfrac{14}{3}}...\dfrac{14}{3}text/20-ch03-04-….txt:190
归一化\dfrac{14}{3}(14)/(3)text/21-ch03-05-….txt:198
归一化(另一种写法)\text{\[\frac{14}{3}\]}同样是 (14)/(3)text/21-ch03-05-….txt:217
符号判等28/6SymPy 化简成 14/3text/22-ch03-06-….txt:146text/22-ch03-06-….txt:152

5.4 三个机制的「为什么非要这么做」

① 抽框为什么不用正则一把梭: get_last_boxed手写的括号配平扫描 (从最后一个 \boxed 起、跳空白、认 {、按 depth 计数配对,text/20-ch03-04-….txt:107text/20-ch03-04-….txt:140), 因为 \boxed{\dfrac{14}{3}} 里面还有嵌套花括号。

书专门用一个边栏回答了「为什么不干脆让另一个 LLM 来抽答案」(text/20-ch03-04-….txt:369text/20-ch03-04-….txt:381): 抽取是机械活,用代码做确定、可复现、便宜;用 LLM 会引入不必要的复杂度和它自己的波动。 —— 这是书里少见的、明确反对「什么都用 LLM」的立场,拆解里要保留。

② 归一化为什么必要: 同一个值模型能写成 \frac{14}{3}14/3$14/3$(14)/(3) 好几种 (text/21-ch03-05-….txt:7)。normalize_text 干的活(text/21-ch03-05-….txt:172): 删特殊 token、删 \left/\right/度数符号、拆 \text{...} 外壳、去掉行内公式标记、 \sqrt{a}sqrt(a)\frac{a}{b}(a)/(b)^**、去千分位逗号、最后统一小写。

③ 判等为什么要上符号引擎: 直接用 == 不行 —— 14/3(14)/(3) 字符串不同; 28/614/3 数学上相同但字符串完全不同(text/22-ch03-06-….txt:26)。 所以用 SymPy(开源符号数学库,已开发测试二十年,text/22-ch03-06-….txt:38), equality_check 的做法是:先试字符串全等 → 不等就双方各自解析成 SymPy 对象 → 判断「两者之差化简后是不是 0」(text/22-ch03-06-….txt:170text/22-ch03-06-….txt:191)。

作者的一条坦白很有价值(text/22-ch03-06-….txt:116): sympy_parser 里捕获的异常种类看着「多到离谱」,但每一种都是他在跑完 500 道题时真撞上的 —— 因为模型不总是产出格式良好的输出。这是「从零手写」才会暴露的现实。

5.5 书自己演示的一次失败,然后修好(极好的教学素材)

书没有一路顺风:3.6 节末尾,equality_check元组答案上翻车了 —— 比较 (14/3, 2/3)(14/3, 4/6),数学上等价,却返回 False, 因为它只会处理简单表达式,不认元组(text/22-ch03-06-….txt:277)。

3.7 节才补上 split_into_parts(按逗号拆开)+ grade_answer(逐段判等,全对才算对), 并给了 16 条测试用例全 PASS 的表(text/23-ch03-07-….txt:176text/23-ch03-07-….txt:275)。几条有意思的:

用例预测标准答案期望
check_3\frac{\sqrt{8}}{2}sqrt(2)True
check_6(2, 1)(1, 2)False(顺序算数)
check_80.51/2True
check_90.33333333331/3False(近似值不算)
check_1250%1/2False

check_9 和 check_12 是这份验证器的边界所在,拆解里要点出来: 它做的是符号等价,不是数值近似;百分号在归一化时被直接删掉,所以 50% 变成了 50

5.6 数据集:MATH-500(3.8 节)

  • 500 道题,从原始 MATH 数据集里精选出来的(text/24-ch03-08-….txt:7);
  • 选它的三条理由(text/24-ch03-08-….txt:20):① 大到有意义、小到能反复跑; ② 后面几章的训练子集来自原始 MATH 但与这 500 题不重叠,所以它能当干净的留出集; ③ 它是推理模型文献里的常用基准,结果好和别人比。 书还说明为什么不用更简单的 GSM8K:MATH-500 对现代推理模型更有挑战性。
  • 出身:这个划分最早出自 OpenAI 的 PRM800K 仓库,现在也在 Hugging Face 上(text/24-ch03-08-….txt:94);
  • 每条的字段:problem(题面)、answer(标准答案)、solution(详细解法,本章不用)、 levelsubjectunique_id(text/24-ch03-08-….txt:137text/24-ch03-08-….txt:161text/24-ch03-08-….txt:173text/24-ch03-08-….txt:179)。

5.7 全量跑出来的数(3.9 节)——全书的基线成绩

模型设备准确率题量耗时
baseCPU/CUDA/MPS30%100.4 min(M4)
官方推理版CPU/CUDA90%107 min(M4)
官方推理版MPS80%10
baseCUDA15.3%50013.3 min(H100)
官方推理版CUDA50.8%500185.4 min(H100)

出处:text/25-ch03-09-….txt:512text/25-ch03-09-….txt:627(表 3.1)、text/25-ch03-09-….txt:636(耗时对照)。

这一对数字是整本书的锚:15.3% → 50.8%,代价是 13.3 分钟 → 185.4 分钟(慢 14 倍)。 后面每一章的改进,都应该回来和这个基线比。

批量推理的加速(text/25-ch03-09-….txt:649):batch=128 时,base 从 13.3 min → 3.3 min, 推理版从 185.4 min → 14.6 min(H100)。

5.8 提示词模板:书里最反直觉的一段(text/25-ch03-09-….txt:130text/25-ch03-09-….txt:154)

书用的模板是「You are a helpful math assistant… \boxed{ANSWER}… Question:…」。 然后作者交代了几个实测结果,每一条都会改变读者的判断:

改动base 模型官方推理模型
完全不用提示模板准确率 +50%−40%
Question: 换成 Problem:(MATH-500 的标准写法)+20%−30%

作者对 Problem: 那 20% 的解释很直白:很可能是因为它更贴近被记住的训练数据 ——「假定 MATH-500 测试集本来就在训练语料里」(text/25-ch03-09-….txt:142)。 他还在 3.4 节写过一条通则:「凡是模型训练时互联网上有的东西,都可以假定进过训练数据」 (text/20-ch03-04-….txt:25)。

这一段在拆解里必须重点讲,它同时说明三件事: ① 小模型对措辞极其敏感;② 基准分数可能被数据污染抬高;③ 同一个改动对两个模型方向相反。

同一段里作者还澄清了一个可能的误读(text/25-ch03-09-….txt:148): 准确率随提示词变化,不代表我们的抽取方法不可靠 —— 模型也可能只是单纯答错了, 换个 LLM 来抽答案救不了。

5.9 第 3 章留下的伏笔

  • 「验证器 → 第 6 章的可验证奖励」明说了两次(text/16-ch03-….txt:41text/22-ch03-06-….txt:13);
  • 「同样的思路可以扩展到代码领域,但本书没做 —— 因为执行代码要额外搭安全沙箱」(text/25-ch03-09-….txt:702);
  • 「小模型对提示词敏感,下一章引入更多提示变体后会更明显」(text/25-ch03-09-….txt:154)。

第三批:第 4 章(不改权重,靠采样和投票)

六、第 4 章:推理时扩展(text/2734,共 77k 字符)

这一章是全书第一次真正「提高分数」。 书开门见山:本章两个方法 都让 base 模型的准确率翻了一倍以上(text/27-ch04-….txt:29)。

6.1 两条路的分岔(4.1 节)

书把提升推理能力分成两条(text/28-ch04-01-….txt:13text/28-ch04-01-….txt:16):

训练时扩展推理时扩展(本章)
花算力在哪训练阶段回答阶段,模型已经训完了
动权重吗不动
怎么花——多吐 token「想久一点」、采多个答案、反复精修

书还就地解释了「compute(算力)」这个词:训练或运行模型所需的计算资源(text/28-ch04-01-….txt:21)。 图 4.2 的曲线明说是照着 OpenAI 那篇 o1 介绍文章画的(text/28-ch04-01-….txt:28, https://openai.com/index/learning-to-reason-with-llms/)。

书特意提醒不要把两条路对立起来(text/28-ch04-01-….txt:34):真实的 LLM 是两者兼用 —— 重训练 + 加推理算力。

6.2 本书选的三招(text/28-ch04-01-….txt:52text/28-ch04-01-….txt:58)

#方法本质在哪一章
1思维链提示让它把过程写出来(变长)4.3
2自洽采样(self-consistency)采多个答案,选出现次数最多的(变多)4.6
3自我精修(self-refinement)模型反复审视并改进自己的答案第 5 章

作者交代了选择的依据(text/28-ch04-01-….txt:88),这段很有分量: 他「在几千次实验里评了十几种推理时扩展技术」,选这三个是因为三条同时成立: ① 在这个模型上确实涨分明显;② 代表推理时扩展的主要范式;③ 简单到能从零手写。 它们覆盖了两大模式:把回答变长(1、3)和生成多个回答(2)。

书还给了一处业界背书(text/28-ch04-01-….txt:94):并行采样在生产系统里也广泛使用,举例 Claude 4 (引 https://www.anthropic.com/news/claude-4)。

6.3 全章走查用的那道题(书自己选的)

「$3x-9$ 的一半等于 $x+37$,求 $x$。」正确答案 83。

这道题贯穿 4.2–4.6,每加一招就重跑一次,结果一路在变,是绝佳的主走查:

做法模型答出对不对出处
贪心解码(第 3 章那套)\boxed{20}text/29-ch04-02-….txt:185text/29-ch04-02-….txt:191
+ 思维链提示(prompt 尾巴加 \n\nExplain step by step.)\boxed{83}text/30-ch04-03-….txt:75text/30-ch04-03-….txt:88
+ 温度采样(T=1.1)\boxed{$x = \frac{90}{7}$}text/31-ch04-04-….txt:1026
+ 温度 0.5 + top-p 0.8\boxed{18}text/32-ch04-05-….txt:653
+ 自洽投票(5 次采样)83、22、54、83、61 → 投票选 83text/33-ch04-06-….txt:200text/33-ch04-06-….txt:204
自洽 + 思维链(5 次)5 次全是 83text/33-ch04-06-….txt:346

这条走查值千金 —— 它把「采样本身不提分、投票才提分」这个反直觉的点用实例说清了。

6.4 思维链提示(4.3 节)

  • 做法朴素到令人意外:在提示词后面加一句「Explain step by step.」 就完了(text/30-ch04-03-….txt:33);
  • 出处:最早的 zero-shot 思维链论文用的是「Let's think step by step.」 (https://arxiv.org/abs/2205.11916,text/30-ch04-03-….txt:26)。作者说自己换成 「Explain step by step.」只是因为在他这一章的实验里效果好;
  • 为什么有效,书给了两条(text/30-ch04-03-….txt:125text/30-ch04-03-….txt:131): ① 把步骤写出来,模型就多了自我纠正的机会; ② 分步解题贴合训练数据的写法 —— 大型数学、逻辑数据集里本来就是详细解法;
  • 书自己泼的冷水(text/30-ch04-03-….txt:100text/30-ch04-03-….txt:137):不是所有题都受益。简单题上思维链可能反而变差, 因为模型可能生成错误的解释把自己带偏 —— 这就是前面提过的「overthinking」;
  • 一句很到位的总结(text/30-ch04-03-….txt:143):思维链不给模型新知识,它只改变模型使用已有知识的方式;
  • 一条重要限制(text/30-ch04-03-….txt:106):已经训好的推理模型(比如 Qwen3 官方推理版)本来就会写解释, 对这类提示不需要也不受益

6.5 温度(4.4 节,27.6k 字符,全章最重的一节)

书把「模型怎么挑下一个词」拆成了四小步,每一步都有具体数字,这是最好的走查素材:

prompt = "The capital of Germany is"
│ ① 编码
▼ token IDs = [785, 6722, 315, 9856, 374]
│ ② 前向,取最后一个位置的分数(这些原始分数叫 logits)
▼ 形状 [1, 151936];画出 19800–19899 这 100 个的分布,取值约 −8 到 20
│ ③ 除以温度 T ← 这就是温度的全部动作
▼ T<1 → 分布更尖(更自信);T>1 → 分布更平(更敢冒险)
│ ④ softmax 归一成概率(全部落在 0–1 之间、加起来等于 1)
▼ T=5.0 时 " Berlin" 只有 0.0003;T=0.5 时涨到 0.3398
│ ⑤ torch.multinomial 按概率抽一个
▼ T=5.0 抽出来是 token 65094 = " mistress"(完全不着调)

出处:text/31-ch04-04-….txt:128(token IDs)、text/31-ch04-04-….txt:149(形状)、text/31-ch04-04-….txt:178(argmax → 19846 = " Berlin")、 text/31-ch04-04-….txt:254(logits 取值范围)、text/31-ch04-04-….txt:298(return logits / temperature —— 温度的实现只有这一行)、 text/31-ch04-04-….txt:538+text/31-ch04-04-….txt:570(0.0003 / 0.3398)、text/31-ch04-04-….txt:697(抽到 " mistress")。

「温度」这个词的来历,书专门开了个小边栏(text/31-ch04-04-….txt:430):来自物理学 —— 温度控制一个系统里有多少随机性和运动。

1000 次采样的分布对照(text/31-ch04-04-….txt:847text/31-ch04-04-….txt:854text/31-ch04-04-….txt:889text/31-ch04-04-….txt:895),这是本节最有说服力的一组数:

T = 5.0(太高)T = 0.35
'}' 2 次、' </' 2 次、' represent' 2 次、' Inf' 2 次、'()*' 2 次、' beside' 2 次、' Kob' 2 次……' Berlin' 435 次' ______' 209 次、' ____' 169 次、' __' 158 次、' _____' 18 次、' Munich' 3 次、' Hamburg' 3 次
1000 次里没有任何一个 token 出现超过 2 次,而且全是废话435/1000 ≈ 42% 抽到 Berlin

书对这组数的两条解读特别好(text/31-ch04-04-….txt:907): ① ' Munich'' Hamburg' 也是德国大城市,并非完全不相关; ② 那一堆下划线 ' ____' 很可能是因为模型见过「The capital of Germany is ____」这种填空题格式

书自己提出并回答的疑问(text/31-ch04-04-….txt:913text/31-ch04-04-….txt:925):既然 Berlin 是对的, 为什么要故意让它有时答错?答:随机性让模型去探索别的可能; 在推理任务里,这种多样性正是自洽投票赖以工作的前提。

边栏「多项式采样」给的三行对照(text/31-ch04-04-….txt:783text/31-ch04-04-….txt:806)可以直接搬: 若 Berlin 0.70、Munich 0.20、Hamburg 0.10 —— 贪心解码永远返回 Berlin; 多项式采样则按权重抽,抽很多次的话 Berlin 出现 70%、Munich 20%、Hamburg 10%。

实用取值建议(边栏,text/31-ch04-04-….txt:1039):0.0 = 贪心解码;0.3–0.8 是「想要一点多样性又不至于跑飞」的常用区间; 更高的值适合创作和广泛搜索,但在需要唯一正确答案的任务上会伤可靠性

一处工程坑,书写了(text/31-ch04-04-….txt:709):torch.multinomialcuda/mps 上结果可能不同, 采样数一大甚至会崩(作者在 PyTorch 2.9 上两种设备都遇到过),所以代码里强制 .cpu()

6.6 top-p / 核采样(4.5 节)

它解决什么问题:光有温度,会「误伤」——偶尔抽到跟上下文完全无关的怪 token(text/32-ch04-05-….txt:7)。 top-p 的定义(书就地给了,text/32-ch04-05-….txt:185):「保留累计概率不超过 p 的那一小撮 token」; 它还有个名字叫 nucleus sampling(核采样)(text/32-ch04-05-….txt:13)。

四步走查(书用一个只有 10 个词的玩具词表演示,数全在):

toy_logits = [-0.7, -3.0, 0.1, -1.2, 2.0, -1.0, -0.5, -2.0, 0.3, 1.5]
│ softmax
▼ ① 按概率从高到低排序
│ ② 算累计和 → [0.4538, 0.7290, 0.8119, 0.8798, 0.9170, …, 1.0000]
│ ③ 卡 top_p = 0.8
│ 朴素写法 cumsum <= 0.8 → 只留 2 个(0.7290 未过线,0.8119 过线)
│ 通行写法 (cumsum - sorted) < 0.8 → 留 3 个(**把跨过门槛的那一个也留下**)
│ ④ 其余置零 → [0,0,0,0, 0.4538, 0,0,0, 0.0829, 0.2752]
▼ 重新归一 → [0,0,0,0, 0.5589, 0,0,0, 0.1021, 0.3390]

出处:text/32-ch04-05-….txt:81(玩具 logits)、text/32-ch04-05-….txt:213(累计和)、text/32-ch04-05-….txt:215(留 2 个)、 text/32-ch04-05-….txt:237+text/32-ch04-05-….txt:246(通行写法留 3 个)、text/32-ch04-05-….txt:346(置零后)、text/32-ch04-05-….txt:374(归一后)。

为什么必须重新归一,书讲了(text/32-ch04-05-….txt:32):砍掉低概率 token 之后,剩下的加起来不等于 1 了, 不归一就没法正确采样。

加了 top-p 之后,真实词表上的效果(接 6.5 的那组数,text/32-ch04-05-….txt:554text/32-ch04-05-….txt:556):

T=0.35,无 top-pT=0.35 + top_p=0.8
Berlin 435、______ 209、____ 169、__ 158、_____ 18、Munich 3、Hamburg 3Berlin 534、______ 249、____ 217 —— Munich 和 Hamburg 被滤掉了

边栏对照 top-k(text/32-ch04-05-….txt:666text/32-ch04-05-….txt:696):top-k 固定保留分数最高的 k 个; top-p 保留的个数是浮动的,取决于累计概率。 作者说 top-k 更好实现、他在前作里讲过,但 top-p 近年更流行

6.7 自洽采样(4.6 节)—— 本章的落点

它是什么:说穿了就是简单多数投票(书自己用了 "Despite the fancy name" 这个说法,text/33-ch04-06-….txt:19)。 出处:Google Research 论文《Self-Consistency Improves Chain-of-Thought Reasoning in Language Models》 (https://arxiv.org/abs/2203.11171,text/33-ch04-06-….txt:19text/31-ch04-04-….txt:32)。

三步(text/33-ch04-06-….txt:132text/33-ch04-06-….txt:138): ① 用 T>0 + top-p 采多个答案 → ② 从每个答案里抽出 \boxed{} 里的短答案 → ③ 选出现次数最多的那个。

书自己指出的两个缺口:

  • 不处理平局:多个答案频次相同就返回 None(text/33-ch04-06-….txt:241)。 书明说第 5 章会做一个「置信度打分」来当平局裁判 ——这是通向第 5 章的伏笔;
  • 依赖能抽出来的短答案:对没有数值型/短答案的问题很难套用(text/33-ch04-06-….txt:611)。

6.8 表 4.1 —— 全书最有价值的一张表(text/33-ch04-06-….txt:358text/33-ch04-06-….txt:542)

全部 500 道 MATH-500,在 DGX Spark 的 CUDA GPU 上跑的。 温度和 top-p 都用 0.9。

#方法模型准确率耗时
1基线,贪心解码base15.2%10.1 min
2基线,贪心解码官方推理版48.2%182.1 min
3思维链提示base40.6%84.5 min
4温度 + top-pbase17.8%30.7 min
5温度top-p + 自洽 n=3base29.6%97.6 min
6温度top-p + 自洽 n=5base27.8%116.8 min
7温度top-p + 自洽 n=10base31.6%300.4 min
8温度top-p + 思维链base33.4%129.2 min
9自洽 n=3 + 温度top-p + 思维链base42.2%211.6 min
10自洽 n=5 + 温度top-p + 思维链base48.0%452.9 min
11自洽 n=10 + 温度top-p + 思维链base52.0%862.6 min
12自洽 n=3 + 温度top-p + 思维链官方推理版55.2%544.4 min

书对这张表的逐行解读(text/33-ch04-06-….txt:563text/33-ch04-06-….txt:605),有四条是判断,不是描述:

  1. 第 4 行只涨 2.6 个点是「预期之内」 —— 因为温度和 top-p 本身不是推理时扩展技术, 它们只是控制采样多样性的旋钮(text/33-ch04-06-….txt:575)。这一条极其重要,否则读者会以为「调温度能提分」; 耗时从 10.1 → 30.7 min 也不是采样代码的开销,而是模型有时会生成更长的回答;
  2. 第 5–7 行:n 从 3 加到 10,准确率 29.6% → 31.6%,几乎没赚到(text/33-ch04-06-….txt:581), 而且 n=5(27.8%)竟然比 n=3(29.6%)还低 —— 非单调;
  3. 第 8 行是反例:采样把思维链弄坏了(33.4% vs 第 3 行的 40.6%,text/33-ch04-06-….txt:587);
  4. 最狠的一条:第 11 行 52.0% 用了 862.6 分钟 —— 书用了「a staggering」形容(text/33-ch04-06-….txt:587)。 对照第 1 行:准确率 15.2% → 52.0%(涨 3.4 倍),耗时 10.1 → 862.6 分钟(涨 85 倍)。

第 12 行说明推理模型也能吃到自洽的红利:48.2% → 55.2%(text/33-ch04-06-….txt:599)。

书的总结句(text/33-ch04-06-….txt:605):这张表「漂亮地呈现了推理时扩展的权衡:拿更多算力换更高准确率」。 并补了一句实务(text/33-ch04-06-….txt:593):有多张 GPU 的话,自洽的多个样本可以并行—— 总算力不变,但墙钟时间能压下来。

6.9 ⚠️ 三处需要在拆解里处理的「书自己的不一致」

这些是我通读时发现的,不是书里承认的。写正文时要么绕开、要么如实说明。

  1. 基线数字对不上:第 3 章表 3.1 是 base 15.3% / 推理版 50.8%(H100); 第 4 章表 4.1 第 1、2 行是 base 15.2% / 推理版 48.2%(DGX Spark)。 硬件不同、PyTorch 版本可能不同 —— 书没有明说这两组数为什么不一致。 拆解里若要用「基线」,必须指明是哪一张表的哪一行,不能混着用;
  2. 清单 4.8 和清单 4.16 对「什么算贪心」写法相反: 清单 4.8 是 if temperature is None or temperature == 1.0: argmax(text/31-ch04-04-….txt:968), 清单 4.16 是 if temperature is None or temperature == 0.0: argmax(text/32-ch04-05-….txt:596)。 而正文和边栏的口径是「0.0 = 贪心解码」「1.0 = 不做改变」(text/31-ch04-04-….txt:311text/31-ch04-04-….txt:1039)。 清单 4.8 那一行与正文口径矛盾,看起来是 MEAP 阶段的笔误。 拆解里讲温度时应按正文口径(0 = 贪心),并且不要照搬清单 4.8 的那行判断;
  3. 正文里两处把清单 4.17 写成了「listing 4.15 / 4.16」(text/33-ch04-06-….txt:51text/33-ch04-06-….txt:126), 而清单标题写的是 4.17。编号笔误,不影响内容,但引用时要按标题的编号。

6.10 第 4 章留下的伏笔

  • 平局怎么办 → 第 5 章的置信度打分(text/33-ch04-06-….txt:241);
  • 自洽只适用于「有短答案」的题 → 第 5 章的自我精修更通用(text/33-ch04-06-….txt:611text/33-ch04-06-….txt:617);
  • 「思维链和自洽可以组合,后面一节再说」(text/31-ch04-04-….txt:19)—— 在 4.6 节兑现了。

第四批:第 5 章(让模型改自己的作业 + 打分的三种办法)

七、第 5 章:自我精修与打分(text/3544,共 72k 字符)

这一章表面上讲「自我精修」,实际上一大半篇幅在讲「怎么给一个答案打分」。 作者自己交代了原因(text/36-ch05-01-….txt:75):对数概率这套东西 下一章实现强化学习时会再用到,而且是作为训练目标的一部分,不再只是推理时的打分信号。 —— 这是全书最关键的一处伏笔:第 5 章是第 6 章的数学准备课。

7.1 为什么还要再来一种推理时方法(5.1 节)

书对自洽(第 4 章)的评价是正面的(text/36-ch05-01-….txt:32):它虽然简单,但常常带来很大提升, 所以在「准确率优先于延迟」的场景里已是常见选择;书举了两个当代例子: DeepSeekMath-V2Google Gemini 3 的 Deep Think 模式

但自洽有一个硬伤(text/36-ch05-01-….txt:38):多数投票要求答案短到能互相比较。 自我精修没有这个限制 —— 它只改进一个答案。

7.2 三种打分器,书全都做了(这一章的骨架)

#打分器依据什么在哪一节
1规则式打分(heuristic)答案能不能干净地抽出来 + 有多短5.3
2平均对数概率(avg logprob)模型自己对这个答案有多大把握5.4–5.6
3(提到但没做)LLM 当裁判另一个模型来打分附录 F.5

书特意说明为什么不用第 3 章的验证器来打分(text/38-ch05-03-….txt:118): 打分的场景里我们假定不知道正确答案;验证器只在「拿现成测试集做评测」时才用得上。 —— 这一条区分极其重要,不讲清楚读者会问「有验证器还打什么分」。

7.3 规则式打分器(5.3 节)

score = 抽取奖励 + 简短奖励:

  • \boxed{} → +2.0;没有但至少含一个数 → +1.0;都没有 → +0.0(text/38-ch05-03-….txt:52text/38-ch05-03-….txt:81);
  • 简短奖励 = 1.5 * exp(-字符数 / 500) —— 指数衰减,最多加 1.5 分(text/38-ch05-03-….txt:80); 短答案接近 1.5,超过 1000 字符的只剩 0.2 分以下(text/38-ch05-03-….txt:176)。

作者的口径很清楚(text/38-ch05-03-….txt:105):绝对数值不重要,相对比例才重要。 2.0 > 1.0 是为了让「干净的答案框」优于「只抽得出一个数」;简短项上限 1.5, 只够用来打破平局,不足以压过抽取奖励

跑出来的数(text/38-ch05-03-….txt:207text/38-ch05-03-….txt:220):第 5.2 节那两个都答对 83 的回答 —— 长的(1419 字符 / 534 token)得 2.088,短的(533 字符 / 231 token)得 2.517,短的胜出

书对「短就是好吗」的态度很诚实(text/37-ch05-02-….txt:205text/37-ch05-02-….txt:217): 短的不一定更好;两个都对时哪个更好取决于人的偏好(清晰度、有用性、中间步骤对不对); 「给中间步骤打分」仍是活跃的研究方向,而过程奖励模型(process reward models)在实践中并不总是更好。 但有一件事是确定的:同等质量下短的更便宜

7.4 从概率到对数概率(5.4–5.5 节,全书数学门槛最高的两节)

它要回答的问题:怎么量化「模型对这个答案有多大把握」? 思路(text/39-ch05-04-….txt:7):每个位置上模型都会把概率分给所有可能的下一个词; 如果一个答案里的词始终拿到高概率,说明这个答案很合模型自己的口味。

书用来演示的一对句子(全节贯穿):

A: "The capital of Germany is Berlin" vs B: "The capital of Germany is Bridge"

完整走查,数全是书里印出来的:

逐位置的下一个词概率(bfloat16):
A [6.1512e-05, 4.6484e-01, 1.6724e-02, 7.3828e-01, 1.6895e-01]
B [6.1512e-05, 4.6484e-01, 1.6724e-02, 7.3828e-01, 2.9802e-07]
前四个完全一样 ↑ 只差最后一个词
│ 全部相乘 = 联合概率

A 5.9372e-08 ( = 0.000000059372 )
B 1.0481e-13 ( = 0.00000000000010481 )
│ 改成:各自取对数再相加

A 逐词 [-9.6875, -0.7695, -4.0938, -0.3008, -1.7812] → 合计 -16.6250
B 逐词 [-9.6875, -0.7695, -4.0938, -0.3008, -15.0000] → 合计 -29.8750

出处:text/39-ch05-04-….txt:385+text/39-ch05-04-….txt:387(A 的概率与联合概率)、text/39-ch05-04-….txt:416+text/39-ch05-04-….txt:418(B 的)、 text/40-ch05-05-….txt:401text/40-ch05-05-….txt:403(A 的对数概率)、text/40-ch05-05-….txt:432text/40-ch05-05-….txt:434(B 的)。

为什么非要换成对数(书给了两条,text/40-ch05-05-….txt:220): ① 很小的概率映射到对数之后落在一个正常的数值范围里; ② 连乘会迅速趋近于 0(下溢:数字小到计算机直接当成 0,信息就丢了,text/40-ch05-05-….txt:278), 取对数把乘法变成加法,长序列也稳。

一条读者必须建立的直觉(text/40-ch05-05-….txt:195):概率是越大越好; 对数概率是越接近 0 越好 —— 0 对应概率 1,非常负的对应极小的概率。

书自己给的代码级口径(text/40-ch05-05-….txt:318text/40-ch05-05-….txt:331):从概率版改到对数版只要改两处: torch.softmaxtorch.log_softmax,torch.prodtorch.sum。 并且专门加了警告:混搭(softmax+sum 或 log_softmax+prod)语法上跑得通,数学上是错的

5.6 节的打分器在此基础上再改两处(text/41-ch05-06-….txt:26): ① 把提示词部分排除掉,只算答案那几个 token; ② 求平均而不是求和 —— 否则长答案天然吃亏,不同长度的答案没法公平比较。

跑出来的数(text/41-ch05-06-….txt:216text/41-ch05-06-….txt:197):同样的问句下, " The capital of Germany is Berlin."-0.2041, " The capital of Germany is Bridge."-3.8906

7.5 三处「必须原样保留的辨析」(书写得很好,我们不该删)

  1. 「打分」和「生成」不是一回事(边栏,text/39-ch05-04-….txt:227text/39-ch05-04-….txt:257): 打分时序列已经存在,我们只是回头去问模型「如果是你写,这几个词各有多大概率」; 不做采样、模型不选任何词。这是回溯性的打分,不是生成步骤;
  2. 贪心解码并不保证得到整体概率最高的序列(text/39-ch05-04-….txt:239): 某一步看着次优的词,可能通向后面一串概率很高的词;反过来,局部最优可能把模型带进 低概率的死胡同。而且就算真找到了全局概率最高的序列,也不保证它是对的—— 只能说明「模型自己最偏爱它」(text/39-ch05-04-….txt:245);
  3. 概率 vs 似然(边栏,text/39-ch05-04-….txt:464text/39-ch05-04-….txt:476):统计学里, 概率是「给定模型,预测数据」,似然是「给定数据,评价模型」。 书的裁定:LLM 的下一个词概率技术上是概率(来自归一化的 softmax); 而那个连乘的结果常被叫做 sequence likelihood(序列似然)。 作者给了自己的一篇科普文链接(https://sebastianraschka.com/faq/docs/probability-vs-likelihood.html)。

还有一条反复出现的警告,必须写进拆解(text/39-ch05-04-….txt:86text/39-ch05-04-….txt:443;text/41-ch05-06-….txt:234):

模型的「有把握」不等于「对」。 高分只说明这个答案很符合它学到的模式, 不代表它是真的、对的、有用的。所以对数概率打分「只是众多有用信号之一, 不是万无一失的裁判」——它可能偏爱自信的错误答案

7.6 自我精修本体(5.7–5.8 节)

三步,每一步都只是拿不同的提示词调一次同一个模型(text/42-ch05-07-….txt:39):

① 出初稿:正常提问 → 模型答 "\boxed{18}"(错,正确是 83)
② 批评:把「原题 + 初稿」塞进一个「你是个严谨的审稿人,找出逻辑错误、
缺失步骤或算术错误……写一段短评和要点式修正方案(120 词以内)」的提示词
→ 模型写出批评,并且**批评里直接把正确解法算了出来**:
「…把方程改成 (1/2)(3x-9)=x+37 → 两边乘 2 → 3x-9=2x+74 → x-9=74 → x=83」
③ 精修:把「原题 + 初稿 + 批评」塞进「照批评修订,末尾给出 \boxed{答案}」的提示词
→ 模型答 "\boxed{83}" ✅

出处:text/42-ch05-07-….txt:90(初稿 18)、text/42-ch05-07-….txt:106text/42-ch05-07-….txt:116(批评提示词原文)、 text/42-ch05-07-….txt:140text/42-ch05-07-….txt:147(批评内容)、text/42-ch05-07-….txt:170text/42-ch05-07-….txt:178(精修提示词)、text/42-ch05-07-….txt:202text/42-ch05-07-….txt:204(最终 83)。

作者在这里下了一个非常有价值的判断(text/42-ch05-07-….txt:154): 批评本身可以是错的,但仍然有用 —— 只要它整体上把模型推向更好的修订。

⚠️ 注意:书在这一句里引用的原话对不上。 正文说批评里写了 「The question itself is incomplete」并指出这句不成立; 但前面印出来的批评原文里没有这句,写的是 「The question seems to have a logical error in its setup」。 MEAP 阶段的对不上号。 拆解里要么改述作者的观点(批评可以有错但仍有用)、 不引那句原话,要么明说书里这处引文与它印出来的输出不符。

5.8 节把它做成循环(text/43-ch05-08-….txt:57text/43-ch05-08-….txt:177),多了两样东西: ① iterations 参数,可以反复精修; ② 可插拔的 score_fn —— 只有当新答案的分数不低于旧的,才接受这次修订(text/43-ch05-08-….txt:168)。

书自己承认这个把关会失灵(text/43-ch05-08-….txt:26text/43-ch05-08-….txt:39):自我精修跑多轮反而可能变差; 打分器不一定能改善结果,用哪个得在 MATH-500 上试出来。

两轮循环的实测输出(text/43-ch05-08-….txt:286text/43-ch05-08-….txt:297),这是绝好的走查素材:

修订前修订后分数变化
110(错)83(对)-0.855 → -0.226(变好,接受)
28383-0.226 → -1.320(变差)

书的解读(text/43-ch05-08-….txt:303):第二轮分数变差了没关系,因为正确答案已经拿到了

7.7 表 5.1 —— 又一张必须完整搬过来的表(text/43-ch05-08-….txt:336text/43-ch05-08-….txt:552)

全部 500 道 MATH-500,DGX Spark 的 CUDA GPU。

#方法打分器轮数模型准确率耗时
1基线(第 3 章)base15.2%10.1 min
2自我精修1base25.0%84.8 min
3自我精修2base22.0%165.4 min
4自我精修规则式1base21.6%84.7 min
5自我精修规则式2base20.8%151.4 min
6自我精修平均对数概率1base21.4%85.3 min
7自我精修平均对数概率2base22.0%165.3 min
8基线(第 3 章)推理版48.2%182.1 min
9自我精修1推理版56.6%498.8 min
10自我精修规则式1推理版57.8%498.6 min
11自我精修平均对数概率1推理版48.4%499.7 min

这张表里有四条反直觉的结论,书都明说了:

  1. 在 base 模型上,「不打分」反而最好(25.0%,第 2 行 > 第 4、6 行)。 书的解释(text/43-ch05-08-….txt:567):两种打分器有时会让错答案盖掉本来正确的初稿;
  2. 多跑一轮通常更差(第 3 行 22.0% < 第 2 行 25.0%);
  3. 平均对数概率打分在两个模型上都最差(第 6、7、11 行)。 书给的原因是这一章最深刻的一句(text/43-ch05-08-….txt:585): 平均对数概率衡量的是「这个答案在模型看来有多自然、多像它预期的样子」, 而不是它对不对;所以它会偏爱流畅、熟悉、语法干净但语义错误的答案 —— 「对数概率这个标准会无意中选中自信的错误」。相比之下,规则式打分只管格式和结构;
  4. base 模型加思维链之后,自我精修反而救不回来(text/43-ch05-08-….txt:573,书说结果未列出)。

书自己做的横向对比(text/43-ch05-08-….txt:597):在这个模型这个任务上,自我精修不如自洽。 自洽之所以仍被广泛使用,是因为它简单却真的管用

7.8 书出版时点上的最新进展(可直接当外部坐标)

text/43-ch05-08-….txt:609:2025 年 11 月,DeepSeek 团队用 DeepSeekMath-V2 证明了 「用第二个 LLM 来做自我精修」可以非常成功,在多个数学竞赛上拿到金牌级成绩。 做法是:专门训练一个「批评模型」,同时把基础模型也训成更擅长在自我精修情境下解题。 —— 书强调:本章的自我精修完全没有额外训练,这是差别所在。

这一条要在拆解里点明,它是「本章方法的天花板在哪」的最好注脚。


第五批:第 6 章(全书的落点 —— 用强化学习真的训出一个推理模型)

八、第 6 章:RLVR + GRPO(text/4558,共 76k 字符)

这一章是全书的落点。 前五章全部是为它铺路:第 2 章给模型和生成函数, 第 3 章给验证器(这里原样变成奖励函数),第 4 章给温度/top-p(这里用来产生多个 rollout), 第 5 章给对数概率(这里进入损失函数)。 结果:base 模型 MATH-500 准确率 15.2% → 47.4%,只训了 50 步。

8.1 RLHF vs RLVR(6.1 节)—— 必须讲清的一对

RLHF(2022,InstructGPT 论文 https://arxiv.org/abs/2203.02155,text/46-ch06-01-….txt:100): 书说它是把 GPT-3 变成 ChatGPT 那个模型的关键成分,也正是 2022 年 LLM 大火的原因(text/46-ch06-01-….txt:106)。 两步(text/46-ch06-01-….txt:156):

① 训一个奖励模型:让 LLM 对同一提示生成多个回答 → 人类标注员从好到坏排序
→ 用一个统计偏好模型把「两两比较」转成相对质量分
→ 训出一个模型,给任何回答打一个单一数值分
② 用这个奖励模型给 LLM 的回答打分(好答案 +2、坏答案 -2 这种),据此更新 LLM

书给的具体例子(text/46-ch06-01-….txt:136text/46-ch06-01-….txt:144)可以直接搬: 问「买笔记本电脑编程和日常用,该考虑什么」—— 回答 A 只是罗列「CPU、内存、存储、显卡、屏幕、续航、键盘、接口、散热、价格」; 回答 B 给了具体值「至少 16GB 内存、至少 256GB 固态硬盘……显卡只有你想在本地训小模型才重要」。 人类标注员多半更喜欢 B,因为它更具体、更贴合提问里说的用途。

RLVR(可验证奖励的强化学习): 把「训出来的奖励模型」换成确定性的验证器(text/46-ch06-01-….txt:217)—— 数学题就是「最终答案对不对」:对得 1,错得 0(text/46-ch06-01-….txt:223)。 于是 RLHF 的两步塌缩成一个训练循环(text/46-ch06-01-….txt:229)。

书列的 RLVR 四条好处 + 一条代价(text/46-ch06-01-….txt:272text/46-ch06-01-….txt:284):

内容
好处 ①不用训、不用养一个额外的奖励模型 —— 那东西大小和成本常常和基础模型相当
好处 ②确定性、可复现:同一个输出永远得同一个分,没有人类标注的噪声和不一致
好处 ③天然可扩展:只要有参考答案,任意多的模型输出都能自动算奖励,不用再花人力
代价要求存在可靠的验证信号,因此被限制在数学、代码这类领域

为什么 RLVR 火了(text/46-ch06-01-….txt:248):DeepSeek-R1(2025)证明了不靠人类偏好数据、 不靠学出来的奖励模型,也能拿到很强的推理性能。 R1 用的可验证奖励包括数学答案正确性(和第 3 章的验证器同类)和代码能否编译执行

书自己划的边界(text/46-ch06-01-….txt:260):代码执行本书不做 —— 要在隔离沙箱里编译运行模型生成的代码,不让它碰宿主系统、私有文件和外部服务, 这比解数学题复杂得多。但书强调:两者的 RLVR 训练算法是一样的(text/46-ch06-01-….txt:266)。

还有一条对 R1 的重要观察(text/46-ch06-01-….txt:51):RL 通常在指令微调之后做; 但 DeepSeek 团队证明了推理 RL 可以直接加在预训练 base 模型上,跳过指令微调和偏好微调。 这样训出来的模型推理准确率一般弱一些,但推理行为清晰而稳健; 更重要的是,它避免了多个训练阶段的效果混在一起,能把提升明确归因到推理训练本身(text/46-ch06-01-….txt:57)。 —— 这正是本书从 base model 起步的理论依据,和第 2 章那句话对上了。

8.2 术语的两层:RLVR 是什么、GRPO 是什么(6.2 节)

书划得很干净(text/47-ch06-02-….txt:32):

RLVR 决定「有什么学习信号可用」,GRPO 决定「这个信号怎么拿去改权重」。

  • policy(策略):书明说这是 RL 的行话,在这里就是指我们要训的那个 LLM(text/47-ch06-02-….txt:20);
  • GRPO = group relative policy optimization(组相对策略优化),出自 DeepSeek 的 DeepSeekMath 论文(https://arxiv.org/abs/2402.03300,text/47-ch06-02-….txt:51);
  • 为什么不用 PPO(text/47-ch06-02-….txt:45text/47-ch06-02-….txt:51):PPO 是 RLHF 里流行的策略梯度算法,原则上也能用在 RLVR; 但 DeepSeek 团队选了更简单的 GRPO,因为 GRPO 不需要一个单独的价值模型来估计价值函数, 而是从一组采样回答的相互比较里取学习信号,计算开销小得多;
  • 作者给了自己写的 PPO/GRPO 对照文章链接 (https://magazine.sebastianraschka.com/p/the-state-of-llm-reasoning-model-training,text/47-ch06-02-….txt:57)。

本章做的事和 DeepSeek-R1-Zero 相似,但规模小得多(text/47-ch06-02-….txt:7)—— 书直说:同等规模的完整训练要几十万美元的 GPU 算力

8.3 厨师比方(6.2.1 节)—— 用不用要斟酌

书用「开小餐馆的厨师」把 GRPO 的每个部件对应了一遍(text/47-ch06-02-….txt:102text/47-ch06-02-….txt:132):

厨师世界GRPO 术语
每天一份顾客点单(比如千层面)prompt
同一道菜试几种做法rollouts
做出来的几盘菜completions
顾客吃完整盘才给反馈,不是边做边评reward(只看最终结果,不评中间步骤)
几盘菜互相比高下组相对优势(advantages)
每盘菜有多像自己一贯的风格logprobs
据此微调做菜风格策略梯度损失
翻出老菜谱作参照参考模型
「别改太猛,吓跑老顾客」的惩罚KL 项
两者合成一个总的调整决定总损失
真的改了做菜风格梯度更新权重

注意:书自己在比方之后立刻承认「即便有这个比方,GRPO 的部件还是很多」(text/47-ch06-02-….txt:137)。 按行文第 7 条,比方是一次性脚手架 —— 拆解里可以借它建立结构感, 但说完必须当场改口用正式说法,之后不许再用「厨师」「菜谱」指代任何机制

8.4 训练数据:12000 道题,和评测集严格不重叠(6.4 节)

原始 MATH 数据集 约 12500 道
├── MATH-500(500 道)→ 第 3 章起一直用作评测集
└── 12000 道 → 本章训练用,与上面 500 道**完全不重叠**

出处:text/49-ch06-04-….txt:35(图 6.11 说明)、text/49-ch06-04-….txt:13(「防止数据泄漏,保证训练和评测干净分离」)。 构造方式作者放在 https://github.com/rasbt/math_full_minus_math500(text/49-ch06-04-….txt:26)。

一条有意思的取舍(text/49-ch06-04-….txt:159):数据集里其实带着完整解法(solution 字段), 但书故意不用它来评中间推理步骤 —— 那样会「不必要地限制模型,并且有过拟合到某一种解法和风格的风险」; 书希望模型更自由地探索解空间

8.5 六个阶段的完整走查(这是拆解这一章的主走查,书自己把数全给了)

书为了讲清流程,故意假造了四个 rollout(text/50-ch06-05-….txt:180text/50-ch06-05-….txt:185), 正确答案是 83:

① 四个 rollout(假设模型产出的四个回答)
r1: \boxed{83}
r2: The correct answer is \boxed{83}
r3: The final answer is 83
r4: We get \boxed{38}

② 算奖励(用第 3 章的验证器,且 fallback=None → 必须有 \boxed{} 才算)
r1 → 1.0 r2 → 1.0 r3 → 0.0 (答案对但没装框!) r4 → 0.0 (框里的数错)
rewards = [1., 1., 0., 0.]

③ 算优势 A_i = (r_i − 平均) / (标准差 + ε),ε=1e-4 防除零
advantages = [0.8659, 0.8659, −0.8659, −0.8659]

④ 算每个 rollout 的**序列级**对数概率(把答案各 token 的对数概率**求和**)
r1: −7.9243 r2: −20.1546 r3: −16.6130 r4: −23.3677

⑤ 策略梯度损失 = −( 优势 × 对数概率 ) 的平均
pg_loss = tensor(−2.5764)

⑥ 反向传播 → 优化器更新权重

出处:text/51-ch06-06-….txt:89text/51-ch06-06-….txt:99(四个奖励)、text/52-ch06-07-….txt:73(奖励与优势两个向量)、 text/53-ch06-08-….txt:377text/53-ch06-08-….txt:387(四个对数概率)、text/54-ch06-09-….txt:48text/54-ch06-09-….txt:63(损失张量)。

这条走查的每一步都有可讲的「为什么」:

  • ② 里 r3 得 0 分是全章最好的教学点(text/51-ch06-06-….txt:20text/51-ch06-06-….txt:53): 答案 83 是对的,但没写成 \boxed{}。书故意fallback=None, 于是奖励函数隐含了一条格式约束 —— 「只有又对又按规定格式写,才给 1.0」。 这就是「怎么让模型学会守格式」的答案:不用额外规则,把它编进奖励里;
  • ③ 为什么要把奖励变成优势(text/52-ch06-07-….txt:100text/52-ch06-07-….txt:106): 优势值直接缩放梯度。优势为正 → 梯度提高产生这个 rollout 的那些动作的可能性; 为负 → 压低;接近零的几乎不起作用。 「GR(组相对)」这三个字母的意思就在这里:同一个提示采多个回答,互相比出学习信号(text/52-ch06-07-….txt:92);
  • ④ 为什么这里用「求和」而不是第 5 章的「求平均」(text/53-ch06-08-….txt:140text/53-ch06-08-….txt:152): GRPO 给的是「整条回答一个奖励、一个优势」,所以对数概率也应当反映 「产生整条序列」的可能性,而不是每 token 的平均。 平均会做长度归一化 —— 那对打分比较有用,但会无意中重新缩放学习信号, 让长短回答对更新的贡献不均; 副作用书也讲了(text/53-ch06-08-….txt:186):求和的对数概率随长度线性变负, 所以两个一样好的答案里,优化会隐含地偏爱短的那个 —— 「除非更长值得更高的奖励,否则求和的对数概率会鼓励模型早点停」;
  • ⑤ 那个负号是怎么回事(text/54-ch06-09-….txt:20text/54-ch06-09-….txt:81): 策略梯度本来是个最大化问题(想让高优势的 rollout 的对数概率更高), 而 PyTorch 的优化器定义为最小化损失,所以乘 −1 翻个号。 书还专门开边栏用 f(x)=3 举例说明这个等价(text/54-ch06-09-….txt:94text/54-ch06-09-….txt:112);
  • .detach() 为什么必要(text/54-ch06-09-….txt:69):优势在策略更新里当作固定的学习信号, 不让梯度回流到优势的计算过程,只更新影响对数概率的那些参数

还有一处实测的对照(text/53-ch06-08-….txt:128text/53-ch06-08-….txt:180text/53-ch06-08-….txt:243): 同一个回答的平均对数概率是 -0.0613, 乘以答案 token 数得到序列级 -16.2390, 而直接用求和版函数算是 -16.2998 —— 书解释差异来自浮点行为和舍入。

8.6 一个「什么都没发生」的真实步骤(6.10 节末尾)

书在真实数据上跑了一次 compute_grpo_loss(text/55-ch06-10-….txt:177text/55-ch06-10-….txt:187),结果是:

rewards: [0.0, 0.0] 两个 rollout 都答错
advantages: [0.0, 0.0] 都一样 → 相对优势全为零
loss: -0.0 梯度为零,权重一动不动
samples: 第一个只生成了 4 个 token(" 14<|endoftext|>")
第二个撞到 256 token 上限还没答完

这个「零梯度」例子极有价值 —— 它把「组相对」的含义演示到了骨子里: 一组回答如果好坏一致,GRPO 就学不到任何东西。 (书还把它出成了练习 6.2:强行让所有奖励相同,验证损失为零,并问「为什么这个行为是可取的」。)

8.7 训练循环(6.11 节)—— 八步里只有一步是新的

书说得很清楚(text/56-ch06-11-….txt:20):这八步几乎全是标准 PyTorch 训练循环, 唯一专属推理模型的是第 4 步:损失由 GRPO 算,而不是常见的分类损失

① 建优化器(AdamW,lr=1e-5)
② 逐步迭代
③ optimizer.zero_grad()
④ ★ stats = compute_grpo_loss(...) ← 唯一特别的一步
⑤ loss.backward()
├ clip_grad_norm_(..., 1.0) 截断过大的梯度,稳住训练
⑥ optimizer.step()
⑦ 记录:平均奖励、平均回答长度、损失 → 写 CSV
⑧ 每 N 步存一次检查点(被 Ctrl-C 打断也会存)

书里给的超参和它们的理由(text/56-ch06-11-….txt:277text/56-ch06-11-….txt:301),这些数字都有参照物:

参数书给的理由
steps50(数据集有 12000 条)纯粹为了教学场景下的合理耗时;但「已经足够拿到好结果」
num_rollouts4省资源;显存不够可降到 2
max_new_tokens512同上;测试可降到 64
temperature / top_p0.8 / 0.9常用区间 0.7–0.9,兼顾多样性和连贯
lr1e-5「在合理范围里,效果不错」
checkpoint_every5一个检查点约 1.5 GB;实际长跑建议设 50 或 100

真实的训练日志(书跑到第 7 步手动中断,text/56-ch06-11-….txt:314text/56-ch06-11-….txt:322):

[Step 1/50] loss=-0.0000 reward_avg=0.000 avg_resp_len=88.0
[Step 2/50] loss=-0.0000 reward_avg=0.000 avg_resp_len=7.5
[Step 3/50] loss=-0.0000 reward_avg=0.000 avg_resp_len=6.5
[Step 4/50] loss=0.0909 reward_avg=0.250 avg_resp_len=6.5
[Step 5/50] loss=1.1001 reward_avg=0.500 avg_resp_len=300.5

书对这份日志的解读是本节最要紧的部分(text/56-ch06-11-….txt:328text/56-ch06-11-….txt:340):

  • 损失和奖励上下跳是正常的,RL 训练就这样;
  • reward_avg 怎么读:num_rollouts=4 时,0.5 = 四个里对了两个,0.25 = 对了一个,0 = 全错;
  • 损失值本身不要过度解读:reward_avg=0 的步骤损失接近零, 是因为所有 rollout 拿到相同奖励 → 组相对优势消失 → 几乎没有梯度信号; 损失数值大只是反映 rollout 之间差距大,GRPO 类目标在训练初期本来就这样;
  • 该看的是两条趋势(text/56-ch06-11-….txt:352text/56-ch06-11-….txt:355):① 多步平均下来奖励应当上升;② 推理准确率应当提升。

⚠️ 书自己的一处不一致:正文说「第 3 步(上面输出的第 4 行)损失数值较大」, 但输出里第 3 步 loss 是 -0.0000,第 4 行对应的是 Step 4(0.0909)。 MEAP 阶段的行号/步号错位。 拆解里引这段时按实际输出说,不要照抄这句。

一条工程现实(text/56-ch06-11-….txt:373):RL 很吃资源,因为每一步都要生成多条(可能很长的)rollout, 所以书里的实现不支持批处理;有多张 GPU 的读者可以用补充材料里带批处理和多卡的版本。

8.8 表 6.1 —— 全书的最终成绩单(text/57-ch06-12-….txt:102text/57-ch06-12-….txt:211)

全 500 道 MATH-500,评测时允许生成 2048 token。

#方法训练步训练时每条上限rollout 数准确率平均回答长度
1base 模型(第 3 章)15.2%78.85 token
2官方推理模型(第 3 章)48.2%1369.79 token
3本章 GRPO50256443.2%560.22
4本章 GRPO50512445.6%579.81
5本章 GRPO50512847.4%586.11

这张表要在拆解里当成全书的高潮来讲,四条解读书都写了:

  1. 50 步就把 15.2% 推到了 47.4%,已经很接近官方推理模型的 48.2%(text/57-ch06-12-….txt:238);
  2. 平均回答长度从 78.85 涨到 586 —— 模型确实学会了「多写中间步骤」; 但仍明显短于官方推理模型的 1369.79,书说这是训练时限制了 token 长度的预期结果(text/57-ch06-12-….txt:226);
  3. 训练时的 token 上限是一条隐形的塑形力(text/57-ch06-12-….txt:220):上限 512 就等于告诉模型 「512 token 之内必须把 \boxed{} 交出来,否则拿不到奖励」。 书引 DeepSeek-R1 团队的观察:回答长度会随训练自然变长,因为模型开始写中间解释; 所以想要最高准确率,就不该把长度卡太死;
  4. 只训 50 步不是偷懒,是发现(text/57-ch06-12-….txt:250): 「50 步似乎已足以在 base 模型里解锁推理行为」;而且 训更久不一定更好,甚至可能掉准确率,因为原始 GRPO 公式在长跑中可能不稳定 —— 这句直接把读者推向第 7 章。

读者不想自己训也行(text/57-ch06-12-….txt:47):作者上传了检查点, download_qwen3_grpo_checkpoints(grpo_type="no_kl", step="00050"); 50 到 9000 步的更多检查点在 https://huggingface.co/rasbt/qwen3-from-scratch-grpo-checkpoints/tree/main/grpo_original_no_kl(text/57-ch06-12-….txt:262)。

8.9 本章故意留下的三个洞(全部由第 7 章补)

  1. 没有 KL 项(text/47-ch06-02-….txt:162text/55-ch06-10-….txt:135)。书的态度值得原样保留: KL 项是原始 GRPO 公式的一部分,但并非严格必要; 很多 LLM 开发者在实践中就是不用它 —— 既简化实现,有时还能提升效果; 书还说「GRPO 在数学题上常被报告为去掉 KL 项时表现更好」;
  2. 没有裁剪的策略比率(clipped policy ratios,text/47-ch06-02-….txt:181);
  3. 长跑不稳定(text/57-ch06-12-….txt:250)。

还有一条书顺带记下的负面结果,很有价值(text/51-ch06-06-….txt:111): DeepSeek-R1 团队试过用过程奖励模型给中间解题步骤打分,失败了; 他们的结论是「只用最终答案正确性做奖励更好,不要中间奖励」。 —— 这条和第 5 章说的「过程奖励模型实践中不总是更好」互相印证,应当在拆解里连起来讲。


第六批:第 7 章(训练跑久了会崩,以及三种补救)

九、第 7 章:GRPO 的诊断与修补(text/5966,共 66k 字符)

这一章的定位很特别:它是全书唯一一章「以失败为主线」的内容。 第 6 章的胜利是「50 步 15.2% → 47.4%」,第 7 章开门就说: 跑久了会掉,而且「代码是对的也会不稳」(text/59-ch07-….txt:42)。

书自己给的两条免责声明,必须原样保留:

  1. text/60-ch07-01-….txt:20:本章的例子来自真实实验,但要谨慎解读 —— 要下强结论,每个实验都得重复多次取平均,因为采样和优化里的随机性会让不同次运行差别明显。 「不过这些例子足以说明主要思想和相关的权衡」;
  2. text/60-ch07-01-….txt:33:这一章可以跳过 —— 第 8 章不依赖它。

9.1 该盯哪些指标(7.2–7.3 节)

书把指标分两层。第一层(基础四项):

指标该看什么书的原话要点
loss只当健全性检查「和预训练相比,损失值本身信息量小」;应大致平稳,大的尖峰值得担心(text/61-ch07-02-….txt:331)
reward_avg应当上升但升到 1.00 反而意味着训练信号消失了 —— 全对就没什么可学,该早停省资源(text/61-ch07-02-….txt:337)
avg_response_len初期应当变长变长应当伴随准确率提升
eval_acc(MATH-500)最终目标默认在训练中算,因为会大幅拖慢;可训练后用第 3 章的脚本单独跑(text/61-ch07-02-….txt:368)

第一次长跑(500 步,无 KL、无裁剪)的结论(text/61-ch07-02-….txt:349): 前约五十步涨得快,之后收益递减,而且训到 400 步附近奖励和准确率明显下滑。 书排除了一种解释:不可能是「后面的题更难」—— 因为评测准确率是每 50 步在同一批 500 道 MATH-500 上算的。 所以问题出在算法本身:原始 GRPO 在长跑中不稳定

第二层(进阶三项):

① 优势的均值(text/62-ch07-03-….txt:110):按 GRPO 的算法它恒为 0,所以 「这个指标主要是健全性检查」——要是它漂离 0,说明代码有 bug 或归一化出了问题

② 优势的标准差(text/62-ch07-03-….txt:116)—— 这才是有信息量的:

标准差含义
接近 1梯度信号缩放得好,更新通常稳定
很小学习信号在消失,常见于奖励塌缩
很大更新过于尖锐,可能把训练搞崩
等于 0极端情形:所有奖励相同 → 优势全同 → 策略梯度为零 → 权重完全不更新

书给的两组实测(text/62-ch07-03-….txt:103text/62-ch07-03-….txt:104text/62-ch07-03-….txt:144text/62-ch07-03-….txt:145): [1,1,0,0] → 优势 [0.8659, 0.8659, -0.8659, -0.8659],均值 0.0000、标准差 0.9998; [0,0,0,0] → 优势 [0,0,0,0],均值 0.0000、标准差 0.0000(全 1 也一样)。

③ 熵(entropy)—— 这一节值得单独拆一小节讲:

书就地下的定义(text/62-ch07-03-….txt:175):熵衡量模型生成下一个词时有多不确定。 熵高 = 概率摊在很多词上,倾向探索;熵低 = 概率集中在一个词上,模型越来越确定, 也可能是训练塌缩的信号(模型不再探索,反复吐同样的东西)。

怎么算(text/62-ch07-03-….txt:250text/62-ch07-03-….txt:298):把每个词的概率乘以它的对数概率,再求和取负。 书用一个 7 个词的玩具词表演示(text/62-ch07-03-….txt:201text/62-ch07-03-….txt:203text/62-ch07-03-….txt:315text/62-ch07-03-….txt:316):

logits = [0.6667, -2.0000, 1.3333, -0.0000, -0.6667, 2.0000, -1.3333]
│ log_softmax
▼ logprobs = [-2.0442, -4.7109, -1.3776, -2.7109, -3.3776, -0.7109, -4.0442]
│ argmax → 5 号词,它的对数概率是 -0.7109
│ softmax
▼ probs = [0.1295, 0.0090, 0.2522, 0.0665, 0.0341, 0.4912, 0.0175]
│ entropy = −Σ(p × log p)
▼ 1.3700

书给的经验刻度(text/62-ch07-03-….txt:275text/62-ch07-03-….txt:281),可直接搬:

含义
约 0–0.5一个词独占,模型高度自信、近乎确定性
约 1–2概率分摊在一小撮词上,稳定训练时的典型状态
远大于 2(上限是 log(词表大小),这里 log(7)=1.9459)概率摊得很开,模型高度不确定、接近随机

书还就地讲了一个换算小知识(text/62-ch07-03-….txt:328):torch.exp()torch.log() 的逆, 所以只有对数概率时,用 torch.exp(logprobs) 就能还原概率。

长跑里熵的实际走势(text/62-ch07-03-….txt:521text/62-ch07-03-….txt:527):早期熵低而平(模型行为偏确定性); 约 200 步之后熵明显上升。书的解读很谨慎: 把熵、上升的平均奖励、未消失的优势标准差三者放在一起看, 判断这是「还算健康的探索」而不是塌缩; 并且这与 MATH-500 准确率停留在 30%–40% 一致 ——「不算好,但也没接近零」。

本节的总结句值得原样用(text/62-ch07-03-….txt:533): 「每个指标只讲故事的一部分,它们必须放在一起、放在上下文里看才有用。

9.2 补救一:裁剪策略比率(7.4 节)

它解决什么问题:限制单次更新里模型能变多少,防止一步迈太大把训练搞崩。

它是什么(text/63-ch07-04-….txt:32):比较同一个回答在权重更新前后的序列对数概率。 书给的口语化说法很好:「如果 LLM 之前给这个答案某个可能性,调完权重之后它觉得这个答案的可能性变了多少?

完整走查(书自己造的数,四个 rollout):

new_logps = [ -7.9243, -20.1546, -16.6130, -23.3677] (更新后)
old_logps = [-10.9243, -20.3546, -14.6130, -23.3677] (更新前)
│ log_ratio = new − old ;ratio = exp(log_ratio)
▼ ratio = [20.0855, 1.2214, 0.1353, 1.0000]
│ clip_eps = 10.0 → clamp 到 [1−10, 1+10] = [-9, 11]
▼ clipped_ratio = [11.0000, 1.2214, 0.1353, 1.0000] ← 只有第一个被削
│ 用 min/max 取更保守的那个(优势为正取 min,为负取 max)
▼ 裁剪后的策略梯度损失 = -2.3998 (原来是 -2.5764)
平均策略比率 = 5.6106

出处:text/63-ch07-04-….txt:128text/63-ch07-04-….txt:133(两组对数概率)、text/63-ch07-04-….txt:161text/63-ch07-04-….txt:162(两个 ratio 向量)、 text/63-ch07-04-….txt:251(两个损失值)、text/63-ch07-04-….txt:257(平均比率 5.6106)。

几处要讲透的点:

  • ratio = 1.0 就是「完全没变」(text/63-ch07-04-….txt:168);
  • clip_eps 取多少差别很大(text/63-ch07-04-….txt:180):DeepSeek-R1 用 10,属于非常弱的裁剪; 而 RLHF 里的 PPO 常用 0.1,属于激进裁剪,每步策略变化小得多;
  • 不裁剪会怎样(text/63-ch07-04-….txt:174):新模型若突然给某个 rollout 高得多或低得多的概率, 原始 ratio 会变得极大或极小,把优势项放大,导致一次巨大的梯度步,可能毁掉训练;
  • eps 就是希腊字母 epsilon,数学里常用来表示一个小的正量(边栏,text/63-ch07-04-….txt:199);
  • 数学推导明说超出本章范围,指向 PPO 原论文 https://arxiv.org/pdf/1707.06347(text/63-ch07-04-….txt:109)。

DeepSeek-R1 的真实做法 vs 本书的简化(text/63-ch07-04-….txt:311text/63-ch07-04-….txt:375),这段很有价值:

DeepSeek-R1本书
复制当前模型当参考策略
用参考策略一次性生成 8192 个回答的大池子只采 8 个 rollout
把这批固定的 rollout 切成 16 个小批依次训不切小批,重新采一批再来一次(默认再来一次)
走完后更新参考模型

书自己承认:「资源受限,我们做不到那么多 rollout 和小批,所以用一个更便宜的近似」。

效果(图 7.13,text/63-ch07-04-….txt:413):比之前的几次训练明显更稳 —— 400 步附近那次平均奖励和评测准确率的下跌不见了

9.3 补救二:KL 项(7.5 节)—— 书演示了一次彻底的崩溃

先给一个身份澄清,很重要(边栏,text/64-ch07-05-….txt:20):

熟悉强化学习的读者会认出来,到目前为止我们实现的东西本质上就是 「带组归一化优势的 REINFORCE」。

KL 是什么(text/64-ch07-05-….txt:35):Kullback–Leibler 散度,衡量当前策略偏离参考策略有多远, 参考策略通常就是训练开始时的原始模型

和裁剪比率的分工,书划得很清楚(text/64-ch07-05-….txt:41): 裁剪比率管「每一步之间」的变化;KL 项管「整条训练轨迹上的长期漂移」。

参考模型怎么维护也不同(text/64-ch07-05-….txt:78):裁剪比率那一节里,参考模型每轮都换; KL 项的参考模型是训练之初的原始模型,固定不动或者很少更换 (DeepSeek-R1 是每 400 步换一次)。

实现(text/64-ch07-05-….txt:156text/64-ch07-05-….txt:161):kl_loss = kl_coeff * mean(logps − ref_logps), 然后 loss = pg_loss + kl_loss代价(text/64-ch07-05-….txt:186):要在内存里多留一份原始模型的副本取值(text/64-ch07-05-….txt:192):实践中 kl_coeff 通常是 0.001 到 0.05 之间的小值。

训练结果:彻底崩掉(图 7.16,text/64-ch07-05-….txt:267text/64-ch07-05-….txt:285)——这是全书最精彩的一段失败分析:

前 50 步:准确率从略高于 15% 涨到约 40% ← 和第 6 章一致
约 200 步:奖励塌缩到 0
之后: 损失爆炸、评测准确率掉向 0%
人工检查生成结果:模型开始吐乱码,例如 "framework.raises Self profess(import"

书给的两条原因,每一条都是好教材:

  1. KL 项用的是「求和」的对数概率,所以序列越长,KL 值天然越大 —— 这会无意中鼓励模型写超长输出(观察到的回答长度确实在涨),进而搞崩训练;
  2. 奖励塌缩到 0 之后,KL 项成了唯一还在提供梯度的东西。 奖励全零 → 优势全零 → 策略梯度不再贡献任何梯度; 而 KL 项还活着,开始主导更新,把模型推向更高的熵、接近均匀的词分布 —— 这同时解释了「输出越来越随机」和「准确率掉到 0%」。

书给的四条补救(text/64-ch07-05-….txt:304text/64-ch07-05-….txt:340):

办法书的评价
kl_coeff 从 0.02 降到 0.001作者试过,不够
对序列对数概率做长度归一化(除以生成 token 数)能减少「靠写长来累积更大绝对差」的动机
重要性采样加权的 KL(DeepSeek-V3.2 提的):kl_coeff * mean(exp(new−old) * (new−ref))那个权重 exp(new_logps − old_logps) 修正了「rollout 是旧策略生成的」这件事:当前策略很少会产出的样本被降权,会产出的被升权
加一个小的格式奖励,防止优势塌缩到零引向 7.6 节

但书最终的建议是(text/64-ch07-05-….txt:291text/64-ch07-05-….txt:346):

对数学数据,常见的推荐是干脆不要 KL 项。 多个近期工作报告去掉或减弱 KL 项后稳定性/性能更好:Dr. GRPO、Olmo 3、DeepSeek-V3.2。 顺带还简化了代码、省了显存(不用再留一份参考模型)。

—— 这和第 6 章那句「很多 LLM 开发者实践中就不用它」前后呼应,可以连起来讲。

9.4 补救三:格式奖励与 <think> 标签(7.6 节)

<think> 是什么(text/65-ch07-06-….txt:32):DeepSeek-R1、Qwen3 这类推理模型用的特殊标记, 它们就是普通的文本 token,只是用来标出中间推理的起止 —— 推理写在 <think>…</think> 里面,最终答案写在外面。书说这整套做法是可选的, 好处是让输出结构显式化,把推理和最终结果分开

一个很具体的技术走查(text/65-ch07-06-….txt:70text/65-ch07-06-….txt:111),值得搬:

base 模型的分词器 encode("<think>") → [13708, 766, 29]
三个 token! 说明 <think> 根本不在它的词表里
│ 好在现代分词器/嵌入层常留有「空占位 ID」备微调时用
│ tokenizer_base._tok.add_special_tokens([... "<think>", "</think>"])

再 encode("<think>") → [151667] 单个 token ✓
encode("</think>") → [151668]

为什么 base 模型「装得下」这两个新 token(text/65-ch07-06-….txt:117): 它的词表大小是 151936,支持 0–151935 的 ID,151667/151668 本来就在范围内。 (另一条路是直接用 Qwen3 推理版的分词器 —— 它原生就支持这两个 token,text/65-ch07-06-….txt:130。)

格式奖励函数(text/65-ch07-06-….txt:198text/65-ch07-06-….txt:210):生成部分里 <think> 的位置早于 </think> 就给 1.0, 否则 0.0(找不到就抛 ValueError → 0.0)。 总奖励变成 rlvr_reward + format_reward_weight * format_reward(text/65-ch07-06-….txt:300)。

结果又是一次「先好后坏」(图 7.19–7.20,text/65-ch07-06-….txt:440text/65-ch07-06-….txt:481):

  • 准确率先涨后跌,而平均奖励基本不变;准确率下滑与回答变短相关;
  • 书给的诊断:模型光靠守 <think> 格式就拿到了太多奖励 (看 format_reward_avg 曲线),于是对答案正确性用力不够;
  • 两条改法(text/65-ch07-06-….txt:481):① 把 format_reward_weight 从 1.0 降到 0.1; ② 把格式奖励改成有条件的 —— 只有答案也对时才给(当前实现是不管对错都给)。 这被出成了练习 7.2,参考结果在附录 B。

一条必须讲的前提(text/65-ch07-06-….txt:369text/65-ch07-06-….txt:375): 不能拿 base 模型来练这个 —— 它从没见过 <think> token,结果会很差。 正确做法是先用含 <think> 的数据做预训练或指令微调(指令微调是第 8 章的内容), 所以本节直接用已经认识 <think> 的「推理版」模型来训

⚠️ 书里有一处编辑残留:text/65-ch07-06-….txt:557 的练习 7.2 正文中间夹了一句 「Note on `loss` and `kl_loss`」,与上下文无关,明显是 MEAP 阶段的粘贴事故。引用时跳过。

还有一个「日志上的假象」值得讲(边栏,text/65-ch07-06-….txt:494text/65-ch07-06-….txt:529): 7.6 节那次运行 loss 全程为 0、kl_loss 也全程为 0。原因是默认设置 --kl_coeff 0.0(关掉 KL)且 --inner_epochs 1(只做一次内部更新, 拿模型和同一步的自己比)—— 策略比率从 1 开始,而优势被归一化成均值 0, 于是这个标量损失算出来就是 0。 书的判词很直接:「这里的 loss = 0 是默认设置造成的计算产物,这个标量损失没有信息量」; 该盯的是 reward_avgformat_reward_avgadv_stdentropy_avg

9.5 GRPO 之后的十几种改法(7.6.3 节)—— 只列不讲

书自己说「限于篇幅,详细解释、代码和实验结果超出本章范围」,给了补充材料链接(text/65-ch07-06-….txt:655)。 但这份清单本身很有价值,是读者出门会撞见的名字,拆解里应当保留(至少列出来):

来源改法
DAPO零梯度信号过滤;主动采样;从序列级损失改成 token 级损失;去掉 KL;clip higher
Dr. GRPO去掉 KL;不做标准差归一化
DeepSeek-V3.2按领域调 KL 强度(数学取零);重加权 KL;离策略序列掩码;保留 top-p/top-k 的采样掩码;保留原始 GRPO 的优势归一化
VERL截断重要性采样
GDPO聚合前按奖励做组内归一化
GSPO序列级重要性采样与裁剪
CISPO裁剪重要性采样权重,而不是裁剪 token 更新

书对这份清单的态度也要保留(text/65-ch07-06-….txt:590text/65-ch07-06-….txt:596): 「除了学习率、最大回答长度、提示格式这些基础设置,可调的旋钮和改法近乎无穷, 把其中一个或少数几个改法研究透,对一个小团队来说可能就是一整个月甚至一整年的课题。 算法会不断变,重要的是理解底层的基本原理,这样才能看懂并欣赏这些改进。」


第七批:第 8 章(蒸馏 —— 便宜得多的另一条路)+ 全书收尾

十、第 8 章:蒸馏(text/6778,共 72k 字符)

这一章是全书的第二条训练路线,也是「实用性」最强的一章。 一句话:不自己摸索,直接抄一个更强的模型的作业。

10.1 为什么需要它(8.1 节)

动机是规模(text/68-ch08-01-….txt:13):最强的推理模型大到没法直接用 —— DeepSeek-R1 有 6710 亿参数;这种规模开发贵、部署贵,远超绝大多数从业者能在本地跑的东西。 DeepSeek-R1 团队自己就是这么做的:拿 6710 亿的模型当老师,蒸馏出一批小模型(text/68-ch08-01-….txt:19)。

书给的成本对照,是全书最有冲击力的一组数(text/68-ch08-01-….txt:50,同一台 DGX Spark):

耗时内存
第 6 章的 GRPO 训练12 小时70 GB
本章的蒸馏训练3 小时15 GB

而且书直接引 DeepSeek-R1 论文的结论(text/68-ch08-01-….txt:31text/68-ch08-01-….txt:68): 对小模型来说,蒸馏出来的效果可能比单纯用强化学习训还好。

10.2 硬蒸馏 vs 软蒸馏(这是第 1 章那个术语陷阱的兑现)

硬蒸馏(本章用的)软蒸馏
学什么老师生成的文本,把老师的 token 当作目标老师在整个词表上的概率分布,用 KL 散度去逼近
需要老师给什么只要文本要 logits 或对数概率
本质就是拿合成数据做监督微调(SFT)经典知识蒸馏

出处:text/68-ch08-01-….txt:37(定义)、text/68-ch08-01-….txt:56(「硬蒸馏就是在合成数据上做监督微调」)、text/68-ch08-01-….txt:74(只需要文本)。 还有第三种:两者结合,即计算机视觉里的经典知识蒸馏,源头是论文 《Distilling the Knowledge in a Neural Network》(text/68-ch08-01-….txt:86)。

为什么 LLM 圈几乎只用硬蒸馏,书给了三条(text/68-ch08-01-….txt:92text/68-ch08-01-….txt:113):

  1. 拿不到完整 logits —— ChatGPT、Claude 这类闭源系统会给你生成的文本, 但一般不给整个词表的分布;
  2. 就算拿得到也麻烦:师生通常得用同一个分词器词表才对得齐, 所以这条路基本只在同一个模型家族内部好走;
  3. 存不起:长推理轨迹的完整 token 分布存储和使用都贵得多,而存纯文本又便宜又简单。

⚠️ 书里专门加了一条法务警告(text/68-ch08-01-….txt:105),拆解里必须保留: 把生成的文本拿去做蒸馏,可能受各家服务条款限制(书点名 OpenAI 和 Anthropic 的 ToS), 实践中用之前应当仔细审阅。

10.3 数据集怎么来的(8.2–8.3 节)

还是那 12000 道 MATH 训练题(与 MATH-500 不重叠,和第 6、7 章同一批)
│ 全部喂给老师:DeepSeek-R1(6710 亿参数),通过 OpenRouter 调用
▼ 收集它的回答当作训练目标
总花费:约 50 美元的 API 费用
产出文件 107 MB(所以放 Hugging Face 而不是 GitHub —— 超过 GitHub 100MB 限制)

出处:text/69-ch08-02-….txt:51(老师是谁、走 OpenRouter)、text/69-ch08-02-….txt:57(50 美元)、 text/70-ch08-03-….txt:20(107 MB / HF 地址)。

RLVR 和蒸馏的监督信号差别,书画得很清楚(text/69-ch08-02-….txt:32):

拿什么和什么比
RLVR(第 6–7 章)学生的最终答案 vs 标准答案 → 验证器给出奖励
蒸馏(本章)学生生成的 token vs 老师生成的 token → 老师的回答直接就是目标序列

一条实务优势(text/69-ch08-02-….txt:45):蒸馏可以提前把老师数据全部生成好,再开始训学生。

数据条目的四个字段(text/70-ch08-03-….txt:148): problem(题面)、gtruth_answer(标准答案)、 message_thinking(老师的推理轨迹)message_content(老师的最终答案)。 后两个合成一条训练目标(text/70-ch08-03-….txt:176):<think>{推理轨迹}</think>\n\n{最终答案}

老师有多强?书当场量了(text/70-ch08-03-….txt:245text/70-ch08-03-….txt:251):

模型MATH-500 准确率
DeepSeek-R1(老师)91.2%(在那 12000 道训练题上是 90.6%,即 10871/12000)
Qwen3 0.6B 官方推理版50.8%
Qwen3 0.6B base(学生的起点)15.2%

这组对照必须搬进拆解 —— 它一眼说明了「老师和学生差多远」。

10.4 数据预处理里最有信息量的一步:长度过滤(8.4.3 节)

12000 条都成功 token 化,一条没跳过
│ 统计长度
▼ 平均 2946 token;最短 236;**最长 42005**(!)
│ 书的判词:平均 2946「对推理模型来说是典型的」,但 42005 「非常离谱」
│ 过滤:只留 ≤ 2048 token 的
▼ 剩 6695 条,**砍掉了 5305 条(44%)**
│ 重新统计
▼ 平均降到 1180 token
│ 固定随机种子 123 打乱,切 25 条当验证集
▼ 训练集 6670 条 + 验证集 25 条

出处:text/71-ch08-04-….txt:425text/71-ch08-04-….txt:427(三个长度)、text/71-ch08-04-….txt:476text/71-ch08-04-….txt:478(过滤前后)、 text/71-ch08-04-….txt:504text/71-ch08-04-….txt:506(过滤后长度)、text/71-ch08-04-….txt:545text/71-ch08-04-….txt:546(切分结果)。

书的判断(text/71-ch08-04-….txt:439):「实践中,控制序列长度是让蒸馏能在较小硬件上跑起来的主要手段之一。」 验证集故意只留 25 条,免得拖慢训练循环(text/71-ch08-04-….txt:552)。

还有两处值得讲的机制:

  • 聊天模板(text/71-ch08-04-….txt:85):用 Qwen3 推理版的分词器并开 apply_chat_template=True, 会自动包上 <|im_start|>user … <|im_end|> / <|im_start|>assistant; 但答案部分必须关掉包裹(chat_wrapped=False),否则提示和答案会各带一个 assistant 起始标记,拼起来就错了(text/71-ch08-04-….txt:122);
  • epoch 的就地解释(边栏,text/71-ch08-04-….txt:33):一个 epoch = 完整过一遍训练集。 训 3 个 epoch,模型就把每条样本看 3 遍,通常每遍顺序不同。 书还说明为什么蒸馏要预先 token 化一次并复用(text/71-ch08-04-….txt:20): RLVR 里每条样本采一次就丢,蒸馏要反复过很多遍,所以一次性处理好更划算 —— 「这也是老师数据一旦收好,蒸馏比 RLVR 更好迭代的原因之一」。

10.5 损失函数:交叉熵,并且和第 5 章接上了(8.6 节)

书在这里把第 5 章的对数概率和这一章的交叉熵接成一条线,这段很值得照搬:

交叉熵 = 那些 token 对数概率取负、再求平均。

书拿第 5 章那个 "The capital of Germany is Berlin" 的例子当场算给你看(text/73-ch08-06-….txt:32): 序列对数概率是 -16.6250 → 取负是 16.6250 → 除以 5 个待预测目标3.325交叉熵也是 3.325。「和对数概率一样,越接近 0 越好」。

实测验证(text/73-ch08-06-….txt:83text/73-ch08-06-….txt:150text/73-ch08-06-….txt:228):在同一条训练样本上, 用第 6 章的 sequence_logprob 算出的平均负对数概率是 1.68; 用 PyTorch 内置的 cross_entropy 算出来也是 1.68书的结论:「cross_entropy 是在用更优化的方式做同一件核心计算」,所以训练时用内置的。

「只在答案上算损失」的理由(text/73-ch08-06-….txt:162): 提示词是给定的上下文,蒸馏里模型的任务不是学会重建输入指令, 而是在这个指令的条件下产出目标答案 —— 所以拿提示当上下文,但不因提示部分的预测罚它。

训练损失 vs 验证损失,书讲了为什么该看后者(text/73-ch08-06-….txt:326text/73-ch08-06-….txt:332): 训练损失在当前正在被优化的样本上算,噪声大,会随样本顺序和刚刚的参数更新波动; 验证损失在留出集上算、不更新权重,是更干净的泛化信号,所以更可靠。

10.6 训练循环与真实曲线(8.7–8.8 节)

循环和第 6 章几乎一样,两点不同(text/74-ch08-07-….txt:20): ① 要多次重复过同一批数据(epoch);② 损失换成交叉熵而不是 GRPO 目标。

小规模演示的输出(10 条样本、2 个 epoch,text/74-ch08-07-….txt:283text/74-ch08-07-….txt:288):

[Epoch 1/2 Step 5/20] train_loss=0.9648 val_loss=0.9082
[Epoch 1/2 Step 10/20] train_loss=0.9844 val_loss=0.8871
[Epoch 2/2 Step 15/20] train_loss=0.8008 val_loss=0.8707
[Epoch 2/2 Step 20/20] train_loss=0.7148 val_loss=0.8586

真实的完整训练(text/75-ch08-08-….txt:56):3 个 epoch、lr=1e-5、max_seq_len=2048、 开 --use_think_tokens、梯度裁剪 1.0 → DGX Spark 上约 3 小时 5 分钟,约 15.02 GB 显存。 书特意解释了为什么比 RLVR 便宜:「大部分昂贵的工作已经挪到一次性的老师数据生成那一步了。」

曲线的解读(text/75-ch08-08-….txt:155):验证损失先陡降后走平 —— 模型确实在从蒸馏数据里学,但继续训收益递减

10.7 表 8.1 —— 蒸馏的最终成绩(text/75-ch08-08-….txt:208text/75-ch08-08-….txt:330)

#方法epoch最终验证损失MATH-500 准确率
1base Qwen3 0.6B(第 3 章)15.2%
2官方推理 Qwen3 0.6B(第 3 章)48.2%
3蒸馏自 DeepSeek-R110.543630.6%
4蒸馏自 DeepSeek-R120.534932.4%
5蒸馏自 DeepSeek-R130.534333.6%
6蒸馏自 Qwen3 235B-A22B10.404345.0%
7蒸馏自 Qwen3 235B-A22B20.396343.8%
8蒸馏自 Qwen3 235B-A22B30.394844.2%

这张表里有一个全书最反直觉、也最有用的发现(text/75-ch08-08-….txt:345):

更强的老师不一定教出更好的学生。 DeepSeek-R1(MATH-500 91.2%)当老师,学生只到 33.6%; Qwen3 235B-A22B(MATH-500 92.4%)当老师,学生到 45.0%书给的解释:老师和学生同属一个模型家族 —— 分词器、提示词惯例、整体回答风格更对齐,老师给的目标对小 Qwen3 学生来说更好模仿

其余三条解读:

  1. 45.0% 已经很接近官方推理参考模型的 48.2%(text/75-ch08-08-….txt:351); 而书顺带点破:那个「官方推理模型」本身也是蒸馏出来的, 只是用了一个大得多的、由 Qwen3 235B-A22B 生成的数据集 ——「这就是蒸馏的核心权衡」;
  2. 别指望学生追平老师(text/75-ch08-08-….txt:357):老师是 92.4% / 91.2%,学生 45%; 「但我们仍然能在一个便宜得多的模型里,回收老师推理行为中有用的一部分」;
  3. 还能更高:换更大的学生(比如 4B 或 30B 的 Qwen3 而不是 0.6B),但训练成本会涨(text/75-ch08-08-….txt:357)。

注意 epoch 2、3 在 Qwen3 老师那一组是掉分的(45.0% → 43.8% → 44.2%), 而验证损失一直在降 —— 验证损失和目标任务准确率并不总是同向,这一点书没有点破, 但表里摆着,拆解里应当自己作为判断块点出来

10.8 未来方向(8.9 节)—— 书自己的预判,可以当外部坐标

书列了四条(text/76-ch08-09-….txt:13text/76-ch08-09-….txt:37):

  1. 继续打磨 DeepSeek-R1 那套配方:旗舰模型用 RLVR,小模型用蒸馏;
  2. 推理时的自动化调度:模型不该对所有任务都写一样长的回答 —— 有的题该短答,有的该多花预算。书举了实例: OpenAI 2025 年发布 GPT-5 时加了 "auto" 模式来调节推理力度和推理轨迹长度;
  3. 改进 RLVR 的奖励生成:目前重度依赖最终答案的奖励; 过程奖励(检查中间步骤)可能提供更丰富的信号。 书举了新证据:DeepSeek-Math-V2 论文(https://arxiv.org/abs/2511.22570)最近证明了 在训练时评判整条答案能显著提升推理性能; —— 注意:这和第 6 章说的「DeepSeek-R1 团队试过程奖励失败了」构成一条时间线上的翻转, 拆解里应该把这两处连起来讲。
  4. 推理模型成为 agent 应用的引擎,书点名 OpenAI Codex、Claude Code、OpenClaw。 在这类场景里,模型不只解题,还要规划、调工具、从失败里恢复、协调长流程; 这会把奖励设计推出数学和代码之外 —— 可能要为成功调用工具、检索信息、 遵守策略等分别给奖励,从而走向多奖励训练

10.9 作者的收尾建议(8.10 节)

下一步怎么做(text/77-ch08-10-….txt:19):把这些方法组合起来,而不是当孤立技术—— 比如先从强老师蒸馏一个小模型,再用 RLVR 继续训,部署时再叠上自洽或自我精修。 「跑这类对照,往往是最快建立直觉的办法」。

怎么跟上这个领域(text/77-ch08-10-….txt:49text/77-ch08-10-….txt:79),书的态度很务实:

  • 核心思想比具体算法长寿:仔细做模型评测、区分推理时方法和训练时方法、 真正搞懂损失和奖励信号怎么算的 —— 这几条会一直有用;
  • 新方法出来时,把它映射回这些基本功:很多新技术本质上是这些积木的变体或组合;
  • 具体渠道:arXiv 的 cs.LG 最新列表(但明说论文量已大到不可能读全,只该拿它扫主题)、 新模型的技术报告(提示惯例、基准、局限往往写在这里)、 X 和 r/LocalLLaMA 这类从业者社区(实现细节、复现、失败案例常常比论文更早出现);
  • 对 AI 助手/深度研究工具的态度:它们适合当过滤器,不能替代读原始论文和模型卡

十一、七个附录(text/7985,共 166k 字符 —— 占全书 24%)

这本书的附录非常重,不是可有可无的边角料。 拆解时至少要在总纲里交代它们讲什么。

附录篇幅内容拆解里怎么用
A 参考文献与延伸阅读14.2k全书引用的论文与文章清单写外部出处时的第一站,先查这里再上网
B 练习答案34.1k全书练习的解答,含 7.2 的实验参考结果部分练习答案里有实验数据
C Qwen3 源码34.3k模型架构与代码(RMSNorm 等)讲架构细节时的依据
D 用更大的 LLM11.3k换更大模型怎么做「边界与局限」一节可引
E 批处理与吞吐19.3k批量推理,书里正文多次指向它讲「为什么书里的实现慢」时必引
F 其他评测方法35.1k多选题、排行榜、LLM 当裁判(第 3 章只做了验证器)拆解「评测」那一章的必要补充
G 聊天界面17.3k多轮对话、历史管理、系统提示第 1 章、第 2 章都指向它

⚠️ 这批附录我这次没有逐字读完(第一批备料以正文八章为主)。 写「评测」那一章之前,必须先读附录 F;写「性能」相关内容前应读附录 E。


第八批:附录细节、书架重叠核查、外部缺口清单

十二、附录里值得进正文的几处(已抽查)

12.1 附录 A 是一份现成的出处清单 —— 写外部引用时先查它,别上网瞎搜

text/79-apx-a-…txt 按章列全了全书引用的论文与文章。关键条目(全部带 URL,书自己核过):

主题出处行号
o1 发布https://openai.com/index/introducing-openai-o1-preview/text/79-apx-….txt:30
DeepSeek-R1https://arxiv.org/abs/2501.12948text/79-apx-….txt:41
Altman 那条表态https://x.com/sama/status/1889755723078443244text/79-apx-….txt:52
苹果的反方论文《The Illusion of Thinking》 https://machinelearning.apple.com/research/illusion-of-thinkingtext/79-apx-….txt:63
Qwen3 技术报告https://arxiv.org/abs/2505.09388;博客 https://qwenlm.github.io/blog/qwen3/text/79-apx-….txt:139text/79-apx-….txt:142
MATH 数据集原始论文《Measuring Mathematical Problem Solving With the MATH Dataset》https://arxiv.org/abs/2103.03874text/79-apx-….txt:221
MATH-500 划分的出处《Let's Verify Step by Step》https://arxiv.org/abs/2305.20050(同一篇也提供了 80 万条步骤级正确性标注)text/79-apx-….txt:232text/79-apx-….txt:271
思维链提示《Large Language Models are Zero-Shot Reasoners》https://arxiv.org/abs/2205.11916text/79-apx-….txt:327
自洽https://arxiv.org/abs/2203.11171text/79-apx-….txt:338
Gemini 3 Deep Think 的公开说法https://x.com/GoogleDeepMind/status/1996658401233842624text/79-apx-….txt:378
DeepSeekMath-V2https://arxiv.org/abs/2511.22570v1text/79-apx-….txt:389
Best-of-N vs 多数投票《Think Deep, Think Fast》https://arxiv.org/abs/2504.14047 —— 书说「可行时多数投票往往更好」text/79-apx-….txt:394text/79-apx-….txt:400
RLHF / InstructGPThttps://arxiv.org/abs/2203.02155text/79-apx-….txt:440
GRPO 原始出处DeepSeekMath https://arxiv.org/abs/2402.03300text/79-apx-….txt:451
PPO(裁剪比率的来源)https://arxiv.org/abs/1707.06347text/79-apx-….txt:513
DAPOhttps://arxiv.org/abs/2503.14476text/79-apx-….txt:524
Dr. GRPO《Understanding R1-Zero-Like Training: A Critical Perspective》https://arxiv.org/abs/2503.20783text/79-apx-….txt:527
VERLhttps://fengyao.notion.site/off-policy-rltext/79-apx-….txt:530
DeepSeek-V3.2https://arxiv.org/abs/2512.02556text/79-apx-….txt:533
GDPOhttps://arxiv.org/abs/2601.05242text/79-apx-….txt:536
GSPOhttps://arxiv.org/abs/2507.18071text/79-apx-….txt:539
CISPOMiniMax-M1 https://arxiv.org/abs/2506.13585text/79-apx-….txt:542
经典知识蒸馏《Distilling the Knowledge in a Neural Network》https://arxiv.org/abs/1503.02531text/79-apx-….txt:593
软蒸馏的强结果MiniLLM https://arxiv.org/abs/2306.08543text/79-apx-….txt:615
MMLUhttps://arxiv.org/abs/2009.03300text/79-apx-….txt:666
Chatbot Arenahttps://arxiv.org/abs/2403.04132;批评它的论文《The Leaderboard Illusion》http://arxiv.org/abs/2504.20879text/79-apx-….txt:688text/79-apx-….txt:705
评测成本TechCrunch:在七个流行基准上评一次 o1 约 1500 美元text/79-apx-….txt:282

⚠️ 引用时要注意:附录里最晚的两条是 2512(DeepSeek-V3.2)和 2601(GDPO)的 arXiv 编号, 和 2026-03 的 MEAP 日期吻合。这些编号我没有逐条上网核过,写进正文前要按标准 「必须核对,不许凭记忆写」逐条打开确认。

⚠️ 一处重要的书内不一致(是缺口,也是机会): 附录 A 把苹果那篇 《The Illusion of Thinking》 列在第 1 章的参考里, 并且用一句话概括了它的结论(推理模型是「精巧(但很有能力)的模式匹配器」,text/79-apx-….txt:57)。 但第 1 章正文从头到尾没有提到这篇论文,也没有讨论它的论点。 这是全书最大的一处「书里用了却没讲透」:书花整章论证「LLM 的推理不是逻辑推理」, 却把最有力的反方证据只放在附录清单里。拆解应当把它补进来,并标成外部来源。

12.2 附录 D:换更大模型要多少内存(text/82-…txt)

书给的估算口径:bfloat16 下每个参数约 2 字节(text/82-apx-….txt:132)。

模型仅权重的粗略内存
1.7B约 3.4 GB
4B约 8 GB
8B约 16 GB
14B约 28 GB
32B约 64 GB

书自己声明这只是下界(text/82-apx-….txt:192):实际还要算激活值、临时缓冲、KV 缓存; 加载时张量可能同时存在于两处,峰值还会更高。 核心建议(text/82-apx-….txt:479 段起):换大模型「主要是换一个检查点和配置字典的事,不是学一套新概念」。

12.3 附录 E:批处理(text/83-…txt)——书里多处指向它,拆解讲性能时必引

它先划了一对概念(text/83-apx-….txt:55text/83-apx-….txt:58): 延迟(latency)= 一条提示多快出答案;吞吐(throughput)= 固定时间内能处理多少条。 单条生成适合理解概念、压低延迟、调试;批处理主要针对吞吐。

书的诚实提醒(text/83-apx-….txt:75):批处理不是在所有设备上都更快 —— 小模型在 CPU 或优化不佳的 GPU 上可能收益很小甚至没有,因为要引入填充等额外复杂度和开销。 「批处理该被理解成吞吐优化,不是万能加速。」

表 E.1 的实测(部分):

脚本批大小内存H100 耗时DGX Spark 耗时
evaluate_math500.py1.8 GB90 min174 min
evaluate_math500_batched.py6423.39 GB16 min108 min
self_consistency_math500.py1.79 GB252 min340 min

注意:内存从 1.8 GB 涨到 23.39 GB(13 倍)换来 H100 上 90→16 分钟(快 5.6 倍), 但在 DGX Spark 上只从 174→108 分钟(快 1.6 倍)—— 正好印证了上面那句提醒。

12.4 附录 F:另外三种评测法(text/84-…txt)——写「评测」那一章前必须先完整读它

第 3 章只做了四种里的一种。附录 F 补齐另外三种:

方法类别怎么做书举的例子
多选题基准型让模型输出一个字母,直接比对MMLU;书演示了一道题、抽出字母、发现答错了(text/84-apx-….txt:409text/84-apx-….txt:417)
验证器基准型第 3 章已做MATH-500
排行榜评判型用户对两个模型的回答投票,用 Elo 评分系统(源自国际象棋排名)聚合成排行榜LM Arena(原 Chatbot Arena);书用 6 条投票现场算了一份排行榜
LLM 当裁判评判型另一个 LLM 拿着评分细则(rubric),对照参考答案给分书用 Ollama + OpenAI 的 gpt-oss 20B 实现了一遍

几条可直接引用的判断:

  • 书说明了为什么早期的 BLEU 之类不行(text/84-apx-….txt:771):它们要求精确的词匹配, 不认同义词和措辞变化;
  • 为什么 LLM 裁判效果好(text/84-apx-….txt:796):除了裁判模型强之外, 「评价一个答案往往比生成一个答案容易」;
  • 排行榜的软肋:偏好比较主观,而且收集人类反馈本身有难度; 附录 A 还给了批评排行榜的论文《The Leaderboard Illusion》;
  • 训练损失、困惑度、奖励这些量属于「模型开发内部用的」,不算这四类(text/84-apx-….txt:37)。

12.5 附录 B、C、G 一句话

  • B(练习答案,34k):含表 B.1「MATH-500 上的平均回答长度」和表 B.2 「不同数据集规模下的准确率」——有实验数据,不只是答案;
  • C(Qwen3 源码,34k):RMSNorm、前馈模块、RoPE(旋转位置编码)分组查询注意力(GQA)、Transformer 块、主模型、KV 缓存、分词器,逐个给代码;
  • G(聊天界面,17k):用 Chainlit 搭界面,讲单轮 vs 多轮的区别 (多轮要把对话历史拼进提示词,并按上下文窗口裁剪)。

十三、⚠️ 书架重叠核查:这本书不是我们书架上第一本讲 GRPO 的

动笔前必须知道这件事,否则会写出第四份重复的 GRPO 讲义。

grep -ril "GRPO" ../ai-*-reference/docs/ 查出来,本库已有三本书的拆解覆盖了 GRPO/RLVR:

已有拆解相关章它讲的是什么(取自各自的 essence)
docs/the-rlhf-book-reinforcement-learning-from/06-grpo-generation.md07-rlvr-reasoning.md算法谱系:GRPO 怎么用一个统计量换掉 PPO 的价值网络、它自带的偏差;GSPO/CISPO/DAPO/Dr. GRPO 各在修什么病;损失聚合与异步训练
docs/post-training-ai-practical-guide-to/05-grpo-verifiable-rewards.md从零写 GRPO 的训练循环:采样一组回答、可验证奖励打分、组内平均分当基线;命门是方差(全组同分,一步白走)
docs/da-yu-yan-mo-xing-cong-li-lun-dao-shi-jian/07-rl-ppo.md08-rlhf-reasoning.mdRLHF 完整闭环 + R1-Zero 的规则奖励与「顿悟时刻」,以及工程框架 verl

判断(我们的,不是书里的):这本书对书架的增量不在「GRPO 是什么」,而在下面四条。 如果错,会错在: 我只读了那三份拆解的 frontmatter 和开头,没有逐章比对正文; 若它们其中某一份已经给出了同一条 MATH-500 纵向对照,则第 1 条增量不成立。

  1. 唯一一本把五种方法放在同一把尺子上纵向量过的书。 全书自始至终用 MATH-500 全 500 题,base 模型 15.2% 是共同基线: 思维链 40.6% · 自洽+思维链(n=10)52.0% · GRPO 50 步 47.4% · 蒸馏 45.0% · 自我精修 25.0% · 官方推理版 48.2%。 这张纵向对照表是别处没有的,也是这本书对读者最大的价值: 「哪条路最划算」这个问题,它是用同一批题、同一个模型答的。
  2. 唯一一本从零手写「验证器」的书。 第 3 章那八步(抽框 → 归一化 → SymPy 判等 → 分段打分) 在别的书里都是一句「用一个验证器」带过。
  3. 唯一一本把 GRPO 的失败画成曲线的书。 第 7 章的 KL 崩溃(奖励塌零后 KL 独占梯度 → 吐乱码 → 准确率归零)和格式奖励被刷分(光守 <think> 格式就赚够了), 都是带日志、带图、带诊断的现场,不是警告句。
  4. 推理时扩展讲得比任何一本 RL 书都深。 温度、top-p、自洽、自我精修、 规则式打分、对数概率打分 —— 第 4、5 两章 149k 字符,而三本 RL 书里这部分基本都是一节带过。

另一处书架命中:书里唯一提到的 agent 产品 OpenClaw(text/04-ch01-….txt:41text/76-ch08-09-….txt:37), 我们的 agent 书架已有完整拆解 —— ../ai-agent-reference/docs/openclaw/(6 章 + 总纲, 带 sourceCommit: 32cf13dc…)。要解释 OpenClaw 是什么,直接引这个书架锚,不必上网。

十四、外部缺口清单(写正文前要补的,按优先级)

说明:下面每一条我都还没上网核过。 这是给写大纲的人的待办,不是已完成的取材。 按标准的顺序:先翻书架(② 类),书架没有再上网(③ 类)

#缺口为什么是缺口该去哪里补
1《The Illusion of Thinking》(苹果)的具体论点书把它列进第 1 章参考却在正文一字未提 —— 而它正是「LLM 推理到底是不是推理」的最强反方③ 打开 https://machinelearning.apple.com/research/illusion-of-thinking;先查我们书架有没有拆过
2OpenClaw 是什么书提了两次,一次没解释,读者完全不知道② 书架已有:shelf=ai-agent-reference/openclaw#index.md
3DeepSeek-R1 到底怎么训的(完整多阶段管线)书全程拿它当参照,但只讲了 R1-Zero 那一半② 书架三份拆解都讲了,优先引 the-rlhf-book#07-rlvr-reasoning.mdda-yu-yan-mo-xing…#08-rlhf-reasoning.md;必要时补 ③ arxiv.org/abs/2501.12948
4Transformer / 注意力 / 嵌入的来历书明说「架构当黑盒」(text/10-ch02-05-….txt:298),但我们的读者零基础② 书架:docs/build-large-language-model/docs/what-is-chatgpt-doing/;书内可引附录 C
5PPO 是什么(GRPO 的对照物)书只说「GRPO 比 PPO 省一个价值模型」,没讲 PPOthe-rlhf-book#05-policy-gradient-ppo.md;③ arxiv.org/abs/1707.06347
6DAPO / Dr. GRPO / GSPO / CISPO 等十几个改法书只列名字不解释(text/65-ch07-06-….txt:608text/65-ch07-06-….txt:655)the-rlhf-book#06-grpo-generation.md 已成谱系,直接引
7书出版后的进展MEAP 定格在 2026 年初③ 上网,但要严格标日期;这一条最容易过期,建议少写
8clip_eps=10 这个「DeepSeek-R1 用的值」书给了但没给出处;这是个会改变读者判断的具体参数③ 核 arxiv.org/abs/2501.12948;核不到就照实写「书里这么说,我们没核到原文」
9MEAP 之后书有没有改我们读的是早期试读版③ 查 Manning 页面;核不到就在总纲写明「基于 MEAP,可能与定稿有出入」

第九批(收尾):全书主线、伏笔清单、建议的章节切分

十五、全书一条主线(通读之后排出来的,给总纲第 3 节做底本)

这本书从头到尾在回答一个问题:一个只有 6 亿参数、数学只能考 15 分的小模型, 怎么变成能考 47 分的推理模型 —— 而且每一步都要能自己动手做出来、自己量出来。

十步链条,每一步都由上一步的结论逼出来:

① 现象:GPT-4o 不是推理模型,却答对了「所有鸟会飞 + 企鹅是鸟 ⟹ 企鹅会飞吗」这道逻辑题。
为什么?因为训练数据里「企鹅不会飞」出现得够多,统计关联替它把矛盾修正了。
▼ 那它什么时候会崩?书给了答案:情形是新的、或者推理层数多的时候。
② 所以要给它一个新的能力:reasoning —— **在给出最终答案之前先生成中间步骤**。
不是哲学意义上的思考,就是「把 token 花在中间过程上,别直接跳结论」。
▼ 可是,怎么知道多花的 token 值不值?
③ 先造尺子,再改东西。不先做评测,后面所有改进都是自说自话。
于是第 3 章手写一个数学验证器:抽出 \boxed{} → 归一化写法 → 用 SymPy 判数学等价 → 打分。
基线量出来了:**base 模型 15.2%,官方推理模型 48.2%(但慢 18 倍)**。
▼ 这把尺子还有第二个用途 —— 记住它,第 6 章会原样变成奖励函数。
④ 最便宜的改进:一句话。在提示词后面加「Explain step by step.」——
**15.2% → 40.6%**。不给模型任何新知识,只改变它使用已有知识的方式。
▼ 但这条路的上限在哪?
⑤ 让它多答几遍,投票。要多答就得有随机性:温度(把分数除以一个数,改变分布的尖平)
配 top-p(只从累计概率够 p 的那一小撮词里抽)。
**注意:温度和 top-p 本身几乎不提分(15.2% → 17.8%),它们只是让「多答几遍」成为可能。**
真正提分的是投票:自洽 + 思维链,n=10 时 **52.0%**。
▼ 代价:10.1 分钟 → 862.6 分钟。**准确率涨 3.4 倍,时间涨 85 倍。**
⑥ 换个路子:让它改自己的作业。出初稿 → 让它批评自己 → 照批评重写。
**15.2% → 25.0%。** 但书老实交代:在这个模型这个任务上,**自我精修不如自洽**。
顺带造出两把「打分尺」:规则式(能不能抽出来 + 有多短)、
和**平均对数概率**(模型自己对这个答案有多大把握)。
▼ 而后者会**偏爱自信的错误答案** —— 这是它反而拖低成绩的原因。
▼ 到这里,不改权重能拿的都拿到了。要再往上,只能动模型本身。
⑦ 动权重的办法叫强化学习。但 ChatGPT 那套 RLHF 要先训一个奖励模型,
那东西的大小和成本常常和基础模型相当。
**换掉它**:数学题的对错是能自动判的 —— 第 3 章那把尺子直接当奖励(对得 1,错得 0)。
这就是 RLVR:两步流水线塌缩成一个循环。
▼ 有了奖励信号,怎么把它变成权重的改动?
⑧ GRPO:同一道题采多个回答,**让它们互相比**。比平均好的,提高产生它的可能性;
比平均差的,压低。这就是「组相对」三个字的全部意思 ——
也意味着**一组回答好坏一致时,它什么都学不到**(梯度精确为零)。
**结果:50 步训练,15.2% → 47.4%,已经贴近官方推理模型的 48.2%。**
平均回答长度从 79 个 token 涨到 586 —— 它真的学会了写中间步骤。
▼ 那多训几步不是更好?
⑨ 不是。**跑久了会崩。** 第 7 章把三种崩法画成曲线:
400 步后准确率下滑(原始 GRPO 长跑不稳);
加了 KL 项之后奖励塌到零、KL 项独占梯度、模型开始吐乱码、准确率归零;
加了格式奖励之后,模型发现「光守 <think> 格式就能赚分」,于是不好好答题了。
三种补救:裁剪策略比率(管每一步)、KL 项(管长期漂移,**但数学任务上多家建议干脆不要**)、
格式奖励(**要给权重,还要设成「答对了才给」**)。
▼ 可是这条路要 12 小时、70 GB 内存。有没有更便宜的?
⑩ 有:抄作业。拿一个 6710 亿参数的老师(DeepSeek-R1)把 12000 道题全做一遍,
让 6 亿参数的学生去学它的答案 —— 这就是蒸馏。**3 小时、15 GB,15.2% → 45.0%。**
而且书在这里给出了全书最反直觉的发现:**更强的老师不一定教出更好的学生** ——
DeepSeek-R1(91.2%)教出 33.6%,Qwen3 235B(92.4%)教出 45.0%,
因为后者和学生**同属一个模型家族**,分词器和风格更对得上,更好模仿。

主线的落点一句话: 五条路都通向同一把尺子上的分数,而这本书真正教会读者的, 是那把尺子怎么造、以及怎么读懂尺子上的数

十六、伏笔清单(不通读根本看不出来的那些)

埋在哪揭在哪内容
第 2 章 2.6 节的边栏「argmax 就是贪心解码,后面会讲别的选法」第 4 章 4.4 节温度 + 多项式采样
第 3 章开篇与 3.6 节两处「验证器到第 6 章会变成可验证奖励」第 6 章 6.6 节reward_rlvr 直接复用 grade_answer
第 3 章 3.9 节「小模型对提示词敏感,下一章引入更多提示变体后会更明显」第 4 章兑现
第 4 章 4.6 节「自洽不处理平局,下一章做一个置信度打分当裁判」第 5 章 5.6 节平均对数概率打分器
第 4 章 4.6 节「自洽只适用于有短答案的题」第 5 章自我精修更通用
第 5 章 5.4 节「这些对数概率下一章会进入训练目标,不再只是打分信号」第 6 章 6.8 节全书最重要的一处伏笔
第 6 章 6.2 节「先做没有 KL 项的简化版,第 7 章补上」第 7 章 7.5 节补上了,而且演示了它会崩
第 6 章 6.2 节「裁剪的策略比率下一章讲」第 7 章 7.4 节兑现
第 6 章 6.12 节「训更久不一定更好,甚至掉准确率」第 7 章全章兑现
第 6 章 6.6 节「DeepSeek-R1 团队试过程奖励失败了」第 8 章 8.9 节翻转:DeepSeekMath-V2 后来证明「训练时评判整条答案」可以显著提升
第 7 章 7.6 节「引入 <think> 要先做指令微调,那是下一章的内容」第 8 章兑现(蒸馏 = 在合成数据上做 SFT)
第 1 章反复论证「LLM 的推理不是逻辑推理」附录 A 才列出苹果那篇反方论文,正文一字未提未兑现的伏笔 —— 我们要补

十七、建议的章节切分(按新词密度切,不按原书章序)

原书 8 章 + 7 附录,562k 字符。按标准「一章 9k–11k 字符、拆解总量与原书相当或更多」, 建议切成 10 章 + 总纲。 依据三条:① 第 1 章新词密度太高必须拆; ② 第 4、5 两章合计 149k、新概念极多,必须拆成三章;③ 第 2、3 章各自内部主题单一,可各成一章。

建议章覆盖原书一句话讲什么主走查建议
总纲全书十步主线(见上一节)+ 时代坐标 + 五条路的成绩对照表
01 推理到底指什么1.1–1.2、1.4–1.5从企鹅那道题起头:不是推理模型却答对了,为什么;reasoning 的工程定义;和逻辑推理差在哪企鹅题(闭世界 / 开世界 / GPT-4o 实际怎么答的)
02 三条路的地图与代价1.3、1.6–1.7三条改进路线(推理时 / RL / 蒸馏)、常规训练管线、为什么推理模型贵、四阶段路线图一道题从 base 到推理模型的成本对照(前向次数 × 调用次数)
03 模型是怎么吐字的2.1、2.4、2.6–2.7分词 → 一次前向出 6×151936 个分数 → 取最后一行 argmax → 拼回去再来"Explain large language models." → 6 个 ID → [6, 151936] → 20286 → " Large"
04 让它跑得动2.2–2.3、2.5、2.8–2.9Qwen3 0.6B 选型、训一个 base 有多贵、KV 缓存、torch.compile同一段 100 token 的四种跑法:5 → 6 → 29 → 68 tokens/秒
05 先把尺子造出来3 全章四种评测法里为什么选验证器;八步流水线;16 条测试用例;提示词换一个词就差 20%a+b=3, ab=13/6 那道题:抽框 → (14)/(3) → SymPy 判 28/6 等价 → 打分
06 不训练也能提分:多写几步4.1、4.3 + 4.4 温度思维链一句话提 25 个点;为什么有效;overthinking;温度是什么(logits ÷ T)「3x−9 的一半等于 x+37」贪心答 20(错)→ 加一句话答 83(对);"The capital of Germany is" 在 T=5 和 T=0.35 下抽 1000 次的分布
07 不训练也能提分:多答几遍4.5 top-p、4.6 自洽top-p 四步;自洽 = 多数投票;表 4.1 全表10 个词的玩具词表走完 top-p 四步;5 次采样 83/22/54/83/61 → 投票 83
08 让它改自己的作业5 全章三种打分器;概率 → 对数概率;自我精修三步;为什么对数概率打分反而更差Berlin vs Bridge:联合概率 5.94e-08 vs 1.05e-13 → 对数概率 −16.63 vs −29.88;两轮精修 10 → 83 → 83
09 真的动权重:RLVR 与 GRPO6 全章RLHF vs RLVR;GRPO 六阶段;为什么求和不求平均;那个负号;50 步 15.2% → 47.4%四个 rollout 走完六步:奖励 [1,1,0,0] → 优势 [.87,.87,−.87,−.87] → 对数概率四个数 → 损失 −2.5764
10 跑久了会崩,以及怎么修7 全章该盯哪些指标(熵、优势标准差);裁剪比率;KL 项怎么把模型训成吐乱码;格式奖励被刷分KL 崩溃全过程:前 50 步 15%→40% → 200 步奖励塌零 → KL 独占梯度 → 吐 "framework.raises Self profess(import" → 0%
11 便宜得多的另一条路:蒸馏8 全章硬 vs 软蒸馏;12000 道题花 50 美元;长度过滤砍掉 44%;交叉熵 = 负平均对数概率;更强的老师不一定更好一条样本:老师的 thinking + content → <think>…</think> → 聊天模板包裹 → 交叉熵 1.68

切分理由(要写进大纲交底):

  • 01/02 是把原书第 1 章劈成两半。 原因是新词密度:第 1 章一章里就有 reasoning / CoT / token / 预训练 / SFT / 偏好微调 / RLHF / 自回归 / 涌现 / 蒸馏 / logits / 推理时扩展 / 强化学习 / 符号逻辑引擎 / 模式匹配……按「一节最多 5 个生面孔」根本塞不下一章; 劈开之后,01 只管「什么是推理、它和逻辑推理差在哪」,02 才管「有哪几条路、各要付什么代价」;
  • 03/04 是把原书第 2 章劈成两半。 分词 + 生成循环是后面每章都要用的承重件, 必须独占一章讲透;而装环境、选型、KV 缓存、编译属于外围,合并成一章「让它跑得动」—— 按标准这叫「把外围概念整节移出」,不是砍解释;
  • 06/07 是把原书第 4 章劈成两半。 原书第 4 章 77k 字符、四个大机制(思维链、温度、top-p、自洽), 一章塞不下;而且它们回答的是两个不同的问题:思维链和温度是「让一次回答更好/更多样」, top-p 和自洽是「多答几遍再挑」。按这个界线切,比按原书节序切更容易讲;
  • 第 5 章(→08)不拆:它虽然 72k,但内部是一条直线(打分 → 对数概率 → 用打分做精修), 拆开会把「为什么讲这么多对数概率」的动机切断;
  • 第 6、7 章(→09、10)不合并:一个讲「怎么成功」,一个讲「怎么失败」,合并会淹掉第 10 章的价值;
  • 附录不单独成章,但 F(其他评测法)要并进 05E(批处理)要并进 04D(更大模型)和 G(聊天界面)在「边界与局限」里各一段

总量预估:11 章 × 约 12k = 约 132k 字符 + 总纲约 15k ≈ 147k。 原书正文(不含附录)约 396k,比值 0.37 —— 明显低于样板的 2.15 倍。 但这是合理的:原书有大量代码清单和逐行注释,那部分我们不搬(红线一), 只搬机制、走查数字和判断。若把「原书正文减去代码」估作约 150k,比值就接近 1。 动笔时若发现讲不透,应当继续拆章,而不是压缩解释。

十八、写正文时的六条注意(通读中记下的坑)

  1. 两组基线数字不一致,别混用:第 3 章表 3.1 是 15.3% / 50.8%(H100); 第 4、5、6、8 章的表都是 15.2% / 48.2%(DGX Spark)。 正文统一用 15.2% / 48.2%,因为后四章的所有对照都以它为基准;引第 3 章时注明设备差异。
  2. 「推理」这个中文词在这本书里至少有三义,必须一词一义: ① reasoning(生成中间步骤)、② inference(跑一次前向,神经网络意义)、 ③ statistical inference(从数据估参数,书里专门辨析过)。 建议:① 叫「推理」;② 一律叫「推断 / 跑一次前向」或直接留英文 inference 并挂牌; ③ 只在辨析那一处出现。
  3. 「蒸馏」有两义,书自己点了:LLM 圈的蒸馏 = 拿老师生成的文本做 SFT; 深度学习传统的知识蒸馏 = 学生同时学老师的输出和 logits首现处必须辨析。
  4. 比喻用完即拆:书里有两个大比喻 —— 「造甲壳虫而不是法拉利」(第 2 章)、 「开餐馆的厨师」(第 6 章)。可以借来搭结构,说完当场改口用正式说法,之后不许再用
  5. 书里的三处笔误已在上面各批笔记里标出(清单 4.8 的贪心判断、第 6 章训练日志的步号错位、 第 7 章练习 7.2 里的粘贴残留、第 5 章那句对不上的引文)。引用时避开,或如实说明。
  6. 附录 F 和 E 还没通读(这次只抽查了结构和几处关键段)。 写第 05 章前必须先完整读附录 F;写第 04 章前必须先完整读附录 E。