基础 · 03

概率与信息论的几何直觉

分布是形状,熵是它的「平」,交叉熵是「用 Q 描述 P 需要多少 bit」。一篇文章看清为什么 cross-entropy 是分类的天然损失。

14 min read

为什么 ML 是概率游戏

一个分类器看到一张图说「这是猫」,它真正在做的是输出一组概率:

softmax([z,z,z,z])=[0.87, 0.10, 0.02, 0.01]\mathrm{softmax}([z_{\text{猫}}, z_{\text{狗}}, z_{\text{鸟}}, z_{\text{鱼}}]) = [0.87,\ 0.10,\ 0.02,\ 0.01]

LLM 生成下一个 token 也一样——给词表里每个 token 都打一个概率,再从里面采样。所有现代 ML 模型的输出本质都是一个分布,不是「答案本身」。

要训练这种模型,就必须能回答:

  • 怎么衡量「这个分布有多不确定」? → 熵
  • 怎么衡量「模型预测的分布和真实分布有多接近」? → 交叉熵 / KL 散度

这两个量是分类、生成、强化学习几乎所有损失函数的底料。这篇就把它们画清楚。

分布:一个形状

把一个离散概率分布画成柱状图——每个柱子的高度就是那个事件发生的概率。这些柱子加起来必须等于 1。

骰子是均匀分布(6 个等高柱子)。一个有偏好的预测(比如「这张图大概率是猫」)是的(一根柱子很高,其他很矮)。

数学上,期望就是「按概率加权的平均」:

E[X]=ipixi\mathbb{E}[X] = \sum_i p_i \cdot x_i

可以理解为柱状图的重心——如果柱子是质量,期望就是平衡点。方差就是「柱子离重心有多远」的平均平方距离,衡量分布的铺开程度

但仅仅「铺开程度」还不够。我们需要一个更基本的量,直接衡量「这个分布到底有多不确定」——这就是熵。

熵:意外的平均

一个事件的「意外感」(self-information) 就是:

I(x)=log2p(x)I(x) = -\log_2 p(x)

概率越小,意外越大。 「明天太阳升起」 p1p \approx 1, I=0I = 0 bit, 一点不意外;「今天 GPT-7 发布」 p=1/1000p = 1/1000, I10I \approx 10 bit, 信息量大。底数取 2 让单位就是熟悉的 bit

把意外按概率加权平均,就是分布的:

H(P)=ipilog2pi=EP[I(X)]H(P) = -\sum_i p_i \log_2 p_i = \mathbb{E}_P[\,I(X)\,]

直觉一句话:熵 = 平均每次抽样,你需要花多少 bit 才能描述结果

  • 均匀分布 → 完全猜不准 → 熵最大(N 个等概率事件,熵 = log2N\log_2 N)。
  • 一点冲突都没有(某事件概率 1) → 闭着眼都能猜中 → 熵 = 0。

拖滑块感受:

46%
A
22%
B
14%
C
9%
D
6%
E
3%
F

熵 H(P)

2.10 bit

最大值 = log₂6 ≈ 2.58 bit(完全均匀时)

几乎能猜中 → 熵很低

熵 = 平均要花多少 bit 才能描述一次抽样。 分布越「平」,熵越大;越「尖」,熵越小。

熵是信息论的「主角色」。它不是抽象的——Shannon 在 1948 年证明,H(P)H(P) 就是用最优编码压缩这个分布的样本所需的平均比特数。换句话说,熵给出了「这个分布最少需要多少存储空间」的下界。

交叉熵:用 Q 描述 P

现在场景换一下:

真实分布是 PP,但我们手上只有一个估计的分布 QQ(模型的预测)。如果用为 QQ 设计的编码去压缩 PP 的样本,平均每次要花多少 bit?

答案就是交叉熵:

H(P,Q)=ipilog2qiH(P, Q) = -\sum_i p_i \log_2 q_i
  • 如果 Q=PQ = P,H(P,Q)=H(P)H(P, Q) = H(P)——最优情况,等于真分布的熵。
  • 如果 QPQ \neq P,H(P,Q)>H(P)H(P, Q) > H(P)——你用了错的编码,被惩罚了多余的 bit。
  • H(P,Q)H(P, Q) 永远 ≥ H(P)H(P)(这就是著名的 Gibbs 不等式)。

这就是为什么 ML 里分类的损失函数就是交叉熵:

L=ipilogqi\mathcal{L} = -\sum_i p_i \log q_i

真实标签是 one-hot,比如「猫」对应 P=[1,0,0,0]P = [1, 0, 0, 0]。这时:

L=logq\mathcal{L} = -\log q_{\text{猫}}

「最小化交叉熵」就翻译成了一句话:让模型预测真实类别的概率尽量大。LLM 训练里的 next-token loss 也是同一个公式,只是「类别」从「猫狗鸟鱼」换成了「词表里的几万个 token」。

试试调一下模型分布 Q,看 cross-entropy 怎么变:

P · 真实分布(固定)Q · 模型预测

Q 押注哪一类?

H(P) · 真实分布的熵

1.28 bit

H(P, Q) · 交叉熵

1.36 bit

KL(P ∥ Q) · 差距

0.07 bit

押对类但不够自信 → KL 还能更低

训练分类器 = 调 Q 让 H(P, Q) 尽量小。 最小值就是 H(P)——此时 Q = P,KL = 0。

KL 散度:两个分布的差距

把交叉熵和真分布的熵相减,得到一个非常有用的量:

DKL(PQ)=H(P,Q)H(P)=ipilog2piqiD_{\mathrm{KL}}(P \,\|\, Q) = H(P, Q) - H(P) = \sum_i p_i \log_2 \frac{p_i}{q_i}

这就是 KL 散度(Kullback–Leibler divergence)。

直觉上:

KL 是「用 QQ 而不是 PP 来描述 PP 时,多浪费了几个 bit」。

它有三个值得记住的性质:

  1. DKL0D_{\mathrm{KL}} \geq 0,等于 0 当且仅当 P=QP = Q。所以可以当「距离」用。
  2. 不对称: DKL(PQ)DKL(QP)D_{\mathrm{KL}}(P \,\|\, Q) \neq D_{\mathrm{KL}}(Q \,\|\, P)。所以不是真正的距离——选哪个方向有讲究。
  3. 训练分类器最小化交叉熵 = 最小化 KL 散度——因为 H(P)H(P) 在数据集固定时是常数。

第二条的不对称很微妙:DKL(PQ)D_{\mathrm{KL}}(P \,\|\, Q) 强迫 QQ 覆盖 PP 的所有支持区域(否则 logp/q\log p/q \to \infty);而 DKL(QP)D_{\mathrm{KL}}(Q \,\|\, P) 反过来,允许 QQ 只「贴」到 PP 的某个模态上。前者叫 mode-covering, 后者叫 mode-seeking——这在 VAE、扩散模型、GAN 里是核心的设计差异。

这个想法在前沿里