01
04|两种 KL 究竟在比较什么:先分清前缀,再分清方向
[返回总目录](../README.md) · 上一篇:[概率基础](03-probability.md) · 数值实践:[手算一次更新](06-worked-example.md)
OPD 的难点常常不是公式长,而是把几个不同问题塞进了一个名字:“学生自己生成”“使用 reverse KL”“只学教师最擅长的答案”,听上去像同一回事,其实并不等价。本篇把它们逐个拆开。前六节是核心概念,最后的带星部分解释为什么两段看起来几乎一样的训练代码,可能得到不同梯度;第一次阅读可以暂时跳过带星部分。
本篇所有数字均为教学构造。约定教师概率为 $p$,学生概率为 $q_\theta$,其中 $\theta$ 是学生内部可学习参数;$x$ 是用户提示,$h_t$ 是提示加上第 $t$ 步之前的输出。概率基础和自然对数的手算方法见上一篇。
图解阅读:先看图片和读图提示;需要手算或追溯证据时,展开各节详解。所有公式、字母解释与原始来源仍保留。
1. KL 比较的是两张概率表
在固定前缀下,教师与学生都对同一个词表给出概率。我们先省略前缀的长写法,用下表作为贯穿例子:

**读图:**正向KL按教师概率加权,反向KL按学生概率加权。它们比较同一对分布,但权重和比值方向同时变化。
展开详解:公式、字母含义、算例与适用条件
| 候选 token | 教师 $p_v$ | 学生 $q_v$ |
|---|---:|---:|
| A | 0.6 | 0.2 |
| B | 0.3 | 0.5 |
| C | 0.1 | 0.3 |
表里的下标 $v$ 指候选 token;$p_v$ 是 $p(v\mid h_t)$ 的缩写,$q_v$ 是 $q_\theta(v\mid h_t)$ 的缩写。它们都对应同一个前缀。学生低估了 A,同时高估了 B 和 C。我们需要一个总分表示这种不一致,而不是只检查最大概率的那个选项。
**Forward KL,正向 KL** 的定义是:
$$
D_{\mathrm{KL}}(p\Vert q)=\sum_{v\in\mathcal V}p_v\ln\frac{p_v}{q_v}.
$$
| 符号 | 含义 |
|---|---|
| $D_{\mathrm{KL}}$ | KL 散度这个函数;下标来自 Kullback 与 Leibler 的姓氏 |
| $p$、$q$ | 同一前缀下教师与学生的完整概率分布;此处省略学生参数下标 |
| $\Vert$ | 分隔两个分布,左右位置决定方向;它不是“取绝对值” |
| $p_v$、$q_v$ | 教师与学生给候选 token $v$ 的概率 |
| $\mathcal V$、$v\in\mathcal V$ | 完整词表,以及逐个取出其中候选 |
| $\sum$、$\ln$ | 对词表逐项求和,以及自然对数 |
A 项为 0.6 乘以 3 的自然对数,约 0.6592。B 项为 0.3 乘以 0.6 的自然对数,约负 0.1532。C 项为 0.1 乘以三分之一的自然对数,约负 0.1099。三项相加约为 0.3961 nat。
**Reverse KL,反向 KL** 把两张分布交换:
$$
D_{\mathrm{KL}}(q\Vert p)=\sum_{v\in\mathcal V}q_v\ln\frac{q_v}{p_v}.
$$
| 符号 | 含义 |
|---|---|
| $D_{\mathrm{KL}}(q\Vert p)$ | 以学生为左边分布、教师为右边分布的 KL |
| $q_v$、$p_v$ | 同一前缀下,学生与教师给候选 $v$ 的概率 |
| $v\in\mathcal V$、$\sum$ | 遍历完整词表并相加 |
| $\ln(q_v/p_v)$ | 学生概率除以教师概率,再取自然对数 |
这次 A 项约负 0.2197,B 项约 0.2554,C 项约 0.3296,总和约 0.3653 nat。交换方向后,外面的权重和里面的比值同时交换了;因此它不是简单地在原先结果前加一个负号。
KL 不是通常几何意义的距离:它一般不对称,不满足一般距离需要的全部性质。不过它是有用的“不一致程度”指标。哪一方向的数更大并没有普遍固定答案,某个例子里 reverse KL 更小,也不表示 reverse KL 训练天然更容易。
2. 为什么某项可以为负,而总和不能为负
当学生高估一个候选时,教师概率除以学生概率会小于 1,自然对数就为负。因此正向 KL 的 B、C 项为负完全正常。错误是看到某一项负数,就把它当成“这个 token 的 KL 为负”,进一步认为整个计算违反 KL 非负性。

*图 4-1|每根柱是一个候选 token 对 KL 的贡献项,纵轴单位为 nat。教学分布为教师 $p=(0.6,0.3,0.1)$、学生 $q=(0.2,0.5,0.3)$。左图按教师加权,三项之和约 0.396058;右图按学生加权,三项之和约 0.365274。绿色负柱没有违反完整 KL 非负性;它们要与同图中的正柱一起求和。*
展开详解:公式、字母含义、算例与适用条件
严格说,那些是 KL 求和中的贡献项。非负性质属于归一化概率表上的完整总和。如果只取词表里几个 token、不处理遗漏质量,或者把一个采样到的 log-ratio 当成全词表 KL,这个数字可能为负,不能套用“完整 KL 非负”检查。
非负性也能用一个很短的数学事实解释。对任何正数,负对数不小于一减这个数;把它用于两张概率表的比值,得到:
$$
\begin{aligned}
D_{\mathrm{KL}}(p\Vert q)
&=\sum_v p_v\left[-\ln\frac{q_v}{p_v}\right]\\
&\ge\sum_v p_v\left(1-\frac{q_v}{p_v}\right)
=\sum_v(p_v-q_v)=0.
\end{aligned}
$$
| 符号 | 含义 |
|---|---|
| $D_{\mathrm{KL}}(p\Vert q)$ | 两张完整概率表的正向 KL |
| $p_v$、$q_v$ | 教师与学生对候选 $v$ 的概率,这段证明先假设都大于 0 |
| $\sum_v$ | 对完整词表求和,省略了“属于词表”的长下标 |
| $\ln$、方括号 | 自然对数,以及把一个整体括起来 |
| $\ge$ | 大于或等于;这里使用了负对数的基本不等式 |
| 最后的 0 | 因为两张概率表各自总和均为 1,相减就是 0 |
例如把某个比值取成 2,负对数约负 0.6931,一减比值为负 1,前者确实更大;比值取成 0.5,负对数约 0.6931,一减比值为 0.5,前者仍更大。相等的条件是比值为 1,因此完整 KL 为 0 对应两张表相同。
出现零概率时采用极限约定:左边概率为 0 的项贡献按 0 处理;左边为正、右边为 0 时,该方向 KL 为无穷大。比如教师认为 A 的概率为 0.1、学生把 A 彻底排除,正向 KL 就无法有限。实践中的 softmax 在精确数学下给有限 logits 对应的 token 正概率,但截断采样、掩码和数值下溢可能引入零值,工程实现必须了解这一点。
3. 能完全表示教师时,两种方向都希望学生匹配教师
有一个常见说法:“教师有 A 60%、B 30%、C 10%,reverse KL 会鼓励学生只输出 A。”如果学生可以自由表示任意三项概率分布,这个说法是错的。

*图 4-2|深色柱始终是教师 $(0.499,0.002,0.499)$,绿色柱是学生的候选。① 为 $(1/3,1/3,1/3)$,② 为 $(0.998,0.001,0.001)$;先遮住③比较两种 KL,再放开③观察共同最优值 0。KL 单位均为 nat,数值由本章公式计算,四舍五入至四位小数。*
展开详解:机制、例子、来源与边界
学生直接变成 0.6、0.3、0.1,两种 KL 都为 0。若学生把全部概率堆到 A,reverse KL 等于 1 乘以六分之十的自然对数,约 0.5108,明显比 0 大。只输出 A 可能是某个受约束模型的折中,但不是这个可自由拟合问题的全局最优。
这一区别十分重要。所谓 mode 可以理解为分布中一个集中的可能结果区域,例如两种不同解题路线、两种不同措辞。Mode-seeking 是“更倾向于集中拟合某些模式”的描述,不能翻译成“反向 KL 数学上要求丢掉所有次要模式”。同样,mode-covering 也不能理解成“正向 KL 会把所有答案变成等概率”。
为了把限制看得清楚,我们另造一个刻意简化的例子:教师把左路线与右路线各放约一半概率,中间路线几乎不使用;学生受到非常强的限制,只允许从图中的前两张概率分布选一张。
这里的“只能二选一”是人为设置的容量约束,用来演示折中,并非真实神经网络的结构。正向 KL 更喜欢①,因为②严重漏掉教师常走的右路线。反向 KL 更喜欢②,因为①在教师几乎不走的中间路线花了三分之一的概率。
手算②的反向 KL:左路线贡献约 0.998 乘以 2 的对数,即 0.6918;中间贡献约负 0.0007;右路线贡献约负 0.0062,总和约 0.6849。虽然右路线几乎被漏掉,反向 KL 给这个漏掉区域的权重也很小,因此另一种折中胜出。如果允许第三个选项“完全复制教师”,它会以 0 同时胜过前两种候选分布。
真实的小模型面对大教师时,约束来自参数共享、表示能力、可用数据与优化难度,不会真的只有两张候选表。[MiniLLM 原文 §2 与 Figure 2](https://arxiv.org/html/2306.08543v4#S2)和 [GKD 附录 A.7](https://arxiv.org/html/2306.13649v3#A1.SS7)都在容量不匹配的语境讨论这些模式倾向。这是经验与近似分析的出发点,不是关于一切模型的无条件定理。
还有一层不能省掉:低概率不等于低质量。罕见但正确的数学解法、少数语言的表达方式、在特殊条件下才合适的工具调用,都可能处在教师的低概率区域。KL 比较的是分布一致性,公式里没有事实核查器。减少某些低概率结果是否有益,需要用实际任务评价,不能从 mode-seeking 这个词直接推出。
4. On-policy 问“谁带学生到这里”,KL 方向问“这里怎么比较”
想象教人开车。第一件事是决定去哪些路口练习:让教练开车带你看示范路线,还是让你自己开,看看你会在哪些路口犹豫?第二件事是到路口以后怎么评分:看教练推荐哪些动作,还是重点检查你最可能做出的动作?地点来源和评分方向是两件独立的设计。

*图 4-3|先沿绿色分叉确认“为什么来到甲或乙”,再沿深色框确认“到这里怎样算损失”。$\bar\theta$ 是采集本批前缀时固定的学生参数;$h$ 是已得到的前缀;$p,q$ 是该前缀下师生对每个候选的概率。图中的 80%、20%、0.1、0.5 都是教学假设,总体平均为 0.18 nat。*
展开详解:公式、字母含义、算例与适用条件
在语言模型里,地点就是前缀。例如学生先写出“先把两个数相减”,这个前缀进入下一步输入;教师现在面对这段学生写出的文字,给下一 token 概率。教师不必先自己写一篇答案,才能为这个前缀提供概率分布。
一个清晰的 on-policy 正向 KL 训练目标是:
$$
L_{\mathrm{on,F}}(\theta;\bar\theta)
=\mathbb E_{h\sim d_{q_{\bar\theta}}}
\left[\sum_{v\in\mathcal V}p(v\mid h)
\ln\frac{p(v\mid h)}{q_\theta(v\mid h)}\right].
$$
| 符号 | 含义 |
|---|---|
| $L_{\mathrm{on,F}}$ | 在学生前缀上计算正向 KL 的训练损失;on 表示前缀来自学生,F 表示 forward |
| $\theta$ | 这次要更新的学生参数 |
| $\bar\theta$ | 采集这一批前缀时的学生参数,横线表示这次更新时把它固定下来 |
| $d_{q_{\bar\theta}}$ | 学生运行时遇到前缀的分布;这里也包含训练提示与选取位置的规则 |
| $h\sim d_{q_{\bar\theta}}$、$\mathbb E$ | 先按学生运行情况取得前缀,再对这些位置求平均 |
| $p(v\mid h)$、$q_\theta(v\mid h)$ | 在同一个已取得的前缀上,教师与学生对候选 $v$ 的概率 |
| $\mathcal V$、$\sum$、$\ln$ | 完整词表、词表求和、自然对数 |
外层平均回答“练哪些位置”,来自学生;方括号里的内层求和回答“在一个位置如何比较”,权重来自教师。没有任何冲突。比如学生 80% 的时候会走到前缀甲、20% 的时候走到前缀乙;甲的词表 FKL 为 0.1,乙为 0.5,外层加权平均就是 0.8 乘 0.1 加 0.2 乘 0.5,等于 0.18。每个位置里的词表求和仍使用教师概率。
这不是仅靠想象构造的可能性。[GKD §3.1 的公式 (4)](https://arxiv.org/html/2306.13649v3#S3.SS1)明确给出学生采样配正向 KL,并说明不对采样分布反向传播。因此“forward KL 必须用教师生成数据”“OPD 必须使用 reverse KL”都不能作为通用定义。
| 前缀怎样取得 | 固定前缀内怎样比较 | 是否逻辑成立 |
|---|---|---|
| 固定人类或教师文本 | 正向 KL | 成立,常见监督蒸馏 |
| 当前学生生成 | 正向 KL | 成立,GKD 的明确实例 |
| 当前学生生成 | 反向 KL | 成立,常见 OPD 选择 |
| 固定文本 | 反向 KL | 也成立,只是前缀来源并非 on-policy |
同理,SFT 描述的是用目标输出做监督训练,并不把目标来源限定成教师。若目标完整序列恰好按教师分布抽样,最大似然与序列级正向 KL 在期望意义上相联系;换成固定的人类数据、贪心教师答案或过滤后的样本,就应具体说明数据分布,不能把所有 SFT 无条件等同于教师分布的精确 KL。
5. “在学生自己的位置练习”不代表所有分布偏差消失
On-policy 直接针对的是一种特定偏差:训练只看示范前缀,部署却要接着学生自己的输出写。让学生自己产生练习前缀,能减轻这种不匹配。但它不是把所有分布问题一次清零。

**读图:**学生会更新,问题和环境也会变化。on-policy改善的是监督落点,并没有把这些变化全部消除。
展开详解:机制、例子、来源与边界
训练提示可能与真实用户问题不同;采样时可能开温度,而部署用贪心;一批数据收集后学生又更新了多次,旧数据就不再严格来自最新策略;长回答可能被截断,工具环境也可能变化。即使前缀确实来自当前学生,教师在学生的错误前缀上也可能判断不准。
比如学生已经写出“北京位于法国”,教师接着给出一个语法流畅的续写分布,并不表示它能通过修改未来 token 把过去那句话自动删除。OPD 的反馈作用于将来的概率更新,之后遇到相似问题时才可能减少这类路径。是否能在当前回答里自我纠正,还取决于模型是否有合适的回退表达、教师信号是否可靠,以及训练目标怎么分配长期影响。
因此更准确的描述是:OPD 把监督放在学生实际容易遇到的位置上,减轻训练与生成前缀的不匹配。这既说明它解决什么,也保留了评价真实效果所需的边界。
6. 同一个 KL 名字,可能指 token 分布,也可能指整段序列
固定前缀上的 KL 只比较“下一 token 怎么选”。序列 KL 则比较“所有可能的完整回答各有多大概率”。两者的候选集合大小不同:三 token 词表下一步只有三项,固定十步的回答就有三的十次方,即 59049 条候选序列。

**读图:**上层决定到达哪个前缀,下层比较前缀处的候选分布。链式分解先保证数值关系,不能省略对梯度路径的检查。
展开详解:公式、字母含义、算例与适用条件
为了写出精确关系,暂时假设回答长度固定为 $T$,教师和学生在每个前缀都使用同一个词表;变长回答则需要把终止规则一起纳入模型。反向序列 KL 可以分解成学生前缀上的单步 KL 之和:
$$
D_{\mathrm{KL}}\big(q_\theta(y\mid x)\Vert p(y\mid x)\big)
=\mathbb E_{y\sim q_\theta(\cdot\mid x)}
\left[\sum_{t=1}^{T}
D_{\mathrm{KL}}\big(q_\theta(\cdot\mid h_t)\Vert p(\cdot\mid h_t)\big)\right].
$$
| 符号 | 含义 |
|---|---|
| $x$ | 此处固定的一道提示 |
| $y$ | 完整回答,左侧 KL 对所有完整回答组成的集合计算 |
| $q_\theta(y\mid x)$、$p(y\mid x)$ | 学生与教师的整段回答分布;$\theta$ 是学生参数 |
| $y\sim q_\theta(\cdot\mid x)$、$\mathbb E$ | 按学生分布生成完整回答并取期望 |
| $T$、$t$、$\sum$ | 固定生成步数、当前步、按所有位置相加 |
| $h_t$ | 当前回答走到第 $t$ 步前已形成的前缀 |
| $q_\theta(\cdot\mid h_t)$、$p(\cdot\mid h_t)$ | 同一前缀上的下一 token 完整分布,点号表示整个词表 |
| $D_{\mathrm{KL}}$、$\Vert$ | KL 函数及其有方向的分布分隔符 |
这来自上一篇的“序列概率相乘、对数相加”,再逐个位置做条件平均。请留意:这是损失数值的恒等式,没有说“把采出来的前缀固定后直接反传”就自动得到左边的完整梯度。
先用一个两步例子验证数值。第一步学生对 A、B 各给 0.5;教师给 0.6、0.4。第二步学生无论此前输出什么,都给 A、B 各 0.5;教师在 A 后给 0.9、0.1,在 B 后给 0.2、0.8。四条完整序列的学生概率都是 0.25,教师的 AA、AB、BA、BB 概率分别为 0.54、0.06、0.08、0.32。
直接按四条序列算反向 KL,四项约负 0.1925、0.3568、0.2849、负 0.0617,总和 0.3874。按前缀分解:第一步 KL 为 0.0204;第二步在 A 后 KL 为 0.5108,在 B 后 KL 为 0.2231;两个前缀各出现一半,所以加起来是 0.0204 加 0.5 乘 0.5108 加 0.5 乘 0.2231,仍为 0.3874。
正向序列 KL 的对应分解采用教师前缀分布。这与第四节的“学生前缀上做词表 FKL”不是同一个完整序列目标。二者都可以合理,但不能混用等号。另外,按每个回答长度平均 token 损失是另一种权重选择;固定长度时只差常数,变长时会改变长短回答的相对权重。
7. ★ 进阶:数值相同,为什么梯度还能不同
梯度可以先理解成一组“该往哪边拧旋钮”的数字。正数说明把对应旋钮稍微调大,会让损失上升;负数说明调大它会让损失下降。梯度下降便朝相反方向迈一小步。

**读图:**固定前缀的局部计算得到左支;完整序列目标还包含右支的到达概率变化。这里两项相加后的方向幅度与单独左支不同。

*图 4-4|左侧把第 6 节的四条路径画全:沿一条路径把条件概率相乘,就得到叶节点的序列概率。右侧只移动首步 A 的 logit,第二步概率全部固定;局部梯度与未来到达概率的梯度合计约 -0.02945。这里的 $p$ 是教师、$q$ 是学生、$x$ 是提示;0.25 是首步 A 概率为 0.5 时的 softmax 局部变化率。所有数值来自第 6、7 节的同一个教学模型。*
展开详解:公式、字母含义、算例与适用条件
如果损失平均在一个由学生控制的前缀分布上,改变学生会产生两种作用:第一,在已经来到的位置改变下一步选择;第二,改变以后会多常来到这个位置。把前缀当固定训练数据,只计算了第一种作用。
用一个抽象但可读的式子说明:
$$
\nabla_\theta L(\theta)
=\mathbb E_{h\sim d_\theta}
\left[\nabla_\theta\ell_\theta(h)
+\ell_\theta(h)\nabla_\theta\ln d_\theta(h)\right].
$$
| 符号 | 含义 |
|---|---|
| $\theta$ | 影响学生行为的一组参数 |
| $L(\theta)$ | 对前缀分布平均后的总体损失 |
| $h$、$d_\theta(h)$ | 一个前缀,以及当前参数下到达它的概率;为教学假设是正概率的有限集合 |
| $\ell_\theta(h)$ | 到了前缀 $h$ 后,该位置的局部损失;小写 $\ell$ 读作“小 ell” |
| $\nabla_\theta$ | 对各学生参数求变化率,合起来组成梯度 |
| $\mathbb E$、$h\sim d_\theta$ | 按学生前缀出现概率求平均 |
| $\ln$ | 自然对数;第二项记入“到达概率改变”的影响 |
这只是对“概率乘损失,再求和”使用乘法求导法则。若不熟悉求导,记住括号里两项分别对应“到这里以后怎么做”和“以后还会不会到这里”即可。固定采样分布意味着训练时只保留第一项;它是一种明确的更新设计,而不是凭空让第二项自动消失。
上面的两步例子还能给出具体数字。只把第一步 A 的 logit 当作可动旋钮,第一步 B 的 logit 固定,第二步的概率表全部固定。当第一步 A、B 各为 0.5 时,A 的 logit 增加一个很小量,A 的概率大约增加这个量的四分之一。这个四分之一来自两类 softmax 的局部变化率。
第一步局部反向 KL 对 A logit 的梯度约为 负 0.10137,所以局部目标想提高走向 A 的概率。可是走到 A 后的第二步 KL 为 0.51083,比 B 后的 0.22314 更大;如果更常走 A,未来平均损失会增加。未来这部分的梯度为两者之差 0.28768 乘以四分之一,即 正 0.07192。完整序列梯度为两者相加,约 负 0.02945。
因此在这个具体设置下,两种更新都想提高第一步 A 概率,但完整序列梯度提高得少一些,因为它考虑了后续影响。别的设置也可能改变方向。不能用“差不多都是逐 token loss”把这个差异忽略。
[MiniLLM §2.2 的公式 (3)](https://arxiv.org/html/2306.08543v4#S2.SS2)明确区分单步与长期梯度贡献;GKD 则明确采用不对采样分布反传的更新。它们提供了理解不同实现的两个锚点。之后的算法可能采用近似、截断、重要性权重或奖励塑形,读代码时仍需看实际更新式。
这里“不对离散采样反传”还有歧义。普通自动微分无法沿着“抽中了哪一个整数 token”直接求导,但可以用策略梯度估计采样概率改变的影响;另一些算法则主动忽略这个影响,只对固定前缀上的局部分布求导。这两种处理都不会给离散 token 编号本身求导,却不是同一种梯度。
★ 选读:JSD 的数学端点与软件端点
**JSD,Jensen–Shannon 散度**,先把师生概率混成一张表,再比较两者与混合表的 KL。加权版本中,$\beta$ 表示教师混合权重,学生权重为一减 $\beta$;两个 KL 也按这组权重平均。这里的 $\beta$ 不是奖励正则强度。
例如教师为 0.6、0.3、0.1,学生为 0.2、0.5、0.3,教师权重取 0.5,混合表就是 0.4、0.4、0.2。教师对混合表的 KL 约为 0.087660,学生对混合表的 KL 约为 0.094582,两者各乘 0.5 再相加,JSD 约为 0.091121。
权重取 0 时,混合表就是学生;教师的那项权重为 0,学生与自身的 KL 也为 0,因此普通未归一化加权 JSD 为 0。权重取 1 时同理。一般分布的端点可按连续延拓理解,不要在程序里直接制造“0 乘无穷大”。
软件可能另外规定:`beta=0` 切换成正向 KL,`beta=1` 切换成反向 KL;也可能对中间式归一化,使端点极限对应 KL。这是函数约定,不能直接把端点代入普通 JSD 公式得到它。[TRL GKD 文档](https://huggingface.co/docs/trl/gkd_trainer)使用了这类端点说明,其 [v1.13.0 源码](https://github.com/huggingface/trl/blob/v1.13.0/trl/experimental/gkd/gkd_trainer.py)在 `generalized_jsd_loss` 中确实把两个端点单独分支处理。对本例,普通 JSD 端点为 0,而单独切换到 FKL/RKL 分支时分别是 0.396058、0.365274,数值区别很明确;实际训练仍应检查所安装版本。
8. 读一段 OPD 方法时,依次定位这四件事
先找数据来源:是学生当前生成、旧学生生成、教师生成,还是混合?再找比较对象:同一前缀上的完整词表、仅采样 token 的分数,还是整段序列?然后找 KL 方向:哪张分布在左边,哪张分布提供平均权重?最后找更新方式:采样分布是否视为固定,是否加入长期回报,哪些部分使用停止梯度?

**读图:**先定位采样分布,再定位局部差异,最后追踪求导路径。这三个答案一起决定实际训练做了什么。
展开详解:机制、例子、来源与边界
这四件事可以组合成许多合理方法。OPD 是一类在学生自身生成轨迹上使用教师监督的训练思路;reverse KL 是其中一种重要损失选择;mode-seeking 是某些限制条件下的行为倾向。理解了这几个层次,第六篇里的手算与代码就不再只是套一个符号公式,而是能解释每个数为什么出现、每个近似舍弃了什么。
[继续实践:06|手算一次完整的蒸馏更新](06-worked-example.md)
正在连接 GitHub 评论…