Skip to content

知识点卡片:熵 (Entropy)

基本信息

属性内容
知识点信息熵、联合熵、条件熵
掌握程度★★★★☆
学习优先级P1
预估时间4小时
面试频率★★★☆☆

核心原理

信息熵 (Shannon Entropy)

熵衡量随机变量的不确定性(平均信息量):

H(X) = -Σ_x P(x) log₂ P(x)      (离散,单位:比特)
H(X) = -∫ p(x) log p(x) dx      (连续,微分熵)

性质:
- H(X) ≥ 0(离散)
- 均匀分布时熵最大(最大不确定性)
- 确定性事件熵为0(无不确定性)

联合熵与条件熵

联合熵:H(X,Y) = -Σ Σ P(x,y) log P(x,y)
条件熵:H(Y|X) = -Σ P(x) Σ P(y|x) log P(y|x)
                = H(X,Y) - H(X)

互信息:I(X;Y) = H(X) - H(X|Y) = H(X) + H(Y) - H(X,Y)

代码实现

python
import numpy as np

def entropy(probs, base=2):
    """计算离散分布的熵"""
    probs = np.asarray(probs)
    probs = probs[probs > 0]  # 过滤0(0*log(0) = 0)
    return -np.sum(probs * np.log(probs)) / np.log(base)

def cross_entropy(p, q):
    """H(p, q) = -Σ p log q"""
    p, q = np.asarray(p), np.asarray(q)
    q = np.clip(q, 1e-15, 1 - 1e-15)
    return -np.sum(p * np.log(q))

def kl_divergence(p, q):
    """KL(p||q) = Σ p log(p/q)"""
    p, q = np.asarray(p), np.asarray(q)
    q = np.clip(q, 1e-15, 1 - 1e-15)
    return np.sum(p * np.log(p / q))

# 示例
# 均匀分布(熵最大)
p_uniform = np.array([0.5, 0.5])
print(f"均匀分布熵: {entropy(p_uniform):.4f}")  # 1.0 比特

# 确定性分布(熵最小)
p_certain = np.array([1.0, 0.0])
print(f"确定性熵: {entropy(p_certain):.4f}")  # 0.0

# 偏斜分布
p_skewed = np.array([0.9, 0.1])
print(f"偏斜分布熵: {entropy(p_skewed):.4f}")  # ~0.47 比特

在深度学习中的应用

1. 交叉熵损失函数

python
"""
分类问题的交叉熵:
真实分布 p(one-hot):H(p) = 0(确定性)
预测分布 q:网络输出(softmax)

H(p, q) = H(p) + KL(p||q) = 0 + KL(p||q) = KL(p||q)

所以:最小化交叉熵 = 最小化KL散度 = 拉近p和q
"""

import torch
import torch.nn.functional as F

# 场景:三分类,真实标签是类别2
logits = torch.tensor([[0.5, 1.0, 2.0]])  # 网络输出
target = torch.tensor([2])  # 真实标签

# 交叉熵 = -log(softmax(logits)[2])
loss = F.cross_entropy(logits, target)
print(f"CE Loss: {loss:.4f}")

# 分解:
probs = F.softmax(logits, dim=-1)
p = torch.tensor([[0., 0., 1.]])  # one-hot真实分布
q = probs
# CE = -[0*log(q0) + 0*log(q1) + 1*log(q2)] = -log(q2)
ce_manual = -torch.log(q[0, 2])
print(f"手动CE: {ce_manual:.4f}")

2. 最大熵原理与正则化

python
"""
最大熵原理:
在满足已知约束的条件下,选择熵最大的分布
(最不偏不倚,最"客观"的选择)

应用:Label Smoothing = 增加标签熵
硬标签 [0, 1, 0] → H = 0
平滑后 [0.05, 0.9, 0.05] → H > 0
→ 防止模型对标签过于自信
"""

class LabelSmoothingCE(nn.Module):
    def __init__(self, smoothing=0.1, num_classes=10):
        super().__init__()
        self.smoothing = smoothing
        self.num_classes = num_classes

    def forward(self, pred, target):
        # 创建平滑标签
        smooth_target = torch.full_like(pred, self.smoothing / (self.num_classes - 1))
        smooth_target.scatter_(1, target.unsqueeze(1), 1.0 - self.smoothing)
        # 这增大了目标分布的熵
        log_preds = F.log_softmax(pred, dim=-1)
        return -(smooth_target * log_preds).sum(dim=-1).mean()

3. 互信息与表征学习

python
"""
InfoNCE / 对比学习:
最大化互信息 I(X; Z) 来学习好的表征

SimCLR损失:
L = -log [exp(sim(z_i, z_j)/τ) / Σ exp(sim(z_i, z_k)/τ)]

本质:最大化正样本对的互信息
"""

面试高频问题

Q1: 熵、交叉熵和KL散度的关系?

CE(p,q) = H(p) + KL(p||q)

推导:
CE(p,q) = -Σ p log q
        = -Σ p log p + Σ p log p - Σ p log q
        = H(p) + Σ p log(p/q)
        = H(p) + KL(p||q)

当p固定时,最小化CE = 最小化KL散度
当p是one-hot时,H(p)=0,CE = KL

Q2: 为什么高熵分布更"不确定"?

  • 均匀分布熵最大:每个结果等概率,最难预测
  • 确定性分布熵零:结果确定,无需额外信息
  • 偏斜分布熵居中:数据的内在不确定性小

相关知识点