4.8 算法信息论与前沿方向
本节处理三个更专门的方向,它们把前面七节的工具推进到新的位置。算法信息论把信息量从分布推广到单个对象:熵描述随机变量平均携带的信息,柯尔莫哥洛夫复杂度描述一个具体对象的描述长度。这一推广回答了压缩极限之外的另一个问题:一个对象本身包含多少信息,与它来自哪个分布无关。
最小描述长度原则把这一想法变成模型选择准则,为奥卡姆剃刀给出定量形式:模型复杂度以描述长度计价,与数据拟合的编码长度相加后取最小值。差分隐私把 KL 散度的家族用于隐私定义,(ε, δ) 参数与散度的阶参数一一对应。量子信息论把概率分布换成密度矩阵,熵、条件熵与互信息都有对应的形式,并且出现经典情形没有的性质,例如负的条件熵。
本节的性质与前七节不同,三个方向都以概念介绍与最小示例为主,细节留给各自的教材。阅读目标是建立接口:知道这些方向用什么工具、解决什么问题、与前面哪些结论直接相连。
4.8.1 柯尔莫哥洛夫复杂度
描述长度的定义
4.4 节的信源编码定理回答了一个统计问题:给定分布,长序列平均需要多少比特。算法信息论回答一个逐对象的问题:一个具体的二进制串
其中
定义依赖具体的通用图灵机,但依赖程度有限。对两台通用图灵机
对所有
基本性质有两条。上界:把
不可压缩性
多数串不可压缩。计数论证直接给出结论:长度小于
取
与熵的关系
两个量描述不同的对象,形式上有对应。对可计算分布,期望意义下
熵是复杂度的期望,复杂度是逐样本的实现值。给定分布时熵给出平均最优码长(4.4 节),不知道分布时
括号内的量度量两个对象的共同信息。与香农互信息相比,
下列代码用游程编码演示描述长度的直观含义:同一长度的四类串有不同的编码长度;随后用计数论证给出可压缩串的比例上界。
import numpy as np
def rle_bits(bits):
"""游程编码的描述长度(比特):逐段记录长度,符号由交替决定"""
runs = []
cur, count = int(bits[0]), 1
for b in bits[1:]:
if int(b) == cur:
count += 1
else:
runs.append(count)
cur, count = int(b), 1
runs.append(count)
return int(sum(np.ceil(np.log2(r + 1)) for r in runs)), len(runs)
rng = np.random.default_rng(0)
n = 200
cases = {
"随机(p=0.5)": rng.integers(0, 2, size=n),
"偏置(p=0.9)": (rng.random(n) < 0.9).astype(int),
"分块(四段)": np.concatenate([np.zeros(50), np.ones(50), np.zeros(50), np.ones(50)]).astype(int),
"全零": np.zeros(n, dtype=int),
}
for name, bits in cases.items():
length, runs = rle_bits(bits)
print(f"{name:14s}: 游程数 = {runs:3d}, 描述长度 = {length:3d} 比特(原始 {n} 比特)")
# 计数论证:长度 n 的串中,可压缩 k 比特以上的比例不超过 2^(-k)
print()
for k in [10, 20, 40]:
print(f"长度 40 的串中,可压缩 {k:2d} 比特以上的比例不超过 2^-{k} = {2.0 ** -k:.3e}")
# 随机串的描述长度接近原始长度:p=0.5 时 158 / 200
# 偏置串的游程更少,描述长度 101 比特,接近熵率给出的理论值 200 * H(0.9) ≈ 94 比特
# 结构性串(分块、全零)的描述长度远小于原始长度输出给出三档对比:随机串的游程编码几乎没有压缩(
4.8.2 最小描述长度与奥卡姆剃刀
两段码
模型选择要在拟合精度与模型复杂度之间权衡。最小描述长度(minimum description length,MDL)原则把这一权衡写成编码长度:用模型描述数据的总长度由两部分组成,
第一项是模型的描述长度,第二项是在给定模型后编码数据的长度。选择总长度最小的模型。以多项式拟合为例,阶数是模型,系数是模型的描述内容,残差是数据在模型下的编码对象:阶数越高,模型描述越长,残差编码越短。
4.4 节的 Kraft 不等式给出编码长度与概率的对应:长度
这正是贝叶斯模型选择的目标(2.12 节)。两个框架在这里重合:概率大对应码长短,先验概率对应模型复杂度。贝叶斯因子与描述长度之差是同一个量的两种语言。
奥卡姆剃刀的定量形式
复杂度惩罚的必要性可以用计数论证说明。若允许的模型数量随复杂度指数增长,总存在一个复杂模型把训练数据拟合得更好,把噪声也编码进去。惩罚项的作用是抵消这一增长:复杂度每增加一比特,可选模型数量翻一倍,而惩罚也增加一比特,净效应使过拟合模型在描述长度上没有优势。
这一机制在经典准则中有对应的近似。BIC 的形式
来自对边际似然的拉普拉斯近似:第一项是数据在最优参数下的编码长度,第二项近似参数的描述长度(每个参数约
与柯尔莫哥洛夫复杂度的关系是近似的:MDL 用可计算、可优化的模型类代替不可计算的
下列代码在带噪声的三次多项式数据上执行两段码准则。模型码长按参数个数乘以每个参数的固定位数计算,数据码长取高斯残差的负对数似然。
import numpy as np
rng = np.random.default_rng(0)
n = 300
x = np.linspace(-1, 1, n)
y = 0.5 + 1.2 * x - 2.0 * x ** 2 + 1.5 * x ** 3 + rng.normal(0, 0.3, size=n)
def two_part_bits(degree, bits_per_param=32):
"""两段码长度:模型参数码 + 数据在模型下的负对数似然(比特)"""
coef = np.polyfit(x, y, degree)
resid = y - np.polyval(coef, x)
sigma2 = np.mean(resid ** 2)
nll_bits = 0.5 * n * np.log2(2 * np.pi * np.e * sigma2) # 高斯残差的编码长度
model_bits = (degree + 1) * bits_per_param
return nll_bits + model_bits, nll_bits, model_bits
print("阶数 模型码长 数据码长 总码长")
best = None
for d in range(0, 9):
total, nll, model = two_part_bits(d)
print(f" {d} {model:6.0f} {nll:8.1f} {total:8.1f}")
if best is None or total < best[0]:
best = (total, d)
print(f"最优阶数 = {best[1]}(真实生成模型为三次)")
# 低阶模型的数据码长长(拟合不足),高阶模型的模型码长长(过拟合的收益不足)
# 总码长在真实阶数处取得最小值输出显示总码长在阶数
4.8.3 差分隐私
定义与散度
差分隐私限制统计结果对单条记录的依赖程度。设随机机制
则称
信息论给出这一条件的精确形式。
Rényi 散度的引入有两个作用。其一是组合:多次查询的隐私损失按阶参数累积,Rényi 形式给出的组合界比基本组合
两种机制
拉普拉斯机制:查询函数
高斯机制:输出加方差为
隐私参数与信息量的关系
下列代码演示拉普拉斯机制的噪声尺度,并数值验证相邻输入的密度比条件。
import numpy as np
rng = np.random.default_rng(0)
print("敏感度为 1 的计数查询,拉普拉斯机制的噪声:")
for eps in [0.1, 1.0, 10.0]:
noise = rng.laplace(0, 1 / eps, size=200000)
print(f" eps = {eps:5.1f}: 噪声尺度 = {1 / eps:6.3f}, 标准差 = {np.sqrt(2) / eps:.3f}, "
f"90% 分位 = {np.quantile(np.abs(noise), 0.9):.3f}")
def lap_pdf(z, mu, b):
return np.exp(-np.abs(z - mu) / b) / (2 * b)
eps = 1.0
b = 1 / eps
z = np.linspace(-10, 10, 8001)
ratio = lap_pdf(z, 1.0, b) / lap_pdf(z, 0.0, b) # 相邻数据集:均值相差 1
print(f"\n最大密度比 = {ratio.max():.6f},e^eps = {np.exp(eps):.6f},"
f"不超过 e^eps:{ratio.max() <= np.exp(eps) + 1e-9}")
# 密度比在所有输出处不超过 e^eps,这正是 (eps, 0)-差分隐私的等价条件输出显示噪声随
4.8.4 量子信息论初步
密度矩阵与冯·诺依曼熵
经典信息论的对象是概率分布,量子信息论的对象是密度矩阵(density matrix):半正定、迹为
熵的定义直接推广:把概率换成密度矩阵的特征值,或把
称为冯·诺依曼熵(von Neumann entropy)。对数取 2 为底时单位为量子比特。三条基本性质:纯态的熵为零(特征值只有一个不为零,等于
复合系统由张量积描述,求部分系统的状态需要偏迹(partial trace):对另一部分取迹。偏迹是量子信息论中概念变化的来源:两体纯态的整体熵为零,而各部分可以是混合态。量子互信息定义为
它与经典互信息同形。量子相对熵定义为
与经典的差别
负的条件熵是量子情形独有的现象。定义
量子信道是完全正、迹保持的线性映射,作用于密度矩阵。量子信道容量分两个层次:传递经典信息的容量由 Holevo 容量给出上界
它不小于经典容量,两者之间的差(Holevo 界是否可达)依赖信道类型;传递量子态本身的容量由相干信息刻画(Lloyd-Shor-Devetak 定理)。两个容量的表达式都以前面的熵与互信息为基础,量子信息论的结构与经典理论平行,计算与可达性的细节更为复杂。
下列代码构造几个典型量子态并计算冯·诺依曼熵,展示纯态、混合态与 Bell 态的区别,并数值检查量子相对熵的非负性。
import numpy as np
def von_neumann(rho):
"""冯·诺依曼熵(比特):对密度矩阵的特征值计算香农熵"""
vals = np.linalg.eigvalsh(rho)
vals = vals[vals > 1e-12]
return float(-np.sum(vals * np.log2(vals)))
def partial_trace_b(rho):
"""对两量子比特系统的第二个子系统求偏迹"""
return rho.reshape(2, 2, 2, 2).trace(axis1=1, axis2=3)
psi = np.array([1, 0], dtype=complex)
print("纯态 |0>:S =", von_neumann(np.outer(psi, psi.conj())), "比特")
print("完全混合态 I/2:S =", von_neumann(np.eye(2) / 2), "比特")
bell = np.zeros(4, dtype=complex)
bell[0] = bell[3] = 1 / np.sqrt(2) # (|00> + |11>) / sqrt(2)
rho_ab = np.outer(bell, bell.conj())
rho_a = partial_trace_b(rho_ab)
print("\nBell 态 (|00> + |11>) / sqrt(2):")
print(" S(AB) =", von_neumann(rho_ab), "比特")
print(" S(A) = S(B) =", von_neumann(rho_a), "比特")
print(" 量子互信息 I(A:B) =", 2 * von_neumann(rho_a) - von_neumann(rho_ab), "比特")
print(" 条件熵 S(A|B) =", von_neumann(rho_ab) - von_neumann(rho_a), "比特(负值)")
def quantum_kl(rho, sigma):
"""量子相对熵 D(rho||sigma)(自然对数)"""
w_r, v_r = np.linalg.eigh(rho)
log_r = v_r @ np.diag(np.log(np.maximum(w_r, 1e-12))) @ v_r.conj().T
w_s, v_s = np.linalg.eigh(sigma)
log_s = v_s @ np.diag(np.log(np.maximum(w_s, 1e-12))) @ v_s.conj().T
return float(np.real(np.trace(rho @ (log_r - log_s))))
rho = np.array([[0.7, 0.2], [0.2, 0.3]])
sigma = np.array([[0.5, 0.05], [0.05, 0.5]])
print("\n量子相对熵 D(rho||sigma) =", round(quantum_kl(rho, sigma), 4), "(非负)")
print("反向 D(sigma||rho) =", round(quantum_kl(sigma, rho), 4), "(两个方向不相等)")
# 纯态熵为 0,完全混合态熵为 1 比特
# Bell 态整体熵为 0,各部分熵为 1 比特,条件熵为 -1 比特输出显示四组数值:纯态熵为
4.8.5 本节小结
单个对象、模型选择与两个前沿
本节介绍三个方向。算法信息论用最短程序长度定义单个对象的复杂度
三个方向的共同线索仍然是熵与散度:
信息论一章到此结束。回顾全章:4.1 与 4.2 建立熵、互信息与各类散度的语言;4.3 把它们放到统计流形上,得到信息几何;4.4 与 4.5 给出压缩与传输的两个极限;4.6 把散度连接到统计推断的误差指数与大偏差;4.7 把工具用到机器学习的目标、表示与泛化分析;4.8 处理单个对象的复杂度、模型选择与两个前沿方向。四章的布局到此完整:线性代数提供结构,概率论与统计推断提供不确定性,最优化提供求解方法,信息论提供度量不确定性与信息的统一尺度,四者共同构成后续课程中深度学习、强化学习与概率图模型的基础。
练习题
第 1 题 概念推导
证明柯尔莫哥洛夫复杂度的两条性质:其一,对长度
参考答案
上界:设通用图灵机
比例上界:长度小于
每个程序至多输出一个串,因此可被这些程序输出的串不超过
与压缩极限的关系:信源编码定理是统计结论,前提是先知道分布(或用模型估计分布),结论是最优平均码长等于熵。上面的计数结论是组合事实,不涉及分布,它对每一个串给出最坏情形下的描述长度下界。两者不矛盾,因为对象不同:计数结论说的是存在不可压缩的串,编码定理说的是对给定的分布存在最优的平均性能。一个信源可以同时满足两条:分布集中在少数简单串上(熵小,平均可压缩),而该分布下概率极小的串仍然不可压缩。实践中压缩工具在随机数据上失效、在结构化数据上有效,对应的就是这两类对象。
第 2 题 计算推理
某团队有两组候选模型:模型 A 的参数量为
参考答案
模型码长之差:
需要的数据码长改进:总码长之差为
若实际改进为每样本
与 BIC 的比较:BIC 的惩罚为
第 3 题 代码验证
用 4.8.3 节的拉普拉斯机制代码验证差分隐私的两条性质:其一,噪声尺度与
参考答案
import numpy as np
rng = np.random.default_rng(0)
# 性质一:噪声尺度与 eps 成反比
print("eps 噪声尺度 经验标准差 理论标准差")
for eps in [0.5, 1.0, 2.0, 4.0]:
noise = rng.laplace(0, 1 / eps, size=200000)
print(f" {eps:.1f} {1 / eps:.3f} {noise.std():.4f} {np.sqrt(2) / eps:.4f}")
# 性质二:敏感度为 2 时,噪声尺度取 2/eps,密度比的最大值仍为 e^eps
def lap_pdf(z, mu, b):
return np.exp(-np.abs(z - mu) / b) / (2 * b)
eps = 1.0
print()
for sens in [1.0, 2.0]:
b = sens / eps
z = np.linspace(-20, 20, 16001)
ratio = lap_pdf(z, sens, b) / lap_pdf(z, 0.0, b)
print(f"敏感度 = {sens:.0f}:噪声尺度 = {b:.2f},最大密度比 = {ratio.max():.6f},e^eps = {np.exp(eps):.6f}")
# 高斯噪声:密度比无界
def gauss_pdf(z, mu, s):
return np.exp(-(z - mu) ** 2 / (2 * s ** 2)) / (s * np.sqrt(2 * np.pi))
z = np.linspace(-20, 20, 40001)
ratio_g = gauss_pdf(z, 1.0, 1 / eps) / gauss_pdf(z, 0.0, 1 / eps)
print(f"\n高斯噪声:位置 z = 20 处的密度比 = {ratio_g[-1]:.3e}(随 |z| 增大而无界)")
print(f"e^(1/(2 s^2)) 形式:最大值随 z -> +inf 发散,无法用 (eps, 0) 形式约束")输出(节选):
eps 噪声尺度 经验标准差 理论标准差
0.5 2.000 2.8270 2.8284
1.0 1.000 1.4184 1.4142
2.0 0.500 0.7085 0.7071
4.0 0.250 0.3551 0.3536
敏感度 = 1:噪声尺度 = 1.00,最大密度比 = 2.718282,e^eps = 2.718282
敏感度 = 2:噪声尺度 = 2.00,最大密度比 = 2.718282,e^eps = 2.718282
高斯噪声:位置 z = 20 处的密度比 = 2.943e+08(随 |z| 增大而无界)结论:噪声尺度与
第 4 题 综合应用
某团队要把模型训练改造成差分隐私版本(差分隐私随机梯度下降)。他们给出三种候选方案:方案一,对每次梯度更新加拉普拉斯噪声,隐私预算
参考答案
方案评价:
方案一的问题在组合:基本组合定理把
方案二的做法是正确方向的两个改动:其一,用 Rényi 散度做组合,隐私损失按阶参数
方案三满足最严格的隐私:输出与数据完全独立,任何
方案一的组合估算:基本组合给出
方案二的优势:Rényi 组合利用损失分布在高阶矩下的行为,把
方案三的位置:在隐私维度上最优(完全不依赖数据),在精度维度上最差(无信息)。三个方案在隐私与精度的平面上构成一条边界上的点,实际选择取决于应用对两个维度的要求。差分隐私的形式化含义正是把这条权衡曲线写清楚:任何声称同时接近两个极端的方案都需要检查其隐私账本(每次查询的
常见错误
错误 1 · 把柯尔莫哥洛夫复杂度当作可计算的量并用于实际压缩
原因:
解决:把
错误 2 · 把 MDL 的模型码长当作参数的物理存储长度
原因:两段码中的模型码长是编码假设下的抽象长度,取决于参数表示的约定。同一模型用固定位数、浮点格式或拉普拉斯近似的
解决:报告中给出编码约定,并说明结论对该约定是否稳健。做法是同时用两种约定(例如固定位数与 BIC 形式)比较排序是否一致;若不一致,说明数据量不足以区分这些模型,需要更多样本或更强的先验。这与 4.6 节的教训一致:界与准则的数值依赖假设,比较时必须固定约定。
错误 3 · 用最大散度描述高斯机制的隐私
原因:两个均值不同、方差相同的高斯分布之间,密度比在尾部无界,最大散度为无穷,因此高斯机制不满足任何
解决:高斯机制用
错误 4 · 把量子熵直接类比经典熵而不检查前提
原因:量子条件熵可以为负,量子互信息可以超过两部分各自的熵(Bell 态中为
解决:使用量子量时回到定义: