信息论・逐式推导|01 熵的直觉、公理与 Python 验证
翻开 Cover & Thomas 的《信息论基础》,"仅需大学数学基础"——可能他们的"大学"是数学系,我的"大学"是校门口小吃一条街。
满书公式让人沉默,但我是真心喜欢。看不懂就慢慢啃,用 Python 一行行实现、调试、画图。
把熵、互信息、信道容量写成代码,比干瞪眼推导踏实多了。
写在前面
这本封面上的《信息论基础》(Cover & Thomas)堪称信息论领域的"圣经"。它之所以经典,是因为它把香农的思想用极其严谨又不失直观的方式呈现了出来。
熵,正是这整个理论体系的基石。下面我们对这个公式进行一次深度拆解,并用 Python 验证它的关键性质。
一、核心公式与直觉
对于一个取有限个值的离散随机变量 ,其概率分布为 ,它的熵 定义为:
约定:
- 通常取以 2 为底的对数,熵的单位是 比特(bits)。
- 当 时,规定 (符合极限结果)。
三个等价视角
视角一:不确定性的度量
抛一枚公平硬币前,你的不确定性最大;如果硬币两面都是正面,则毫无悬念。熵就是量化"不可预测程度"。概率越平均,熵越大。
视角二:信息内容的期望
是观察到事件 时获得的"信息量"或"惊异度"。概率越小,信息量越大。熵 是所有可能事件信息量的期望值:
视角三:高效编码的极限
香农的源头洞见:如果一个信源以分布 产生符号,无论怎么设计编码,平均每个符号所需的最少比特数就是 。这是熵的操作性定义。
二、公理化推导:为什么必须是这个形式?
为什么不能用 或其他函数?香农提出三条公理,证明了 是唯一解。
设 是待求度量。
公理1:连续性 – 随 连续变化。
公理2:极大性 – 当所有事件等概率 时不确定性最大;且随 增加而增加。
公理3:可分解性 – 总不确定性 = 分组决策的不确定性 + 组内决策不确定性的加权平均。
例:有事件 A(1/2), B(1/3), C(1/6)。
总不确定性 应等于:
先判断是 {A} 还是 {B, C} 的不确定性 ,
然后以 1/2 的概率进入 {B, C} 组,再区分 B 和 C 的不确定性 。
即:
为什么强制对数?
概率乘法 需映射为信息量加法,而对数恰好满足 。
三、数学性质与 Python 验证
1. 对数底数的选择
- 底数 2 → 比特(计算机标准)
- 底数 e → 纳特(微积分方便)
- 底数 10 → 哈特(工程)
换算:
2. 熵的上界
- 下界:分布完全确定(一个概率1,其余0)
- 上界:均匀分布时取等,利用 Jensen 不等式证明。
3. 链式法则
Python 验证:绘制伯努利分布的熵曲线
"""
Python 验证:绘制伯努利分布的熵曲线
功能:
1. 定义熵的计算函数
2. 生成概率值并计算对应熵值
3. 绘制熵随概率变化的曲线
4. 验证均匀分布(p=0.5)时熵最大
5. 保存图片到项目 assets 目录
"""
import numpy as np
import matplotlib.pyplot as plt
import os
def set_chinese_font():
"""设置 matplotlib 支持中文显示"""
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
def entropy(p):
"""计算二值随机变量的熵(单位:比特)"""
p = np.clip(p, 1e-12, 1 - 1e-12) # 避免 log(0)
return - (p * np.log2(p) + (1-p) * np.log2(1-p))
def main():
# 设置中文字体
set_chinese_font()
# 生成概率值(0到1之间取100个点)
p_vals = np.linspace(0, 1, 100)
h_vals = entropy(p_vals)
# 创建绘图
plt.figure(figsize=(8, 5))
# 绘制熵曲线
plt.plot(p_vals, h_vals, linewidth=2, color='#00E5FF')
plt.fill_between(p_vals, 0, h_vals, alpha=0.2, color='#00E5FF')
# 添加标签和标题
plt.xlabel('p (正面概率)', fontsize=12)
plt.ylabel('熵 H (比特)', fontsize=12)
plt.title('伯努利分布的熵:不确定性在 p=0.5 时最大', fontsize=14)
# 添加网格和参考线
plt.grid(True, alpha=0.3)
plt.axvline(0.5, linestyle='--', alpha=0.5, color='gray')
plt.axhline(1.0, linestyle='--', alpha=0.5, color='gray')
plt.text(0.5, 1.02, '最大熵 = 1 bit', ha='center')
# 创建 assets 目录(如果不存在)
assets_dir = os.path.join(os.path.dirname(__file__), '..', 'assets')
os.makedirs(assets_dir, exist_ok=True)
# 保存图片
output_path = os.path.join(assets_dir, 'entropy_curve.png')
plt.savefig(output_path, dpi=100, bbox_inches='tight')
plt.close() # 关闭图形释放内存
print(f"图片已保存到: {output_path}")
# 输出关键验证结果
max_entropy = np.max(h_vals)
max_index = np.argmax(h_vals)
max_p = p_vals[max_index]
print(f"验证结果:")
print(f"最大熵值: {max_entropy:.4f} 比特")
print(f"对应概率: p = {max_p:.2f}")
print(f"结论: 均匀分布(p=0.5)时熵最大,符合理论预期")
运行结果:
验证结果:
最大熵值: 0.9999 比特
对应概率: p = 0.49
结论: 均匀分布(p=0.5)时熵最大,符合理论预期
[伯努利分布的熵曲线]
验证链式法则(简单示例)
"""
验证链式法则(简单示例)
功能:
1. 定义联合分布 P(X,Y)
2. 计算边缘熵 H(X)、条件熵 H(Y|X)、联合熵 H(X,Y)
3. 验证链式法则:H(X,Y) = H(X) + H(Y|X)
"""
import numpy as np
def main():
# 联合分布 P(X,Y)
# X 取值 0,1;Y 取值 0,1
p_xy = np.array([[0.2, 0.3],
[0.1, 0.4]])
# 计算边缘分布 P(X)
p_x = p_xy.sum(axis=1) # [0.5, 0.5]
# 计算条件分布 P(Y|X)
p_y_given_x = p_xy / p_x[:, None]
# 计算各熵值
H_X = -np.sum(p_x * np.log2(p_x))
H_Y_given_X = -np.sum(p_xy * np.log2(p_y_given_x))
H_XY = -np.sum(p_xy * np.log2(p_xy))
# 输出结果
print("=== 链式法则验证 ===")
print(f"联合分布 P(X,Y):")
print(p_xy)
print(f"\n边缘分布 P(X): {p_x}")
print(f"\n条件分布 P(Y|X):")
print(p_y_given_x)
print(f"\n=== 熵值计算 ===")
print(f"H(X) = {H_X:.4f} 比特")
print(f"H(Y|X) = {H_Y_given_X:.4f} 比特")
print(f"H(X,Y) = {H_XY:.4f} 比特")
print(f"\n=== 链式法则验证 ===")
print(f"H(X) + H(Y|X) = {H_X + H_Y_given_X:.4f} 比特")
# 验证等式是否成立
if np.isclose(H_XY, H_X + H_Y_given_X):
print("\n✓ 链式法则验证通过:H(X,Y) = H(X) + H(Y|X)")
else:
print("\n✗ 链式法则验证失败")
运行结果:
=== 链式法则验证 ===
联合分布 P(X,Y):
[[0.2 0.3] [0.1 0.4]]
边缘分布 P(X): [0.5 0.5]
条件分布 P(Y|X):
[[0.4 0.6] [0.2 0.8]]
=== 熵值计算 ===
H(X) = 1.0000 比特
H(Y|X) = 0.8464 比特
H(X,Y) = 1.8464 比特
=== 链式法则验证 ===
H(X) + H(Y|X) = 1.8464 比特
验证通过!链式法则 成立。
四、Cover & Thomas 书中的严谨化
典型集与 AEP(渐近均分性质)
若 独立同分布,则 。
所有序列的概率质量几乎全集中在约 个"典型序列"上。这正是数据压缩的理论依据。
与 KL 散度的联系
其中 为均匀分布。你的实际分布离"完全无知"越远(KL 散度越大),不确定性越小。
五、结语与下期预告
熵的公式 不是凭空捏造,它是衡量"不确定性"的唯一自洽尺度。
《信息论基础》用代码推导,是我的"降熵"方式。
下一篇:敬请期待。
代码仓库准备中:
👉 即将同步至 Gitee(info-theory-playground)
欢迎在评论区评论指正。
技术标签:#信息论 #熵 #Python #机器学习 #数学基础
专栏:《信息论・逐式推导》第 1 篇
敬请期待下一篇:敬请期待