知识点卡片:熵 (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 = KLQ2: 为什么高熵分布更"不确定"?
答:
- 均匀分布熵最大:每个结果等概率,最难预测
- 确定性分布熵零:结果确定,无需额外信息
- 偏斜分布熵居中:数据的内在不确定性小