🏠 总目录📚 本教程 01b · KL 散度
📑 本页目录(点开跳转)

01b · KL 散度:交叉熵的真身

38 分钟 | ⭐⭐ 给一个被引用了六次、却从没定义过的量上户口


🎯 一句话

KL 散度 = 你拿错误的分布 Q 去编码真正来自 P 的消息,平均每条多付的比特数。

上一章说「交叉熵是伯努利分布下的最大似然」,但没说清一件事: "交叉熵"这个信息论的词,为什么会出现在一个统计问题里? 这一章的答案是 —— 它们本来就是同一个东西

最小化 KL = 最小化交叉熵 = 最大化似然。 上一章的最大似然,一直在最小化 KL,只是没点破。

⚠️ 为什么值得在这里停一下

KL 散度是这套教程里被引用最多、却从来没定义过的量。 站里至少有四个板块直接拿它当已知概念在用:

站里哪儿用到它 那里怎么用的
强化学习 11 · PPO TRPO 拿 KL 做硬约束:新旧策略的 KL ≤ δ
强化学习 12 · RLHF 奖励里减 β·KL;⭐「盯 KL 而不是奖励分数来早停」是那一章最有用的经验
推荐算法 18 · 蒸馏 学生匹配老师的软标签,损失就是 KL
Kaggle 02 · R-Drop 同一条输入过两次 dropout,用对称 KL 把两个输出拉近

四处都直接用,没有一处停下来定义过它。 这一章是它的正式户口 —— 读完这一章再去那四处,就不会卡在这个词上(链接在章末的「这一章连到哪里」)。


🌀 一、直觉:用错码本要多付多少比特

   真实分布 P(某个沙漠城市的天气)  晴 80%   阴 15%   雨 5%
   你的假设 Q(你以为三种一样多)    晴 33%   阴 33%   雨 33%

   你要把每天的天气用二进制码发给朋友。
   ├─ 按【真实分布 P】设计码本 → 平均每天 0.88 比特(这是最优,没法更省)
   └─ 按【你的假设 Q】设计码本 → 平均每天 1.58 比特

   ⭐ 多付的 0.70 比特,就是 KL 散度
      —— 编码开销涨了 79%,代价全部来自"你的假设错了"

💡 一句话

KL(P‖Q) = 你拿 Q 的码本去编码真正来自 P 的消息,平均每条多付的比特数。 假设完全正确(Q = P)→ 一分钱不多付 → KL = 0;假设越离谱 → 多付越多。

🔑 为什么"多付的比特数"这个说法值得记住:它一句话解释了为什么 KL 不可能是负的 —— 用错码本不可能比用对码本还省。后面那条「KL ≥ 0」的性质,直觉就在这。

📐 定义

$$D_{KL}(P\,\|\,Q) \;=\; \sum_x P(x)\log\frac{P(x)}{Q(x)} \;=\; \mathbb{E}_{x\sim P}\!\left[\log\frac{P(x)}{Q(x)}\right]$$

💡 人话在 P 身上采样,每次记下「P 觉得这事多常见」比「Q 觉得这事多常见」高出多少(取对数),求平均。

📏 单位:用 $\log_2$ 结果的单位是比特(上面那个例子), 用自然对数 $\ln$ 单位是 nat。机器学习里默认自然对数 —— 反正只关心相对大小。

⭐ 四条性质(第四条是后面一切的钥匙)

性质 说明
$D_{KL}\ge 0$,且 = 0 当且仅当 P = Q 「用错码本不可能比用对码本还省」。这就是它能当"差多远"用的资格
不对称:$D_{KL}(P\|Q)\ne D_{KL}(Q\|P)$ 所以它叫散度不叫距离。下一节整节都在讲这件事的后果
不满足三角不等式 它连"度量"都不是,别拿它当距离矩阵用
P(x)>0 但 Q(x)=0 → $D_{KL}=\infty$ ⭐⭐ 真实会发生的事,你的模型给了 0 概率 → 无穷大的惩罚。 反过来 P(x)=0 的地方那一项恒为 0,Q 在那儿怎么胡来都不罚

⚖️ 二、非对称到底意味着什么:前向 KL vs 反向 KL

先看两个具体数字。两个二元分布:

   P = (0.50, 0.50)     ← 五五开
   Q = (0.99, 0.01)     ← 几乎一边倒

   KL(P ‖ Q) = 2.33 比特      ⭐ 前向
   KL(Q ‖ P) = 0.92 比特      ⭐ 反向

   同样两个分布,只是换了个顺序 —— 答案差 2.5 倍。

🔑 记忆法:期望在谁身上取,谁就是考官

回头看定义:求和只在 P 有质量的地方展开。P(x)=0 的地方那一项是 0, 不管 Q 在那儿长什么样。所以「谁在前面」决定了「谁在出题」。

前向 KL $D_{KL}(P\|Q)$ 反向 KL $D_{KL}(Q\|P)$
考官是谁 真实数据 P 模型自己 Q
什么会被重罚 数据出现过、而模型给 0 概率 → ∞ 模型敢出声、而数据里几乎没有 → 很大
什么完全不罚 模型在没数据的地方乱给概率 模型丢掉一整个峰(0·log0 = 0,免费)
结果 mode-covering / 宁滥勿缺 mode-seeking / 宁缺勿滥
谁在用 最大似然、交叉熵(下一节证明) 变分推断 / VAE、RLHF 的 KL 惩罚项
灰色虚线 = P(真实分布,两个峰) 橙色实线 = Q(只有一个峰的模型)前向 KL:min KL(P ‖ Q)最大似然 / 交叉熵在最小化的那个反向 KL:min KL(Q ‖ P)变分推断 / RLHF 惩罚项用的那个Q 被迫盖住每个峰 → 概率糊在低谷上Q 只蹲在一个峰上 → 另一个峰被丢掉mode-covering(宁滥勿缺)mode-seeking(宁缺勿滥)
⭐ 同一个 P(两个峰)、同一个 Q(只能有一个峰),换个 KL 方向答案完全不同:前向 KL 逼 Q 盖住所有峰,代价是把概率糊到中间那个其实没数据的低谷上;反向 KL 允许 Q 只挑一个峰蹲着,丢掉另一个峰一分钱不罚。

💥 三个你可能撞见过的现象,机理都在这

现象 是哪个 KL 干的
语言模型(最大似然训的)容易生成四平八稳、"平均脸"式的句子 前向 KL 的 mode-covering:为了盖住训练集里所有说法,概率被摊开,摊到了没人真会那么说的中间地带
VAE / 变分推断估出来的后验偏窄,低估不确定性 ELBO 里那一项是反向 KL,mode-seeking → 抓住一个峰就不管别的了(第 13 章的 ELBO)
RLHF 训久了输出多样性下降(mode collapse) RLHF 的惩罚项是 $D_{KL}(\pi\,\|\,\pi_{SFT})$ —— 反向 KL。它罚「跑到 SFT 模型不敢去的地方」,但对「把概率全押在 SFT 的某一个峰上」零惩罚。所以 KL 惩罚拴得住模型不跑飞,拦不住它塌缩

⚠️ 别读成「反向 KL 不好」。 RLHF 要的正是反向 KL 那种约束:不许跑出参考模型的支撑集 —— 跑出去就意味着奖励模型没见过那种输出,那里给的分数根本不可信mode collapse 是这个选择的副作用,不是实现 bug。 强化学习第 7 章观察到了这个现象,机理就在这一节。


🔗 三、三个说法,同一件事

最小化 KL = 最小化交叉熵 = 最大化似然。 这一节把它们串成一条。

第一步:交叉熵 = 熵 + KL

还是沙漠天气那个例子:

含义
$H(P)$ 0.88 比特 数据本身的不确定性,和你的模型一点关系都没有
交叉熵 $H(P,Q)$ 1.58 比特 你用 Q 的码本实际付的
KL $D_{KL}(P\|Q)$ 0.70 比特 多付的

$$\underbrace{H(P,Q)}_{\text{交叉熵}} \;=\; \underbrace{H(P)}_{\text{熵}} \;+\; \underbrace{D_{KL}(P\,\|\,Q)}_{\text{KL 散度}}$$

📐 推导(三行,想看再点)

$$H(P,Q) = -\sum_x P\log Q = \underbrace{-\sum_x P\log P}_{H(P)} + \underbrace{\sum_x P\log P - \sum_x P\log Q}_{\sum_x P\log(P/Q)\;=\;D_{KL}(P\|Q)}$$

加一项减一项而已。

关键在于:$H(P)$ 只和数据有关,对模型参数 θ 来说是个常数。 所以 最小化交叉熵 ⟺ 最小化 KL —— 差的那一项你根本动不了。

💡 这回答了上一章结尾留下的那个问题: 交叉熵不是随手挑的一个「衡量两个分布差多远」的量。 它就是 KL 加上一个不可优化的常数,优化时二者完全等价

第二步:最小化 KL = 最大化似然

训练时你手上没有真实分布 P,只有 n 个样本。 那就用经验分布 $\hat P$ 代替它:每个训练样本各占 1/n 的概率质量

$$D_{KL}(\hat P\,\|\,q_\theta) = \sum_{i=1}^{n}\frac1n\log\frac{1/n}{q_\theta(x_i)} = \underbrace{-\log n}_{\text{常数}} \;-\; \frac1n\sum_{i=1}^{n}\log q_\theta(x_i)$$

后面那一项,正是平均负对数似然 —— 上一章第二节那个东西。

$$\boxed{\;\min_\theta D_{KL}(\hat P\|q_\theta)\;\iff\;\min_\theta\Big(-\tfrac1n\textstyle\sum_i\log q_\theta(x_i)\Big)\;\iff\;\max_\theta\ \text{似然}\;}$$

同一件事的三种说法

说法 视角 在哪会遇到
最小化 KL 信息论:让模型分布贴近数据分布 RLHF 早停、蒸馏、变分推断
最小化交叉熵 深度学习:你写在代码里的 CrossEntropyLoss 每一个分类任务
最大化似然 统计:上一章全章 最小二乘、逻辑回归

顺带解决了上一节的一个问题:这里出现的是 $D_{KL}(\hat P\|q_\theta)$,前向 KL。 所以 mode-covering 是最大似然的固有性质,不是某个模型的缺陷 —— 你只要在用交叉熵训练,就在要求模型「盖住数据里出现过的一切」。

🔬 亲眼验证一次(三个数会完全相同)

import numpy as np

y = np.array([0, 2, 1, 2, 0])                    # 5 个样本的真实类别
q = np.array([[.7, .2, .1], [.1, .2, .7], [.2, .6, .2],
              [.3, .3, .4], [.5, .4, .1]])       # 模型预测的概率

# ① 负对数似然:只取"真实类别"那一格的概率
nll = -np.mean(np.log(q[np.arange(len(y)), y]))               # ⭐

# ② 交叉熵:把真实类别写成 one-hot 分布 P,再算 -Σ P·log Q
P = np.eye(3)[y]
ce = -np.mean(np.sum(P * np.log(q), axis=1))                  # ⭐

# ③ KL(P‖Q):one-hot 分布的熵 H(P)=0,所以 KL 恰好等于交叉熵
kl = np.mean(np.sum(P * np.log(np.clip(P, 1e-12, None) / q), axis=1))   # ⭐

print(nll, ce, kl)      # 0.5667226848155111 三次,一模一样

💡 为什么 one-hot 时 KL 就等于交叉熵:分类任务的"真实分布"是个 one-hot, 它的熵是 0(完全确定),所以 $H(P,Q)=0+D_{KL}$。 换句话说,你写的每一行 CrossEntropyLoss,实际上都在最小化 KL 散度。


🔗 这一章连到哪里

站里每一处用到 KL 的地方,读完这一章都能直接看懂了。

去哪 为什么
第 1 章 · 最大似然 本章证明的那件事的另一半:那一章把损失函数还原成分布假设,本章说明它一直在最小化 KL
ML基础 03 · 线性模型 ⭐ 那一章说「分类用交叉熵不用 MSE 是经典考点」,本章第三节给出更深一层的根因:交叉熵就是 KL 加一个常数
强化学习 11 · PPO 去看 TRPO 的信任域 $D_{KL}(\pi_{old}\|\pi_\theta)\le\delta$ 到底约束了什么
强化学习 12 · RLHF ⭐ 那里有一条「盯 KL 而不是奖励分数来早停」的建议 —— 读完本章你就知道那个数字在量什么了
强化学习 07 · 探索与利用 那一章观察到 RLHF 训久了 mode collapse,本章第二节给机理:惩罚项是反向 KL
强化学习 13 · DPO 整个 DPO 的推导出发点:带 KL 约束的 RLHF 目标有闭式解,从中反解出奖励表达式
AI基础设施 18b · 知识蒸馏 · 推荐算法 18 蒸馏损失 = $D_{KL}(\text{老师}\|\text{学生})$,学生在匹配老师的软标签分布
Kaggle 02 · R-Drop 那里的对称 KL 为什么要对称:单向 KL 会偏袒其中一个输出
第 13 章 · EM 与高斯混合 ELBO 里那个"贴紧下界"的缝隙,缝隙宽度就是一个 KL

✅ 检查点

  1. 用编码的说法解释一下 KL 散度在量什么。沙漠天气那个例子里三个数分别是多少?
  2. KL 的四条性质是什么?为什么它叫"散度"不叫"距离"?第四条反过来(P=0 的地方)说明了什么,为什么这一条是钥匙?
  3. 前向 KL 和反向 KL 分别把模型逼成什么样?用什么办法一眼分辨谁是谁?
  4. 「最小化 KL = 最小化交叉熵 = 最大化似然」这条链子,中间两步各靠什么成立?
  5. 为什么分类任务里交叉熵和 KL 的数值恰好相等?
  6. RLHF 的 KL 惩罚拴住了模型不跑飞,为什么拦不住 mode collapse?这是 bug 吗?
  7. 语言模型为什么容易生成"平均脸"式的句子?这和最大似然有什么关系?
👀 答案
  1. 用 Q 的码本去编码真正来自 P 的消息,平均每条多付的比特数。沙漠天气:熵 H(P) = 0.88 比特(数据本身的不确定性),交叉熵 H(P,Q) = 1.58 比特(用错码本实际付的),KL = 0.70 比特(多付的,开销涨 79%)。
  2. ≥ 0,且 = 0 当且仅当 P = Q不对称不满足三角不等式P>0 而 Q=0 时为 ∞。因为 ②③ 它不满足"距离"的定义,所以叫散度。第四条反过来:P=0 的地方那一项恒为 0,Q 在那儿怎么胡来都不罚 —— ⭐ 这条不对称正是前向/反向 KL 行为差异的全部来源:谁在前面,谁就决定了哪些地方会被检查。
  3. 前向 KL(考官是真实数据)→ mode-covering,宁滥勿缺:数据出现过的地方模型给 0 概率就是 ∞ 惩罚,但模型在没数据的地方乱给不罚 → 概率被糊到峰间低谷上。反向 KL(考官是模型自己)→ mode-seeking,宁缺勿滥:丢掉一整个峰完全免费(0·log0 = 0),但在 P 很小处出声要重罚。⭐ 一眼分辨:期望在谁身上取,谁就是考官。数字:P=(0.5,0.5)、Q=(0.99,0.01) 时 KL(P‖Q)=2.33 而 KL(Q‖P)=0.92 比特,差 2.5 倍
  4. 第一步靠 交叉熵 = 熵 + KL,而 H(P) 与模型参数无关是常数。第二步靠用经验分布 P̂ 代替 P(每样本占 1/n),代入后 KL = 常数 −(1/n)Σlog q(xᵢ),后一项就是平均负对数似然
  5. 因为分类的"真实分布"是 one-hot,熵 H(P) = 0,而交叉熵 = 熵 + KL = 0 + KL。⭐ 所以你写的每一行 CrossEntropyLoss 都在最小化 KL
  6. 因为 RLHF 的惩罚项是 KL(π ‖ π_SFT),是反向 KL:它重罚「跑到 SFT 模型不敢去的地方」(这正是要防的——那里奖励模型没见过、分数不可信),但对「把概率全押在 π_SFT 的某一个峰上」零惩罚不是 bug,是选反向 KL 这个决定的副作用:管得住"跑多远",管不住"塌成一个点"。
  7. 因为最大似然最小化的是前向 KL,而前向 KL 是 mode-covering 的:模型被迫盖住训练集里出现过的每一种说法,代价是把概率摊到中间地带——那里没人真会那么说。⭐ 这是最大似然的固有性质,不是模型的缺陷。

🛑 可以停在这里

走神救援

KL(P‖Q) = 你拿 Q 的码本去编码真正来自 P 的消息,平均每条多付的比特数。沙漠天气(真实晴 80%/阴 15%/雨 5%,你以为三种一样多):最优码本 0.88 比特、错码本 1.58 比特,多付 0.70 —— 开销涨 79%。定义 D(P‖Q) = Σ P·log(P/Q)。四条性质:≥ 0 且仅 P=Q 时为 0、⭐不对称(所以叫散度不叫距离)、不满足三角不等式、⭐⭐P 有质量而 Q 给 0 概率 → ∞ 惩罚;反过来 P=0 处那一项恒为 0,Q 怎么胡来都不罚 —— 最后这条是一切的钥匙。⭐非对称的后果:P=(0.5,0.5)、Q=(0.99,0.01) 时 KL(P‖Q)=2.33 而 KL(Q‖P)=0.92 比特,差 2.5 倍。记忆法:期望在谁身上取,谁就是考官前向 KL(考官是真实数据,⭐最大似然和交叉熵最小化的正是它)→ mode-covering,宁滥勿缺:被迫盖住每个峰,概率糊到中间没数据的低谷上——语言模型的"平均脸"句子就是这么来的反向 KL(考官是模型自己,变分推断和 RLHF 惩罚项用它)→ mode-seeking,宁缺勿滥:只蹲一个峰,丢掉别的免费——VAE 后验偏窄也是这条。⭐RLHF mode collapse 的机理:惩罚项 KL(π‖π_SFT) 是反向 KL,罚「跑出参考模型支撑集」(该罚——出去了奖励模型没见过、分数不可信),但对「塌进一个峰」零惩罚;⚠️是选择的副作用,不是 bug。⭐⭐三个说法是同一件事交叉熵 = 熵 + KL,而 H(P) 与参数无关是常数;再用经验分布 P̂(每样本占 1/n)代入,剩下的正是平均负对数似然最小化 KL = 最小化交叉熵 = 最大化似然。所以交叉熵就是 KL 加一个你动不了的常数;分类的 one-hot 真实分布熵为 0,此时交叉熵与 KL 数值完全相等——你写的每一行 CrossEntropyLoss 都在最小化 KL。⭐ 副产品:既然用的是前向 KL,mode-covering 就是最大似然的固有性质

下一节 👉 02-MAP与正则化的真身.md ⭐⭐⭐

去那里的理由:本章和上一章都在「只看数据」的框架里。02 加进先验, 于是 L2 正则被还原成高斯先验、L1 被还原成拉普拉斯先验 —— 这是本板块公认最漂亮的一个结论。

打卡记录保存在你的浏览器里,首页能看到总进度