Skip to content

信息论基础:熵 / 交叉熵 / KL 散度

一句话:SFT 的损失是交叉熵、DPO 与 RLHF 的核心约束是 KL 散度、蒸馏本质是最小化 KL——这几个名词其实是同一套"用多少比特描述一个分布"的语言。本页用大白话把它们和「比特」串成一条线,读懂后再回头看正文的损失函数会清晰很多。

全站大量损失函数都建立在这几个概念上,但它们常被当成"已知"一笔带过。这里不堆公式,先讲清楚每个量到底在度量什么、为什么单位是"比特"、它们之间是什么关系。

一个统一的视角:信息 = "多惊讶"

信息论的出发点是一个朴素直觉:一件事越不可能发生,它真发生时带来的信息越多

  • "明天太阳照常升起"——几乎必然,说了等于没说,信息量≈0。
  • "明天本市下陨石"——概率极低,一旦发生信息量爆炸。

把这个直觉量化:一个概率为 p 的事件,它的**信息量(自信息)**定义为

math
I = \log_2 \frac{1}{p} = -\log_2 p .

log 是为了让"两件独立事件一起发生的信息量 = 各自信息量相加"(概率相乘 → 对数相加)。底数取 2 时,单位就叫比特(bit)

比特的真实含义:一个比特 = 一次"是/否"问答能消除的不确定性。概率 p=12 的事件信息量正好是 log212=1 比特——猜一次硬币正反,恰好需要问 1 个是非题。概率 18 的事件是 3 比特,因为要 3 个是非题才能锁定(23=8 选 1)。

机器学习里损失函数常用自然对数 ln(底数 e),此时单位叫 nat(奈特)。比特和 nat 只差一个常数 ln20.693,换算不影响任何优化结论,所以正文里 log 不特别标底数。

熵:一个分布"平均有多不确定"

单个事件有信息量,那一整个概率分布平均下来有多少信息量?这就是熵(entropy)——对自信息按概率求期望:

math
H(p) = \mathbb{E}_{x\sim p}\big[-\log p(x)\big] = -\sum_x p(x)\log p(x).

直觉上,熵衡量这个分布有多"乱"/多难猜

  • 一枚公平硬币,p=(0.5,0.5),熵 = 1 比特(最不确定,最难猜)。
  • 一枚作弊硬币,p=(0.99,0.01),熵 ≈ 0.08 比特(几乎总是正面,很好猜)。
  • 一枚必出正面的硬币,p=(1,0),熵 = 0(毫无悬念,零信息)。

换个工程视角:熵就是"用最优编码方案,平均每个样本最少需要多少比特才能存下来"。越确定的分布越好压缩,熵越低。

交叉熵:用"错"的分布去编码,要多花多少比特

现在出现两个分布:

  • p真实分布(数据里 token 实际的分布,训练时就是 one-hot 的标签)。
  • q模型预测的分布πθ 输出的 softmax 概率)。

交叉熵(cross-entropy) 衡量的是:真实数据来自 p,但你却按 q 的"以为"去编码,平均每个样本要花多少比特

math
H(p, q) = \mathbb{E}_{x\sim p}\big[-\log q(x)\big] = -\sum_x p(x)\log q(x).

注意区别:求期望用的是真实分布 p(事件实际怎么发生),但每个事件的"编码长度"用的是模型的 q(你以为它多稀奇)。模型猜得越准(q 越接近 p),交叉熵越小。

这正是 SFT 的损失。训练时真实标签是 one-hot(正确 token 概率为 1,其余为 0),交叉熵 xp(x)logq(x) 就只剩正确 token 那一项 logq(正确 token),于是逐 token 的交叉熵损失退化成负对数似然(NLL):

math
\mathcal{L}_{\text{SFT}}(\theta) = -\,\mathbb{E}_{(x, y) \sim \mathbb{D}} \left[ \sum_{t=1}^{\lvert y \rvert} \log \pi_\theta\big(y_t \mid x, y_{\lt t}\big) \right].

最小化交叉熵 = 让模型对正确 token 给出尽可能高的概率。详见 SFT 总览

KL 散度:两个分布"差多远"

交叉熵里其实混了两部分:数据本身的不确定性(熵 H(p),跟模型无关,改不了),加上模型猜不准带来的"额外开销"。把后者单独拎出来,就是 KL 散度(Kullback–Leibler divergence,相对熵)

math
\mathrm{KL}(p \,\|\, q) = \mathbb{E}_{x\sim p}\!\left[\log \frac{p(x)}{q(x)}\right] = \sum_x p(x)\log\frac{p(x)}{q(x)}.

它度量"q 冒充 p,平均每个样本多浪费了多少比特"。三个关键性质:

  1. 非负KL(pq)0,当且仅当 p=q 时为 0。两个分布越像,KL 越小。
  2. 不对称KL(pq)KL(qp)。所以它叫"散度"不叫"距离",写的时候必须分清谁在前。
  3. 它就是交叉熵减去熵——这是把三者拴在一起的核心恒等式。

把它们拴在一起:一行恒等式

math
\underbrace{H(p, q)}_{\text{交叉熵}} = \underbrace{H(p)}_{\text{真实分布的熵}} + \underbrace{\mathrm{KL}(p \,\|\, q)}_{\text{模型偏差}}.

用大白话讲这一行:

你按模型 q 去编码真实数据的总开销(交叉熵)= 数据本身不可压缩的成本(熵)+ 因为模型不准而多付的冤枉钱(KL 散度)。

由此就能理解为什么这些损失长成那样:

  • 训练 SFT 时为什么直接最小化交叉熵就行? 因为 H(p) 是数据固有的、跟参数 θ 无关的常数,最小化交叉熵 H(p,q) 完全等价于最小化 KL(pq)——也就是让模型分布去逼近数据分布。
  • 为什么蒸馏用 KL 而不用交叉熵? 蒸馏里"真实分布"是教师模型的软标签(不是 one-hot),H(p) 不再是常数,直接写成 KL(教师学生) 更干净,含义也更明确:让学生分布贴近教师分布。详见 蒸馏总览

困惑度(Perplexity):交叉熵的"指数版"

评测语言模型时最常听到的 困惑度(perplexity, PPL),其实不是新东西——它就是交叉熵取指数:

math
\text{PPL}(p, q) = e^{H(p, q)} = \exp\!\left(-\frac{1}{N}\sum_{t=1}^{N}\log q(y_t \mid y_{\lt t})\right).

为什么要多此一举取个指数?因为换了个更好懂的单位

  • 交叉熵活在对数尺度,单位是比特 / nat,回答"平均每个 token 要花多少比特";
  • 困惑度取指数回到线性尺度,回答"平均每一步,模型像是在多少个等可能选项里犹豫"——也就是"有效分支数"。

举例:一个模型在测试集上 PPL = 20,意思是它预测下一个词时的不确定程度,相当于每步都在 20 个等可能的词里挑。越低越好:完美模型 PPL = 1(每步都确定,毫不困惑),纯随机 N 选 1 的模型 PPL = N

所以这一页的几个量串起来就是一条链:自信息 → 熵 / 交叉熵(取期望)→ 困惑度(再取指数)。三者单调对应,最小化 SFT 的交叉熵损失,完全等价于最小化困惑度——这也是为什么 PPL 是语言模型最常用的内在评测指标。

在后训练里到处都是它

KL 散度在对齐阶段反复出现,作用都是同一个:当一把"别跑太远"的缰绳——既要优化目标,又不许新模型相对参考模型 πref 偏移太多,以免崩坏或钻奖励的空子。

出现位置KL 在干什么
SFT损失就是交叉熵 / NLL,等价于最小化 KL(数据|πθ)
PPO / RLHF奖励里加 βKL(πθ|πref) 惩罚项,防止策略偏离参考模型太远
DPO偏好损失中的 β 正是 KL 约束强度,公式里的对数概率比就是 KL 项的体现
蒸馏直接最小化学生与教师输出分布的 KL

这也解释了为什么 符号约定 里把 β 统一定义为"KL 约束强度 / 偏好优化温度系数"——它在不同算法里调的都是同一根缰绳的松紧。

一张速查表

公式一句话含义
自信息logp(x)单个事件有多"惊讶",单位比特
H(p)xplogp一个分布平均有多不确定 / 最少要多少比特存下
交叉熵 H(p,q)xplogqq 编码来自 p 的数据,平均要多少比特
KL 散度 KL(p|q)xplogpqq 冒充 p 多浪费多少比特(≥0,不对称)
困惑度 PPLeH(p,q)交叉熵取指数;模型平均在"多少个选项"里犹豫
核心关系H(p,q)=H(p)+KL(p|q)总开销 = 固有成本 + 模型偏差

读懂这张表,再去看 SFTDPOPPO蒸馏 的损失函数,就不会再被"交叉熵""KL"这些词卡住了。