压缩即智能:从信息熵到世界模型的预测与理解 1. 从一句反直觉的断言说起为什么压缩能等同于智能第一次看到压缩即智能这个说法大多数人的反应是困惑——压缩不就是把文件变小吗跟智能有什么关系我当初也是这个反应。但如果你真的动手写过压缩算法或者认真琢磨过预测模型的工作原理你会发现这两件事在数学底层几乎是同一件事。这个系列我打算用几章的篇幅把智能的本质是压缩这条线索从头到尾捋一遍。第一章先解决最核心的问题信息熵到底在度量什么它和理解之间是什么关系以及为什么一个足够好的世界模型本质上就是一个足够好的压缩器。适合谁来读如果你写过一点代码对机器学习有模糊的认知但总觉得熵KL散度最小描述长度这些词飘在空中落不了地那这篇就是写给你的。我不打算堆公式而是尽量用你手上正在做的事来解释这些概念为什么非出现不可。先说结论后面慢慢展开一个系统对世界的理解程度可以用它预测下一个观测值时节省了多少信息量来衡量。预测得越准需要的存储越少压缩率越高——而预测得准恰恰就是我们说一个系统聪明的日常含义。这个等价关系不是哲学比喻它有严格的数学形式。接下来我会一层层把它拆开。2. 信息熵把意外程度变成一个可以计算的数2.1 从今天下雨吗这个最朴素的问题入手假设你住在一个常年干旱的地方一年365天里只有5天下雨。我问你明天会下雨吗你几乎可以闭着眼睛回答不会。这个回答几乎不携带任何信息因为结果高度可预测。换一个地方一年里有一半时间在下雨。同样的问题你的回答就变得有价值了——它真的在传递信息。香农的天才之处在于他把这种意外程度变成了一个可以精确计算的量。一个事件发生的概率是 p它携带的信息量就是 -log(p)。概率越接近1信息量越接近0概率越小信息量越大。这个定义不是拍脑袋来的。它必须满足几个直觉上合理的要求必然发生的事件信息量为零两个独立事件的信息量应该可以相加信息量应该连续依赖于概率。满足这三条的数学形式本质上只有 -log(p) 这一种差一个常数倍。所以熵不是一个发明而是一个发现——它是唯一合理的选择。2.2 熵是平均意外程度不是混乱程度很多人把熵通俗地解释成混乱程度这个说法在热力学里勉强能用但在信息论里会误导人。熵的准确定义是在你知道概率分布的前提下对下一个符号进行最优编码时平均每个符号需要的最少比特数。注意这里有两个关键限定。第一你知道概率分布——熵是相对于一个模型而言的。第二最优编码——它衡量的是理论下界不是某个具体算法的表现。举个能算的例子。假设一个信源只发两种符号 A 和 BA 出现的概率是 0.9B 是 0.1。那么A 的信息量 -log2(0.9) ≈ 0.152 比特B 的信息量 -log2(0.1) ≈ 3.322 比特平均熵 0.9 × 0.152 0.1 × 3.322 ≈ 0.469 比特也就是说虽然每个符号理论上可以用1个比特表示0和1但因为这个信源高度偏向A实际上平均只需要0.469比特就能无损编码。省下来的那一半多就是从可预测性里榨出来的。2.3 为什么这个数字是压缩的物理下限这里有个容易被忽略的点熵给出的下界是无损压缩的下界。你不可能用比熵更少的比特无损地表示这个信源这是香农信源编码定理保证的。我实测过一个很直观的对比。拿一段英文文本用最朴素的定长编码每个字符8比特存储和用基于字符频率的霍夫曼编码存储后者通常能压到原来的55%到65%。而英文文本的字符级熵大约在4.0到4.5比特/字符之间也就是说理论极限能压到50%出头。霍夫曼编码之所以达不到极限是因为它按单个字符编码没有利用字符之间的相关性——比如q后面几乎总是u。这就引出了下一节的核心要突破单符号熵的限制你必须建模符号之间的关系。而建模关系就是理解的开始。3. 条件熵与互信息预测能力如何被量化3.1 从独立编码到看着上文编码单符号熵假设每个符号独立出现。但真实世界的数据几乎从不独立——文字有语法图像有空间连续性音频有频谱结构。当你利用这些结构时你实际上是在做条件编码给定前面的内容预测下一个符号。条件熵 H(X|Y) 度量的是在已知 Y 的情况下X 还剩下多少不确定性。如果 Y 能完美预测 X条件熵为0如果 Y 对 X 毫无帮助条件熵等于原来的熵。互信息 I(X;Y) H(X) - H(X|Y)正好度量了知道 Y 之后关于 X 的不确定性减少了多少。这个量是对称的也是非负的。3.2 一个能亲手验证的小实验你可以用一段文本做这个实验感受一下条件熵的威力。第一步统计单个字符的频率分布算出字符级熵。英文大概在4.1比特左右。第二步统计每个字符在前一个字符已知条件下的分布算出条件熵 H(X_i | X_{i-1})。这个值会降到大约3.3比特。第三步把条件扩展到前两个、前三个字符。条件熵会继续下降但边际收益递减。到前五个字符左右英文的条件熵会逼近1.0到1.5比特/字符这个区间。这个逐步下降的过程就是模型在变聪明的过程。每多利用一点上下文就多榨出一点可预测性压缩率就更高一点。一个能利用无限长上下文的模型理论上能把英文压到接近其真实熵——而那个真实熵恰恰就是英语这门语言的全部规律的信息量。3.3 预测即压缩的严格对应现在可以把这个对应关系说清楚了。任何压缩算法都可以拆成两部分一个概率模型对下一个符号给出概率分布和一个编码器根据概率分布把符号映射成比特。给定概率模型最优编码器的平均码长就是模型预测分布的交叉熵。模型预测得越准交叉熵越低压缩率越高。反过来任何压缩器都隐含一个概率模型——你从它的输出反推总能得到一个对数据的概率分布。所以预测和压缩不是类比关系是同一件事的两种说法。一个模型对世界的理解越深它对下一个观测的预测分布就越接近真实分布它能达到的压缩率就越接近真实熵。这里有个容易踩的坑很多人以为压缩率高就等于模型好。但如果你的模型过拟合了训练数据它在训练集上压缩率极高在新数据上却崩掉。真正衡量理解程度的是在未见过的数据上的压缩率。这一点后面讲世界模型时会反复用到。4. 最小描述长度奥卡姆剃刀的数学化4.1 最简单的解释最好到底怎么算奥卡姆剃刀说如无必要勿增实体。这句话在哲学上很漂亮但没法直接用来做工程决策——什么叫必要多复杂算增实体最小描述长度MDL原理给了它一个可计算的版本。核心思想是最好的模型是能把模型本身加上用这个模型编码数据的总长度压到最短的那个。总描述长度 L(模型) L(数据|模型)第一项是描述模型本身需要的比特数第二项是用这个模型编码数据需要的比特数。模型越复杂第一项越大但模型越强第二项越小。最优模型在这个权衡中找到平衡点。4.2 为什么这一项模型本身的长度如此关键这一项是很多人忽略的。举个极端例子假设你有一个模型它把整段数据直接背下来了预测时查表就行。那么 L(数据|模型) 0压缩率完美。但 L(模型) 等于数据本身的长度——你只是把数据从左边口袋挪到了右边口袋总长度没变。这就是过拟合的本质你把复杂度从数据拟合项转移到了模型描述项总账没省。真正有价值的模型是能用很短的描述捕捉到数据中大量规律的那个。牛顿力学用几个公式描述了行星运动L(模型) 极短L(数据|模型) 也极短总长度远小于把每颗行星每个时刻的位置都存下来。这就是理解的经济学定义。4.3 两段式编码与贝叶斯的内在联系MDL 和贝叶斯推断在数学上是等价的。L(模型) 对应先验概率的负对数L(数据|模型) 对应似然的负对数总描述长度最小化等价于后验概率最大化。这个等价关系不是巧合。贝叶斯推断说根据数据更新对模型的信念MDL 说找总描述最短的模型两者都在做同一件事在模型复杂度和数据拟合度之间找最优权衡。我个人的经验是理解了这个等价关系之后调模型正则化项的时候心里就有底了。L2 正则化本质上是在说我偏好权重小的模型因为描述它们需要的比特少L1 正则化是在说我偏好稀疏的模型因为零权重不用编码。正则化系数就是在调 L(模型) 和 L(数据|模型) 之间的兑换率。5. 世界模型智能体内部的压缩器5.1 智能体为什么必须压缩世界现在把视角拉到一个在环境中行动的智能体。它每时每刻接收大量感官输入如果它把每个输入都原样存储很快就会淹没。它必须做取舍哪些信息值得保留哪些可以丢弃。这个取舍的标准是什么保留那些能帮助预测未来的信息丢弃那些对预测无用的信息。这恰恰就是压缩的定义。一个智能体内部的世界模型本质上就是一个压缩器它把高维、嘈杂、冗余的感官流压缩成一个低维、干净、可预测的内部状态。这个内部状态不需要还原原始输入它只需要保留对决策有用的部分。5.2 预测误差就是压缩没压好的信号如果世界模型压缩得好它对下一个观测的预测就应该准预测误差就小。预测误差大说明模型没有捕捉到数据中的某些规律压缩没做到位。这就给了一个非常干净的学习信号最小化预测误差就是在最大化压缩就是在提升对世界的理解。这个视角统一了很多看起来不同的方法。自编码器最小化重构误差是在压缩预测编码网络最小化下一帧预测误差是在压缩对比学习拉近正样本、推远负样本本质上也是在学一个能把数据压缩到低维流形的表示。5.3 从记住到理解的分界线一个只会记忆的系统和一个真正理解的系统区别在哪里记忆系统L(模型) 很大L(数据|模型) 很小总长度不省。 理解系统L(模型) 很小L(数据|模型) 也小总长度大幅节省。用日常语言说记忆是把答案抄下来理解是找到生成答案的规律。抄下来的答案只能应对见过的问题找到的规律能应对没见过的问题。这就是为什么泛化能力和压缩能力是同一件事的两面。一个模型如果在训练集上压缩得很好但在测试集上压缩得差说明它学到的是记忆而不是规律。真正学到规律的模型在未见数据上同样能压缩得好。实操提示如果你想评估一个表示学习模型到底学到了什么别只看下游任务的准确率。试试用它压缩一批新数据看压缩率如何。压缩率在训练集和测试集之间的差距比准确率更能暴露过拟合。6. 把理论落到代码一个最小可运行的压缩实验6.1 用字符级n-gram模型做条件压缩光讲理论不够我们动手写一个能跑的实验亲眼看到模型越强压缩越好。思路很简单用不同阶数的n-gram模型对一段文本做算术编码比较压缩率。阶数越高模型利用的上下文越长理论上压缩率越好。import math from collections import defaultdict def build_ngram_model(text, n): 构建n-gram频率模型返回条件概率表 counts defaultdict(lambda: defaultdict(int)) for i in range(len(text) - n): context text[i:in-1] next_char text[in-1] counts[context][next_char] 1 # 转成概率加平滑避免零概率 probs {} vocab_size len(set(text)) for context, next_counts in counts.items(): total sum(next_counts.values()) vocab_size probs[context] { c: (cnt 1) / total for c, cnt in next_counts.items() } return probs, vocab_size def cross_entropy(text, model, n, vocab_size): 计算模型在文本上的交叉熵比特/字符 probs, _ model total_bits 0.0 count 0 for i in range(len(text) - n): context text[i:in-1] next_char text[in-1] if context in probs and next_char in probs[context]: p probs[context][next_char] else: p 1.0 / vocab_size # 未见上下文退化为均匀分布 total_bits -math.log2(p) count 1 return total_bits / count跑这段代码你会看到交叉熵随 n 增大而下降。n1 时大约4.1比特n3 时降到3.0左右n5 时接近2.5。每降一点就意味着模型多理解了一点语言结构。6.2 交叉熵、困惑度与压缩率的换算这三个指标说的是同一件事只是单位不同。交叉熵比特/符号最优编码下平均每个符号的比特数。困惑度2的交叉熵次方可以理解为模型在每一步平均在多少个候选之间犹豫。压缩率交叉熵除以原始编码的比特数比如8比特/字符。如果交叉熵是2.5比特/字符原始是8比特/字符压缩率就是31.25%。困惑度是 2^2.5 ≈ 5.66意思是模型平均在5到6个字符之间犹豫。我习惯用困惑度来调模型因为它对数值变化更敏感训练时曲线更好看。但跟人解释压缩效果时用压缩率更直观。6.3 实测中的几个意外发现第一个意外平滑参数对结果影响巨大。我一开始用最简单的加一平滑n5时压缩率反而不如n3。原因是高阶n-gram遇到大量未见上下文平滑把概率摊得太均匀反而增加了编码长度。后来换成插值平滑高阶和低阶加权混合高阶模型才真正发挥出优势。第二个意外训练集和测试集的压缩率差距比准确率差距更能反映过拟合。我试过一个n8的模型训练集上压缩到1.8比特/字符测试集上却是3.5。而n4的模型训练集2.6测试集2.9。虽然后者训练集表现差但泛化好得多。这印证了前面说的真正衡量理解的是在未见数据上的压缩。第三个意外文本长度对结论有影响。短文本上高阶模型因为上下文稀疏表现反而不稳定。要观察到清晰的阶数越高压缩越好的趋势至少需要几十万字符的语料。7. 常见误解与边界条件7.1 压缩即智能不等于压缩率越高越智能这是最需要澄清的一点。压缩率是在特定数据集上衡量的。一个模型在某个数据集上压缩率极高可能只是因为它过拟合了这个数据集或者这个数据集本身规律简单。真正的智能体现在跨分布的压缩能力在一个分布上训练的模型能不能在另一个相关但不同的分布上同样压缩得好。这对应的是泛化是迁移学习是举一反三。所以更准确的说法是智能体现在用尽可能短的模型描述在尽可能广的数据分布上达到尽可能低的压缩率。三个尽可能缺一不可。7.2 有损压缩与无损压缩对应不同的理解前面讨论的主要是无损压缩。但有损压缩同样重要甚至更贴近生物智能。生物系统不会无损记住所有感官输入它做的是有损压缩丢弃细节保留对生存有用的结构。什么该丢、什么该留取决于任务。这就是为什么理解总是相对于某个目标而言的——没有绝对的理解只有对完成某类任务足够好的理解。在工程上这意味着设计表示学习目标时必须想清楚下游任务是什么。一个为图像分类训练的压缩器和为一个为图像生成训练的压缩器保留的信息完全不同。7.3 计算复杂度理论下界不等于实际可达香农熵给出的是理论下界但达到这个下界可能需要无限的计算资源。实际中我们总是在压缩率和计算成本之间权衡。一个能完美预测的模型如果推理一次要跑三天那它在实践中毫无价值。这就是为什么工程上大量使用近似方法变分推断、采样、蒸馏。它们牺牲一点压缩率换取可接受的计算成本。理解这个权衡很重要因为它解释了为什么理论上最优的方案经常不是工程上最优的方案。做研究可以追理论极限做产品必须算总账。8. 这一章留下的线索把这一章的核心串起来信息熵度量了在已知模型下编码数据的最少比特数条件熵和互信息刻画了利用上下文能省多少MDL把模型复杂度和数据拟合度统一到一个总长度里世界模型就是智能体内部的压缩器预测误差就是压缩没压好的信号。这条线索往下走自然会遇到几个问题如果世界模型是压缩器那它的最优结构应该长什么样为什么现在的深度网络能压缩得这么好压缩目标和强化学习的目标怎么统一下一章我打算聊预测编码与自由能把最小化预测误差这个信号从信息论一路推到神经科学和强化学习。那里面有个很漂亮的结论一个系统如果持续最小化它的预测误差它就在隐式地最大化它对世界的压缩也就走在通往理解的路上。如果你手头有代码环境强烈建议把第6节那个n-gram实验跑一遍。亲眼看到交叉熵随模型变强而下降比读十遍公式都管用。我当初就是跑完这个实验才真正相信压缩和理解不是比喻是同一件事。