AI 工程基础体系 · 第 38/100 篇。内容覆盖机器学习、深度学习与生成式 AI;模型、数据、评测、权限和成本会作为同一生产系统处理。

AI 信息论基础:熵、交叉熵、KL 散度、互信息与编码直觉

信息论研究的是“不确定性如何被表示、传输和消除”。在机器学习中,它并不是一组只用于考试的公式:

  • 描述数据或随机变量本身有多不确定;
  • 交叉熵描述用概率模型 qq 表示真实分布 pp 时,平均需要付出多少信息代价;
  • KL 散度描述模型分布与真实分布之间的额外代价;
  • 互信息描述一个变量知道另一个变量后,不确定性减少了多少;
  • 编码直觉把这些量连接到压缩、预测、分类损失、语言模型困惑度和生成式 AI 的 token 概率。

理解这些概念前,需要先固定概率分布、对数和期望的含义。


1. 概率分布与信息量

设离散随机变量 XX 的取值集合为 X\mathcal X,概率分布为

p(x)=P(X=x)p(x)=P(X=x)

满足:

p(x)0,xXp(x)=1p(x)\ge 0,\qquad \sum_{x\in\mathcal X}p(x)=1

如果 XX 的某个结果概率很高,它并不令人意外;如果结果概率很低,它包含的信息通常更多。因此单个结果的信息量定义为:

I(x)=logp(x)I(x)=-\log p(x)

这里的对数底数决定单位:

  • log2\log_2:单位是 bit;
  • ln\ln:单位是 nat;
  • log10\log_{10}:单位是 hartley,机器学习中较少使用。

概率越小,logp(x)-\log p(x) 越大。例如使用 bit:

I(1)=log21=0I(1)=-\log_2 1=0

确定会发生的事件不提供新信息;而

I(1/1024)=log2(1/1024)=10I(1/1024)=-\log_2(1/1024)=10

表示这个结果需要约 10 bit 来描述。

信息量具有可加性。若两个事件独立,则:

I(x,y)=log[p(x,y)]=log[p(x)p(y)]=I(x)+I(y)I(x,y) =-\log[p(x,y)] =-\log[p(x)p(y)] =I(x)+I(y)

这也是对数在信息论中自然出现的原因。


2. 熵:随机变量平均有多少不确定性

2.1 离散熵的定义

离散随机变量 XX 的熵定义为信息量的期望:

H(X)=Exp[logp(x)]=xXp(x)logp(x)H(X) =E_{x\sim p}[-\log p(x)] =-\sum_{x\in\mathcal X}p(x)\log p(x)

熵不是某一次观测的信息量,而是长期重复观测时的平均信息量。

例如,公平硬币:

p()=p()=12p(正)=p(反)=\frac12

使用 bit:

H(X)=12log21212log212=1 bitH(X) =-\frac12\log_2\frac12 -\frac12\log_2\frac12 =1\text{ bit}

这表示每次投掷平均需要 1 bit 描述结果。

对于必然为正面的硬币:

p()=1,p()=0p(正)=1,\qquad p(反)=0

有:

H(X)=1log210log20=0H(X)=-1\log_2 1-0\log_2 0=0

其中约定 0log0=00\log 0=0,因为:

limp0+plogp=0\lim_{p\to 0^+}p\log p=0

确定结果没有不确定性,也不需要额外编码。


2.2 熵的范围与最大值

如果 XXKK 个可能取值,则:

0H(X)logK0\le H(X)\le \log K

当且仅当所有结果等概率时取得最大值:

p(x)=1Kp(x)=\frac1K

可以用 KL 散度证明这一点。设均匀分布为 u(x)=1/Ku(x)=1/K,则:

DKL(pu)=xp(x)logp(x)1/KD_{\mathrm{KL}}(p\|u) =\sum_xp(x)\log\frac{p(x)}{1/K}

展开:

DKL(pu)=xp(x)logp(x)+logK=H(X)+logKD_{\mathrm{KL}}(p\|u) =\sum_xp(x)\log p(x)+\log K =-H(X)+\log K

由于 KL 散度非负:

H(X)logKH(X)\le \log K

等号成立的条件是 p=up=u

这说明“类别越多”不自动意味着“熵越高”。类别数量只给出上界,真正的熵还取决于概率是否均匀。


2.3 一个完整算例:偏置硬币

设硬币正面概率为 0.90.9,反面概率为 0.10.1。使用 bit:

H(X)=0.9log20.90.1log20.10.9(0.152)0.1(3.322)0.469 bit\begin{aligned} H(X) &=-0.9\log_2 0.9-0.1\log_2 0.1\\ &\approx -0.9(-0.152)-0.1(-3.322)\\ &\approx 0.469\text{ bit} \end{aligned}

虽然每次仍有两个可能结果,但由于正面高度可预测,平均信息量只有约 0.4690.469 bit,而不是公平硬币的 1 bit。

注意:单次出现反面时的信息量为:

log20.13.322 bit-\log_2 0.1\approx 3.322\text{ bit}

这大于正面出现时的:

log20.90.152 bit-\log_2 0.9\approx 0.152\text{ bit}

熵是平均值,不能与某个具体样本的信息量混淆。


3. 条件熵:知道部分信息后还剩多少不确定性

对两个离散随机变量 X,YX,Y,条件熵定义为:

H(YX)=xp(x)H(YX=x)=x,yp(x,y)logp(yx)H(Y\mid X) =\sum_xp(x)H(Y\mid X=x) =-\sum_{x,y}p(x,y)\log p(y\mid x)

它表示已经知道 XX 后,YY 平均还剩多少不确定性。

联合熵为:

H(X,Y)=x,yp(x,y)logp(x,y)H(X,Y) =-\sum_{x,y}p(x,y)\log p(x,y)

利用联合概率分解:

p(x,y)=p(x)p(yx)p(x,y)=p(x)p(y\mid x)

可得链式法则:

H(X,Y)=x,yp(x,y)log[p(x)p(yx)]=x,yp(x,y)logp(x)x,yp(x,y)logp(yx)=H(X)+H(YX)\begin{aligned} H(X,Y) &=-\sum_{x,y}p(x,y)\log[p(x)p(y\mid x)]\\ &=-\sum_{x,y}p(x,y)\log p(x) -\sum_{x,y}p(x,y)\log p(y\mid x)\\ &=H(X)+H(Y\mid X) \end{aligned}

因此:

H(YX)=H(X,Y)H(X)H(Y\mid X)=H(X,Y)-H(X)

在经典离散概率中,知道更多变量不会增加剩余不确定性:

H(YX)H(Y)H(Y\mid X)\le H(Y)

但这句话只适用于条件熵的正确概率定义。工程中如果用有限样本估计熵,采样噪声可能导致估计值违反直觉,例如估计出的条件熵略高于边际熵。


4. 交叉熵:用 qq 描述来自 pp 的数据

4.1 定义

设真实分布为 pp,模型使用分布 qq。交叉熵定义为:

H(p,q)=Exp[logq(x)]=xp(x)logq(x)H(p,q) =E_{x\sim p}[-\log q(x)] =-\sum_xp(x)\log q(x)

关键区别是:

  • H(p)H(p) 使用真实概率 p(x)p(x) 编码真实分布;
  • 交叉熵 H(p,q)H(p,q) 使用模型概率 q(x)q(x) 编码来自真实分布 pp 的样本。

如果模型给真实事件很低的概率,logq(x)-\log q(x) 会很大,损失也会很大。


4.2 交叉熵与分类损失

KK 分类问题中,真实标签是 yy,模型输出概率为:

q1,,qK,kqk=1q_1,\ldots,q_K,\qquad \sum_kq_k=1

如果标签使用 one-hot 向量 pp,即正确类别 yy 的概率为 1,其余为 0,则单个样本的交叉熵为:

H(p,q)=k=1Kpklogqk=logqyH(p,q) =-\sum_{k=1}^Kp_k\log q_k =-\log q_y

因此常见的分类交叉熵损失,本质上就是正确类别负对数概率。

例如三分类样本的真实类别为第 2 类:

p=(0,1,0)p=(0,1,0)

模型预测:

q=(0.2,0.7,0.1)q=(0.2,0.7,0.1)

则:

L=log0.70.357 natL=-\log 0.7\approx 0.357\text{ nat}

如果模型预测为:

q=(0.49,0.01,0.50)q=(0.49,0.01,0.50)

虽然最大概率类别可能是第 3 类,且分类结果错误,但更重要的是正确类别概率只有 0.010.01,损失为:

log0.014.605 nat-\log 0.01\approx 4.605\text{ nat}

交叉熵因此不仅关注“猜对或猜错”,还惩罚错误的置信度。一个极度自信但错误的模型,损失会非常大。


4.3 从 logits 推导 softmax 交叉熵

神经网络通常输出 logits:

z=(z1,,zK)z=(z_1,\ldots,z_K)

而不是直接输出概率。softmax 定义为:

qk=ezkjezjq_k=\frac{e^{z_k}}{\sum_j e^{z_j}}

真实类别为 yy 时:

L=logqy=logezyjezj=zy+logjezj\begin{aligned} L &=-\log q_y\\ &=-\log\frac{e^{z_y}}{\sum_j e^{z_j}}\\ &=-z_y+\log\sum_j e^{z_j} \end{aligned}

这就是常说的 log-sum-exp 形式。

对某个 logit zkz_k 求导:

Lzk=qk1[k=y]\frac{\partial L}{\partial z_k}=q_k-\mathbf 1[k=y]

其中 1[k=y]\mathbf 1[k=y]k=yk=y 时为 1,否则为 0。于是:

  • 正确类别的梯度为 qy1q_y-1,会推动 zyz_y 增大;
  • 错误类别的梯度为 qkq_k,会推动其 logit 减小。

这解释了交叉熵为什么适合训练分类模型。

实际实现通常应直接使用框架提供的“带 logits 的交叉熵”接口,而不是先手动 softmax 再取 log。原因是:

e1000e^{1000}

可能溢出,而 log-sum-exp 可以通过减去最大 logit 稳定计算:

logjezj=m+logjezjm,m=maxjzj\log\sum_j e^{z_j} =m+\log\sum_j e^{z_j-m}, \qquad m=\max_jz_j


4.4 数据集交叉熵

NN 个样本,经验交叉熵通常为:

H^(p,q)=1Ni=1Nlogq(yixi)\hat H(p,q) =-\frac1N\sum_{i=1}^N\log q(y_i\mid x_i)

这也是平均负对数似然。最小化它等价于最大化训练数据的平均对数似然:

argminθ[1Nilogqθ(yixi)]=argmaxθilogqθ(yixi)\arg\min_\theta \left[-\frac1N\sum_i\log q_\theta(y_i\mid x_i)\right] = \arg\max_\theta \sum_i\log q_\theta(y_i\mid x_i)

这只是训练目标的等价变形,并不表示模型已经学到了真实世界分布。训练集偏差、标签噪声、分布偏移和数据泄漏仍然会影响结果。


5. KL 散度:模型相对真实分布多付出的代价

5.1 定义与交叉熵分解

KL 散度定义为:

DKL(pq)=xp(x)logp(x)q(x)D_{\mathrm{KL}}(p\|q) =\sum_xp(x)\log\frac{p(x)}{q(x)}

将对数拆开:

DKL(pq)=xp(x)logp(x)xp(x)logq(x)=H(p)+H(p,q)\begin{aligned} D_{\mathrm{KL}}(p\|q) &=\sum_xp(x)\log p(x)-\sum_xp(x)\log q(x)\\ &=-H(p)+H(p,q) \end{aligned}

因此:

H(p,q)=H(p)+DKL(pq)\boxed{H(p,q)=H(p)+D_{\mathrm{KL}}(p\|q)}

这个等式是机器学习中最重要的关系之一:

  • H(p)H(p) 是数据本身不可避免的平均信息量;
  • DKL(pq)D_{\mathrm{KL}}(p\|q) 是模型不准确造成的额外代价;
  • 交叉熵是二者之和。

由于 Gibbs 不等式:

DKL(pq)0D_{\mathrm{KL}}(p\|q)\ge 0

所以:

H(p,q)H(p)H(p,q)\ge H(p)

当且仅当 p=qp=q 时取等号。


5.2 支持集条件与无限损失

如果存在某个事件 xx,满足:

p(x)>0,q(x)=0p(x)>0,\qquad q(x)=0

则:

DKL(pq)=+D_{\mathrm{KL}}(p\|q)=+\infty

交叉熵同样为无穷大,因为真实会发生的事件被模型赋予了零概率。

这在生成式 AI 中尤其重要。一个语言模型如果对真实数据中会出现的 token 给出严格零概率,那么理论上的负对数似然会无限大。实际 softmax 在有限 logits 下通常产生严格正概率,但:

  • 词表裁剪;
  • 硬过滤;
  • 不正确的 token mask;
  • 解码阶段禁止某些 token;

都可能让某些真实序列变得不可表示。

训练和评测时,不能把“生成阶段的硬约束”直接当成无条件概率模型,否则可能破坏似然计算。


5.3 KL 不是距离

KL 散度常被称为“分布距离”,但它不是严格的距离,因为通常:

DKL(pq)DKL(qp)D_{\mathrm{KL}}(p\|q)\ne D_{\mathrm{KL}}(q\|p)

例如:

p=(0.9,0.1),q=(0.5,0.5)p=(0.9,0.1),\qquad q=(0.5,0.5)

使用 nat:

DKL(pq)=0.9ln0.90.5+0.1ln0.10.50.368D_{\mathrm{KL}}(p\|q) =0.9\ln\frac{0.9}{0.5} +0.1\ln\frac{0.1}{0.5} \approx 0.368

反向计算:

DKL(qp)=0.5ln0.50.9+0.5ln0.50.10.511D_{\mathrm{KL}}(q\|p) =0.5\ln\frac{0.5}{0.9} +0.5\ln\frac{0.5}{0.1} \approx 0.511

方向不能省略。

更直接的反例是:

p=(1,0),q=(0.5,0.5)p=(1,0),\qquad q=(0.5,0.5)

则:

DKL(pq)=ln2D_{\mathrm{KL}}(p\|q)=\ln 2

但:

DKL(qp)=+D_{\mathrm{KL}}(q\|p)=+\infty

因为反向 KL 会访问 qq 支持的第二个事件,而 pp 对该事件赋予了零概率。


5.4 为什么不同方向会产生不同模型行为

最小化:

DKL(pq)D_{\mathrm{KL}}(p\|q)

时,期望是在真实分布 pp 下计算的。真实分布支持的区域都必须被 qq 覆盖,否则会产生很大甚至无限的惩罚。这通常被描述为偏向“覆盖多个模式”。

最小化:

DKL(qp)D_{\mathrm{KL}}(q\|p)

时,期望是在模型分布 qq 下计算的。模型可以把概率集中到某个高密度模式,避开真实分布低概率区域,因此常表现出“偏向单个模式”的行为。

但“mode-cover”和“mode-seeking”是常见优化直觉,不是对所有参数化模型和优化过程的绝对定理。模型容量、目标函数、近似误差和优化算法都会影响最终行为。


5.5 机器学习中的 KL 用法

知识蒸馏中,教师模型给出软分布 pTp_T,学生模型输出 qSq_S,可以最小化:

DKL(pTqS)D_{\mathrm{KL}}(p_T\|q_S)

这会让学生不仅学习硬标签,还学习教师对“其他类别”的相对判断。

变分自编码器中,常见目标包含:

DKL(qϕ(zx)p(z))D_{\mathrm{KL}}\bigl(q_\phi(z\mid x)\|p(z)\bigr)

它约束编码器产生的潜变量分布不要偏离先验过远。这里的方向是模型设计的一部分,不能随意交换。

分布漂移检测中,可以比较时间窗口或人群切片的离散分布。但直接使用 KL 前必须处理零计数、平滑和样本量问题,否则一个未观测类别就可能导致无穷大或极不稳定的结果。


6. 互信息:一个变量能减少另一个变量多少不确定性

6.1 定义

随机变量 X,YX,Y 的互信息定义为:

I(X;Y)=H(X)H(XY)I(X;Y) =H(X)-H(X\mid Y)

利用链式法则,也可以写成:

I(X;Y)=H(Y)H(YX)I(X;Y)=H(Y)-H(Y\mid X)

还可以写成联合分布与独立分布之间的 KL 散度:

I(X;Y)=DKL(p(x,y)p(x)p(y))\boxed{ I(X;Y) = D_{\mathrm{KL}}\bigl(p(x,y)\|p(x)p(y)\bigr) }

展开:

I(X;Y)=x,yp(x,y)logp(x,y)p(x)p(y)\begin{aligned} I(X;Y) &=\sum_{x,y}p(x,y) \log\frac{p(x,y)}{p(x)p(y)} \end{aligned}

因此:

I(X;Y)0I(X;Y)\ge 0

且当且仅当:

p(x,y)=p(x)p(y)p(x,y)=p(x)p(y)

也就是 X,YX,Y 独立时,互信息为 0。

互信息是对称的:

I(X;Y)=I(Y;X)I(X;Y)=I(Y;X)

这与 KL 散度的非对称性不同。


6.2 完整算例:完全相关与独立变量

X,YX,Y 都是公平二值变量。

情形一:Y=XY=X

联合分布只有两个可能结果:

P(X=0,Y=0)=12,P(X=1,Y=1)=12P(X=0,Y=0)=\frac12,\qquad P(X=1,Y=1)=\frac12

由于知道 XX 后就完全知道 YY

H(YX)=0H(Y\mid X)=0

H(Y)=1H(Y)=1 bit,因此:

I(X;Y)=10=1 bitI(X;Y)=1-0=1\text{ bit}

这表示 XX 完整解释了 YY 的不确定性。

情形二:X,YX,Y 独立

四种组合概率均为 1/41/4。知道 XX 不会改变 YY 的分布:

H(YX)=H(Y)=1 bitH(Y\mid X)=H(Y)=1\text{ bit}

所以:

I(X;Y)=0I(X;Y)=0


6.3 互信息不等于相关系数

线性相关系数只刻画特定的线性关系,而互信息刻画一般依赖关系。

一个重要例子是 XOR:

X,YBernoulli(1/2),Z=XYX,Y\sim\mathrm{Bernoulli}(1/2),\qquad Z=X\oplus Y

对单独的 XXYY,都有:

I(X;Z)=0,I(Y;Z)=0I(X;Z)=0,\qquad I(Y;Z)=0

因为只知道其中一个输入,ZZ 仍然等可能为 0 或 1。

但联合知道 X,YX,Y 后,ZZ 完全确定:

I((X,Y);Z)=H(Z)=1 bitI((X,Y);Z)=H(Z)=1\text{ bit}

因此“每个特征单独与标签互信息低”并不意味着“这些特征组合后没有预测能力”。这也是单变量特征筛选可能漏掉交互特征的原因。


6.4 互信息与特征、表示和生成模型

在特征选择中,可以估计:

I(Xj;Y)I(X_j;Y)

筛选与标签相关的特征。但高互信息不等于因果关系,也不等于部署后稳定。一个特征可能通过时间泄漏、用户 ID 或权限范围外的数据获得很高互信息,却无法在真实预测时使用。

在表示学习中,常见目标是让表示 ZZ 保留任务相关信息:

I(Z;Y)I(Z;Y)

同时限制不希望保留的信息,例如敏感属性 SS

I(Z;S)I(Z;S)

不过这些量通常难以直接准确估计,实际方法依赖变分上界、对比学习目标或分类器近似。近似目标下降,不自动证明真实互信息已经按同样幅度下降。

在生成模型中,条件生成分布为:

p(xc)p(x\mid c)

条件 cc 是否有用,可以从不确定性减少来理解:

I(X;C)=H(X)H(XC)I(X;C)=H(X)-H(X\mid C)

如果条件信息与目标无关,理想模型不会因为它而显著降低预测熵;如果条件包含关键信息,条件分布会比无条件分布更集中。


7. 编码直觉:为什么这些公式等于“平均描述长度”

7.1 前缀编码与 Kraft 不等式

考虑二进制前缀码。前缀码要求一个码字不能是另一个码字的前缀,这样接收方才能无歧义地解码。

若每个事件 xx 的码长为 l(x)l(x),Kraft 不等式要求:

x2l(x)1\sum_x2^{-l(x)}\le 1

对于概率 p(x)p(x),理想码长是:

l(x)=log2p(x)l^*(x)=-\log_2p(x)

但它不一定是整数。实际可以取:

l(x)=log2p(x)l(x)=\lceil-\log_2p(x)\rceil

其期望码长满足:

H2(X)E[l(X)]<H2(X)+1H_2(X)\le E[l(X)]<H_2(X)+1

其中 H2H_2 表示使用 bit 的熵。

含义是:已知真实分布后,长期平均编码长度可以接近熵,但单个码字必须是整数长度,通常会产生少量舍入开销。

严格地说,经典结论通常针对无失真前缀编码和足够长的独立同分布序列;单个样本、有限块长和具体编码器可能有额外开销。


7.2 用错误分布编码:交叉熵是平均码长

假设数据真实来自 pp,但编码器按 qq 设计理想码长:

lq(x)=log2q(x)l_q(x)=-\log_2q(x)

那么真实平均码长为:

Exp[lq(x)]=xp(x)(log2q(x))=H2(p,q)E_{x\sim p}[l_q(x)] =\sum_xp(x)(-\log_2q(x)) =H_2(p,q)

结合分解式:

H2(p,q)=H2(p)+DKL,2(pq)H_2(p,q)=H_2(p)+D_{\mathrm{KL},2}(p\|q)

因此,错误模型造成的额外平均码长就是:

DKL,2(pq)D_{\mathrm{KL},2}(p\|q)

这不是比喻,而是概率建模与通用编码之间的数学对应。


7.3 自回归语言模型与 token 编码

对 token 序列 x1:Tx_{1:T},链式法则给出:

p(x1:T)=t=1Tp(xtx<t)p(x_{1:T}) =\prod_{t=1}^Tp(x_t\mid x_{<t})

取负对数:

logp(x1:T)=t=1Tlogp(xtx<t)-\log p(x_{1:T}) = \sum_{t=1}^T-\log p(x_t\mid x_{<t})

所以语言模型的 token 级交叉熵,就是序列总负对数似然,也可以理解为在已知前文时逐 token 编码的总平均代价。

如果平均每个 token 的交叉熵是 LL nat,则困惑度定义为:

PPL=eL\mathrm{PPL}=e^L

如果交叉熵用 bit,则:

PPL=2L\mathrm{PPL}=2^L

困惑度不是“模型知道的词汇数量”,而是指数化的平均 token 预测不确定性。不同 tokenizer、文本切分、数据领域和评测集合之间的困惑度通常不能直接横向比较。


8. 交叉熵、准确率与校准的差异

准确率只观察:

argmaxkqk\arg\max_k q_k

而交叉熵观察正确类别的完整概率 qyq_y

考虑两个预测:

q(1)=(0.51,0.49),q(2)=(0.99,0.01)q^{(1)}=(0.51,0.49),\qquad q^{(2)}=(0.99,0.01)

如果第一类是真实标签,二者准确率都为 1,但损失分别为:

ln0.510.673-\ln 0.51\approx0.673

和:

ln0.990.010-\ln0.99\approx0.010

第二个模型不仅预测正确,而且更确信;在大量样本上,交叉熵会奖励这种概率质量。

反过来,如果第二个预测在真实标签为第二类时出错,其损失为:

ln0.014.605-\ln0.01\approx4.605

这说明交叉熵对过度自信的错误非常敏感。

校准描述预测概率是否具有频率意义。例如,模型对许多样本都预测“置信度约 0.8”,如果这些样本实际约 80% 正确,则模型较校准。交叉熵通常能反映概率质量,但单独一个交叉熵数值不能完整诊断校准,仍需结合可靠性图、分桶统计或 Brier score 等指标。


9. 标签平滑、软标签与交叉熵

硬标签的真实分布为 one-hot:

py=1,pk=0  (ky)p_y=1,\qquad p_k=0\;(k\ne y)

标签平滑会改为:

py=1ε,pk=εK1  (ky)p_y=1-\varepsilon,\qquad p_k=\frac{\varepsilon}{K-1}\;(k\ne y)

此时损失为:

L=(1ε)logqykyεK1logqkL =-(1-\varepsilon)\log q_y -\sum_{k\ne y}\frac{\varepsilon}{K-1}\log q_k

它不再要求模型把全部概率集中到一个类别,通常可以降低过度自信。

但标签平滑不是无条件改进:

  • 如果标签本来非常准确,过度平滑可能限制可达到的概率质量;
  • 如果类别极不平衡,均匀分配平滑质量可能不符合真实先验;
  • 训练目标改变后,训练交叉熵与原始 one-hot 评测损失不再完全对应。

软标签还可以来自教师模型、人类分布式标注或多答案数据。此时交叉熵更接近拟合一个条件分布,而不是拟合唯一“正确类别”。


10. 生成式 AI 中的条件概率、采样与信息量

10.1 训练损失与生成结果不是同一件事

语言模型训练通常最小化:

tlogpθ(xtx<t)-\sum_t\log p_\theta(x_t\mid x_{<t})

这要求模型为真实训练 token 分配高概率。

生成时却通常从模型分布采样,或使用贪心、beam search、top-kk、top-pp 等解码策略。解码会改变实际输出分布,因此:

  • 训练交叉熵评估的是模型对参考序列的概率;
  • 生成质量还受搜索策略、重复惩罚、停止条件和安全过滤影响;
  • 低困惑度不保证事实正确、风格合适或满足权限约束。

如果生成系统在运行时截断候选 token,它实际采样的分布可能是重归一化后的分布,而不是原始模型分布。分析成本、质量和安全行为时,需要区分模型分布与解码后分布。


10.2 温度如何改变熵

给定 logits zkz_k,温度 T>0T>0 的分布为:

qk(T)=exp(zk/T)jexp(zj/T)q_k^{(T)} = \frac{\exp(z_k/T)} {\sum_j\exp(z_j/T)}

  • T>1T>1:分布更平,熵通常增加;
  • 0<T<10<T<1:分布更尖,熵通常降低;
  • T0+T\to0^+:趋向于最大 logit 的贪心选择;
  • TT\to\infty:趋向于均匀分布。

“熵通常增加或降低”需要限定为改变温度的典型 softmax 情况;如果叠加候选截断、过滤或特殊约束,最终分布还取决于这些操作。


11. 一个可运行的 NumPy 示例

下面代码实现离散熵、交叉熵、KL 散度和互信息,并验证关键等式。前置条件是 Python 3 和 NumPy。

import numpy as np

def normalize(p):
    p = np.asarray(p, dtype=float)
    if np.any(p < 0):
        raise ValueError("probabilities must be non-negative")
    total = p.sum()
    if total <= 0:
        raise ValueError("probabilities must have positive sum")
    return p / total

def entropy(p, base=np.e):
    p = normalize(p)
    positive = p > 0
    value = -np.sum(p[positive] * np.log(p[positive]))
    return value / np.log(base)

def cross_entropy(p, q, base=np.e):
    p = normalize(p)
    q = normalize(q)
    if np.any((p > 0) & (q <= 0)):
        return np.inf
    positive = p > 0
    value = -np.sum(p[positive] * np.log(q[positive]))
    return value / np.log(base)

def kl_divergence(p, q, base=np.e):
    return cross_entropy(p, q, base) - entropy(p, base)

def mutual_information(joint, base=np.e):
    joint = np.asarray(joint, dtype=float)
    if np.any(joint < 0) or joint.sum() <= 0:
        raise ValueError("joint distribution must be non-negative and non-empty")

    joint = joint / joint.sum()
    px = joint.sum(axis=1, keepdims=True)
    py = joint.sum(axis=0, keepdims=True)
    product = px @ py

    positive = joint > 0
    value = np.sum(joint[positive] * np.log(
        joint[positive] / product[positive]
    ))
    return value / np.log(base)

p = np.array([0.9, 0.1])
q = np.array([0.5, 0.5])

print("H(p)       =", entropy(p, base=2), "bits")
print("H(p, q)    =", cross_entropy(p, q, base=2), "bits")
print("KL(p || q) =", kl_divergence(p, q, base=2), "bits")
print("check      =", entropy(p, base=2) + kl_divergence(p, q, base=2))

joint = np.array([
    [0.5, 0.0],
    [0.0, 0.5],
])
print("I(X;Y)     =", mutual_information(joint, base=2), "bits")

对于前面的偏置硬币和均匀模型,输出应接近:

H(p)       = 0.4689955935892812 bits
H(p, q)    = 1.0 bits
KL(p || q) = 0.5310044064107188 bits
check      = 1.0
I(X;Y)     = 1.0 bits

这里的 check 验证:

H(p,q)=H(p)+DKL(pq)H(p,q)=H(p)+D_{\mathrm{KL}}(p\|q)

joint 矩阵中只有 (0,0)(0,0)(1,1)(1,1) 有概率,表示 Y=XY=X,所以互信息为 1 bit。

代码中对 p=0 的项进行了跳过,这是数学约定 0log0=00\log 0=0 的实现。对于 q=0p>0 的情况,函数返回无穷大,而不是静默加一个很小的数;生产代码若使用平滑,应明确记录平滑策略,因为它会改变被评估的分布。


12. 连续变量:微分熵不能简单照搬离散熵

对于连续随机变量,概率质量函数被概率密度 f(x)f(x) 替代。微分熵定义为:

h(X)=f(x)logf(x)dxh(X)=-\int f(x)\log f(x)\,dx

它与离散熵有相似形式,但性质不同:

  1. 微分熵可以为负;
  2. 它依赖坐标单位;
  3. 对连续变量做可逆变换时不保持不变;
  4. 它不直接等于有限比特的无损编码长度。

例如把长度单位从米改成毫米,密度会发生缩放,微分熵也会随之变化。因此不能把连续变量的微分熵直接解释为“这个物理量需要多少 bit”。

连续分布之间的 KL 散度仍然定义为:

DKL(pq)=p(x)logp(x)q(x)dxD_{\mathrm{KL}}(p\|q) = \int p(x)\log\frac{p(x)}{q(x)}\,dx

它具有非负性,并且在适当条件下具有坐标变换不变性。连续变量互信息也仍可写作:

I(X;Y)=DKL(p(x,y)p(x)p(y))I(X;Y) = D_{\mathrm{KL}}\bigl(p(x,y)\|p(x)p(y)\bigr)

这也是为什么在表示学习和变分推断中,KL 与互信息通常比单独的微分熵更稳健、更有解释力。


13. 估计这些量时最容易出错的地方

13.1 对数底数不一致

ln\ln 得到 nat,用 log2\log_2 得到 bit:

Hbit=Hnatln2H_{\text{bit}}=\frac{H_{\text{nat}}}{\ln 2}

如果训练损失用 nat,却拿它直接和 bit 形式的熵比较,数值会相差约 ln2\ln 2 或其倒数。比较论文、模型或服务指标时必须注明单位。


13.2 平均方式不一致

token 级交叉熵可能按:

  • 所有有效 token 平均;
  • 每条序列先平均,再对序列平均;
  • 包含或排除 padding;
  • 按字符、词、token 统计。

这些定义不相同。尤其在序列长度差异很大时,“每条序列等权”和“每个 token 等权”会产生不同结果。


13.3 用 argmax 概率代替完整分布

互信息、KL 和交叉熵都依赖完整概率分布。把模型输出只保留最大类别,会丢失不确定性结构。

例如:

(0.51,0.49)(0.99,0.01)(0.51,0.49) \quad\text{和}\quad (0.99,0.01)

argmax 结果相同,但熵、交叉熵和校准行为完全不同。


13.4 有限样本互信息估计偏差

如果 X,YX,Y 的类别很多而样本很少,联合频数表会非常稀疏。直接用经验频率计算互信息可能:

  • 高估或低估真实依赖;
  • 对偶然共现非常敏感;
  • 产生大量零概率;
  • 在切分数据后不稳定。

连续高维变量的互信息估计更困难,常见方法包括离散化、核密度、近邻估计和神经估计器,但每种方法都有偏差、方差或优化稳定性问题。互信息估计值下降时,必须同时检查样本量、估计器和随机种子,不能只看一个数字。


13.5 训练集交叉熵低不等于泛化好

训练交叉熵下降表示模型提高了对训练样本的概率分配,但可能发生:

  • 记忆训练样本;
  • 标签泄漏;
  • 训练和验证分布不同;
  • 评测文本出现在预训练数据中;
  • 数据切分跨越同一用户、同一文档或同一时间实体。

生产评测应明确数据来源、时间切分、用户隔离、权限边界和去重策略。否则一个很低的交叉熵可能只是数据泄漏的结果。


14. 从信息量到生产系统:模型、数据、评测、权限与成本

信息论指标不能脱离生产系统解释。

14.1 数据权限会改变可用分布

如果某类数据只有特定用户或租户有权访问,那么训练和评测时使用这类数据不仅是数据问题,也是权限问题。即使它显著降低预测熵或提高互信息,也不能据此绕过访问控制。

对于检索增强生成系统,实际条件分布更接近:

p(answerquery,authorized context)p(\text{answer}\mid \text{query},\text{authorized context})

而不是:

p(answerquery,all available context)p(\text{answer}\mid \text{query},\text{all available context})

把无权访问的上下文加入训练、日志或离线评测,可能让交叉熵变低,却使线上系统违反权限约束。


14.2 token 熵不等于 token 成本

语言模型的 token 数量直接影响推理成本、延迟和上下文占用;token 熵描述的是预测不确定性。两者相关但不等价:

  • 长文本可能每个 token 都很容易预测,但成本仍然高;
  • 短文本可能存在高不确定性,但 token 成本不一定高;
  • 采样策略改变输出长度和重复率,也会改变成本;
  • 缓存、批处理、模型大小和服务商计费规则会进一步影响总成本。

因此生产监控至少要区分:

平均 NLL/token,输入 token 数,输出 token 数,延迟,实际计费\text{平均 NLL/token} ,\quad \text{输入 token 数} ,\quad \text{输出 token 数} ,\quad \text{延迟} ,\quad \text{实际计费}

不能用困惑度或熵单独替代成本指标。


14.3 不确定性不能直接当成风险概率

高熵表示模型分布更分散,低熵表示模型更集中,但低熵不代表答案真实。模型可能对错误事实非常自信。

风险评估需要结合:

  • 事实核验;
  • 任务特定准确率;
  • 置信度校准;
  • 拒答和升级策略;
  • 权限与审计;
  • 对抗和分布外测试。

信息论指标描述概率结构,不自动提供因果、事实性或合规保证。


15. 一张关系图

flowchart LR
    P["真实分布 p"] --> H["熵 H(p)<br/>真实不确定性的平均信息量"]
    P --> CE["交叉熵 H(p,q)<br/>用 q 编码来自 p 的数据"]
    Q["模型分布 q"] --> CE
    CE --> Decomp["H(p,q) = H(p) + KL(p || q)"]
    P --> KL["KL 散度<br/>模型造成的额外编码代价"]
    Q --> KL

    X["变量 X"] --> MI["互信息 I(X;Y)<br/>知道一个变量后减少的不确定性"]
    Y["变量 Y"] --> MI
    MI --> MI2["I(X;Y)=KL(p(x,y) || p(x)p(y))"]

    CE --> CLS["分类交叉熵<br/>-log q(y|x)"]
    CE --> LM["语言模型 NLL<br/>sum_t -log q(x_t|x_<t)"]
    LM --> PPL["困惑度<br/>exp(平均 NLL)"]

图中的核心路径是:

  1. 真实分布自身有熵;
  2. 模型用 qq 预测真实样本时产生交叉熵;
  3. 交叉熵比真实熵多出的部分是 KL 散度;
  4. 互信息则把“联合分布是否偏离独立分布”表示成 KL 散度;
  5. 分类和语言建模损失都是交叉熵在不同输出结构下的具体形式。

16. 最容易混淆的结论

熵不是准确率。
熵描述整个概率分布的不确定性;准确率只看最大概率类别是否正确。

交叉熵不是熵。
只有当 q=pq=p 时,交叉熵才等于真实熵。一般情况下:

H(p,q)H(p)H(p,q)\ge H(p)

KL 散度不是对称距离。
写出 DKL(pq)D_{\mathrm{KL}}(p\|q) 时,必须说明谁是真实分布、谁是近似分布。

互信息为零表示独立,而不是“没有线性相关”。
它检测的是一般统计依赖;零互信息比零相关更强。

低损失不保证可靠。
损失可能因数据泄漏、权限越界、评测分布过窄或模型过度自信而虚假变好。

困惑度依赖 tokenizer 和评测协议。
不同 token 粒度、文本过滤和平均方式下,数值不能直接比较。

把这些概念统一起来,可以得到一个简洁框架:

熵:数据本身有多不确定\boxed{ \text{熵:数据本身有多不确定} }

交叉熵:用模型概率描述数据的平均代价\boxed{ \text{交叉熵:用模型概率描述数据的平均代价} }

KL:相对理想分布多付出的代价\boxed{ \text{KL:相对理想分布多付出的代价} }

互信息:一个变量能消除另一个变量多少不确定性\boxed{ \text{互信息:一个变量能消除另一个变量多少不确定性} }

编码:上述量都可以理解为平均描述长度或额外描述长度\boxed{ \text{编码:上述量都可以理解为平均描述长度或额外描述长度} }

这组关系构成了从概率预测、分类训练、语言模型评测,到压缩、表示学习和生成式 AI 的共同数学基础。


系列导航与关联阅读

官方资料

本文依据研究论文、标准组织与主流框架官方文档重新梳理;正文、示例与工程清单由 WR BLOG 编写。