信息论基础:自信息、信息熵、条件熵、互信息

聊压缩,绕不开信息论。很多人觉得这东西太数学,离工程很远。我刚开始做压缩的时候也这么想,直到有一次调一个流式压缩算法,怎么压都压不到目标大小,最后回头一算,才发现数据本身的熵已经锁死了压缩率上限。嗯,从那以后我再也不敢跳过信息论了。

说白了,信息论就是告诉你:这段数据理论上最少能压到多小。它不关心你用哪种算法,只关心数据本身的“信息量”。

2.1 自信息:一条消息到底有多“意外”

先看最基础的概念——自信息。它衡量的是单个事件发生所带来的信息量。

公式很简单:

I(x) = -log₂ P(x)

其中 P(x) 是事件 x 发生的概率。底数取 2,单位就是比特(bit)。

举个例子:

  • 如果明天太阳从东边升起,概率接近 1,log₂(1) = 0,自信息为 0。这件事说了等于没说。
  • 如果明天彩票中头奖,概率极低,自信息就很大。你想想看,一条“我中奖了”的消息,信息量远大于“我吃饭了”。
核心直觉:概率越小的事件,一旦发生,带来的信息量越大。压缩时,高频出现的内容应该用短码表示,低频内容用长码——这就是霍夫曼编码的底层逻辑。

我在项目中遇到过一个问题:有人把自信息直接当成压缩后的比特数来用,结果发现压出来的文件比理论值大很多。为什么?因为自信息只针对单个符号,而实际数据是一串符号,我们需要看整体。

2.2 信息熵:整个数据源的平均信息量

信息熵就是自信息的期望值。它衡量的是一个随机变量 X 的平均不确定性。

H(X) = -∑ P(x) · log₂ P(x)

这个值就是无损压缩的理论极限。任何无损压缩算法,平均每个符号需要的比特数都不可能低于 H(X)。

我习惯用一个例子来理解:

符号 概率 自信息 (bit)
A 0.5 1.0
B 0.25 2.0
C 0.25 2.0

熵值 H = 0.5×1.0 + 0.25×2.0 + 0.25×2.0 = 1.5 bit/符号。也就是说,无论你用多好的算法,平均每个符号至少需要 1.5 个比特。

避坑指南:我曾经看到有人用 8 位 ASCII 存一段只有 4 种字符的日志,熵只有 1.8 bit/字符,却用了 8 倍的空间。这就是典型的“没算熵”导致的浪费。先算熵,再选编码,这是基本功。

2.3 条件熵:知道一部分后,剩下的不确定性

现实中的数据往往有相关性。比如英文文本里,'q' 后面几乎一定是 'u'。如果你已经知道前一个字符是 'q',那么后一个字符的不确定性就大大降低了。

条件熵 H(Y|X) 衡量的就是:已知 X 的情况下,Y 还剩多少不确定性。

H(Y|X) = -∑ P(x, y) · log₂ P(y|x)

这个值在压缩中极其重要。为什么?

  • 如果 H(Y|X) 远小于 H(Y),说明 X 和 Y 高度相关。
  • 我们可以利用这种相关性来压缩——比如用前一个像素预测后一个像素,只存差值。

我记得有一次做图像压缩,直接对像素值编码,熵是 7.2 bit/像素。但换成差分编码后,条件熵降到了 3.1 bit/像素。这就是预测模型的价值。

2.4 互信息:两个变量共享了多少信息

互信息 I(X; Y) 是信息论里我最喜欢的概念之一。它衡量的是:知道 X 能减少多少对 Y 的不确定性。

I(X; Y) = H(Y) - H(Y|X)

也可以写成对称形式:

I(X; Y) = ∑∑ P(x, y) · log₂ [P(x, y) / (P(x) · P(y))]

互信息有几个关键性质:

  • 非负:I(X; Y) ≥ 0
  • 对称:I(X; Y) = I(Y; X)
  • 如果 X 和 Y 独立,互信息为 0
注意:互信息不是距离,它不满足三角不等式。它衡量的是“共享信息量”,而不是“差异”。在特征选择、字典设计、上下文建模中,互信息是筛选有用信息的黄金标准。

2.5 它们与压缩极限的关系

现在我们把四个概念串起来,看看它们如何定义压缩的边界。

核心结论就一句话:信息熵是无损压缩的理论下界。

具体来说:

  1. 自信息告诉你单个符号需要多少比特。
  2. 信息熵告诉你整个数据源的平均下界。
  3. 条件熵告诉你利用上下文后,下界还能降多少。
  4. 互信息告诉你两个变量之间有多少冗余可以消除。

你想想看,如果一个压缩算法声称能压到比熵还低,那只有两种可能:要么是有损压缩,要么是算法算错了。我见过有人拿一个随机数生成器“压缩”到 10%,结果解压出来全是错的——这就是没理解熵的含义。

工程启示:做压缩之前,先算一下数据的熵。如果当前算法已经接近熵值,就别再折腾无损优化了,该考虑有损压缩或者换数据表示方式。我曾经在一个日志压缩项目里,算完熵发现已经压到极限的 95%,果断放弃无损优化,改用列式存储+字典编码,最终压到了熵值的 60%——但那是另一回事了。

2.6 知识体系总览

下面这张图把四个概念的关系画清楚了,我建议你多看几遍:

信息论核心概念与压缩极限 自信息 I(x) = -log₂P(x) 信息熵 H(X) = -∑P·log₂P 条件熵 H(Y|X) 互信息 I(X;Y) = H(Y)-H(Y|X) 单个符号的信息量 → 平均得熵 利用上下文降低不确定性 → 条件熵更低 互信息 = 可消除的冗余量 → 压缩空间 = H(X) - I(X;Y) 无损压缩极限 = H(X) 利用条件熵可进一步降低

从图中你能看到一条清晰的脉络:自信息是基础,熵是平均,条件熵是带上下文的熵,互信息是熵的差值。它们共同定义了压缩的理论天花板。

我个人习惯在做任何压缩方案之前,先画一张这样的关系图,把数据源的概率分布、相关性、冗余类型都理清楚。这样选算法的时候才不会跑偏。

一句话总结:信息熵告诉你“最少需要多少比特”,条件熵告诉你“利用上下文还能省多少”,互信息告诉你“两个变量之间有多少冗余可以挖”。这三个值算清楚,压缩方案就成功了一半。