2深度学习

概率与信息论

不确定性建模

概率熵KL散度最大似然

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第2章:概率与信息论(Probability and Information Theory)

一、导读

1.1 本章学习目标

第2章为深度学习提供概率论和信息论的数学基础。深度学习的核心任务之一是在不确定性下做出决策——模型需要对未知数据做出预测,同时量化自身的信心。概率论提供了描述不确定性的严格数学框架,而信息论则提供了度量信息量和不确定性的工具。

本章的核心学习目标包括:

  • 掌握概率的基本规则:加法法则、乘法法则、条件概率、贝叶斯定理
  • 理解常见概率分布:伯努利分布、多项式分布、高斯分布及其在深度学习中的应用
  • 掌握边缘概率和条件概率的计算:理解如何从联合分布中推导边际和条件分布
  • 理解信息论的核心概念:自信息、熵、交叉熵、KL散度
  • 掌握最大似然估计的原理:理解参数估计的基本方法
  • 了解结构化概率模型:条件独立性和贝叶斯网络的基本概念

1.2 为什么本章如此重要

深度学习中的模型本质上是在学习数据的概率分布。无论是分类任务中的类别概率、生成模型中的数据分布、还是强化学习中的策略分布,概率论都是不可或缺的工具。

具体来说:

  • 分类任务:模型的输出是各类别的概率分布,训练目标是最大化正确类别的概率
  • 损失函数:交叉熵损失是分类任务的标准损失函数,直接来源于信息论
  • 生成模型:VAE、GAN等生成模型直接建模数据的概率分布
  • 正则化:Dropout可以理解为对模型集成的近似贝叶斯推断
  • 信息论度量:KL散度用于衡量分布差异,互信息用于特征选择

不理解概率论和信息论,就无法理解深度学习为什么这样设计损失函数、为什么用softmax、为什么交叉熵比均方误差更适合分类。

1.3 核心问题引导

在阅读本章时,请带着以下问题思考:

为什么深度学习中的分类任务几乎都用交叉熵损失而不是均方误差?

贝叶斯定理在深度学习中有哪些应用?先验和似然分别对应什么?

信息熵的物理意义是什么?为什么熵越大表示不确定性越高?

KL散度和交叉熵有什么关系?为什么交叉熵可以作为损失函数?

最大似然估计和最小化交叉熵有什么关系?

为什么高斯分布在深度学习中如此重要?


二、核心概念详解

2.1 概率基础

2.1.1 概率的公理化定义

概率是描述不确定事件的数学工具。Kolmogorov 公理化定义:

  • 非负性:P(A) ≥ 0
  • 归一性:P(Ω) = 1(样本空间的概率为1)
  • 可加性:互斥事件 A、B,P(A∪B) = P(A) + P(B)
python
import numpy as np

# 离散概率分布
probabilities = np.array([0.1, 0.3, 0.4, 0.2])
print(f"概率之和: {np.sum(probabilities)}")  # 1.0

# 连续概率分布(概率密度函数)
from scipy.stats import norm
x = np.linspace(-3, 3, 100)
pdf = norm.pdf(x, loc=0, scale=1)
# 概率密度函数的积分为1
from scipy.integrate import quad
integral, _ = quad(lambda x: norm.pdf(x, 0, 1), -np.inf, np.inf)
print(f"概率密度积分: {integral:.4f}")  # 1.0

2.1.2 条件概率与贝叶斯定理

条件概率:在事件B发生的条件下,事件A发生的概率:

P(A|B) = P(A∩B) / P(B)

贝叶斯定理:

P(A|B) = P(B|A) · P(A) / P(B)

其中:

  • P(A) 是先验概率(prior)
  • P(A|B) 是后验概率(posterior)
  • P(B|A) 是似然(likelihood)
  • P(B) 是证据(evidence)
python
# 贝叶斯定理示例:疾病检测
# 假设某疾病发病率为0.1%,检测准确率99%,假阳性率5%
P_disease = 0.001          # 先验概率
P_positive_disease = 0.99  # 灵敏度(真阳性率)
P_positive_no_disease = 0.05  # 假阳性率

# 全概率公式
P_positive = (P_positive_disease * P_disease + 
              P_positive_no_disease * (1 - P_disease))

# 贝叶斯定理:检测阳性时真正患病的概率
P_disease_positive = P_positive_disease * P_disease / P_positive
print(f"检测阳性时患病的概率: {P_disease_positive:.4f}")  # 约0.0194

在深度学习中的应用:贝叶斯定理是贝叶斯深度学习的基础。先验对应正则化项,似然对应数据拟合项,后验对应训练后的模型参数分布。

2.1.3 边缘概率

从联合分布中消除某些变量,得到边缘分布:

P(A) = Σ_B P(A, B)  (离散情况)
P(A) = ∫ P(A, B) dB  (连续情况)
python
# 边缘概率示例
# 联合概率分布
joint_prob = np.array([
    [0.1, 0.2, 0.1],
    [0.15, 0.25, 0.2]
])

# 边缘概率 P(X)
P_X = np.sum(joint_prob, axis=1)  # [0.4, 0.6]

# 边缘概率 P(Y)
P_Y = np.sum(joint_prob, axis=0)  # [0.25, 0.45, 0.3]

2.2 常见概率分布

2.2.1 伯努利分布

伯努利分布是二值随机变量的分布:

P(X=1) = p, P(X=0) = 1-p
E[X] = p, Var(X) = p(1-p)
python
from scipy.stats import bernoulli

p = 0.7
X = bernoulli(p)

# 生成样本
samples = X.rvs(size=10)
print(f"样本: {samples}")

# 概率质量函数
print(f"P(X=0) = {X.pmf(0):.1f}")  # 0.3
print(f"P(X=1) = {X.pmf(1):.1f}")  # 0.7

在深度学习中的应用:二分类任务的输出可以建模为伯努利分布,sigmoid函数的输出就是参数p。

2.2.2 多项式分布(分类分布)

多项式分布是伯努利分布的多类别推广:

P(X=i) = p_i, Σp_i = 1
python
from scipy.stats import multinomial

# 6面骰子的概率
n = 1
probs = [1/6] * 6
X = multinomial(n, probs)

# 生成样本
samples = X.rvs(size=5)
print(f"样本:\n{samples}")

在深度学习中的应用:多分类任务的输出用softmax函数转化为分类分布。

python
import torch
import torch.nn.functional as F

# softmax 将 logits 转化为概率分布
logits = torch.tensor([2.0, 1.0, 0.1])
probs = F.softmax(logits, dim=0)
print(f"概率分布: {probs}")  # 和为1
print(f"概率之和: {probs.sum()}")  # 1.0

2.2.3 高斯分布(正态分布)

高斯分布是深度学习中最重要的连续分布:

N(x|μ, σ²) = (1/√(2πσ²)) · exp(-(x-μ)²/(2σ²))
python
from scipy.stats import norm
import matplotlib.pyplot as plt

# 不同参数的高斯分布
x = np.linspace(-5, 5, 200)

fig, axes = plt.subplots(1, 2, figsize=(12, 4))

# 不同均值
for mu in [-2, 0, 2]:
    axes[0].plot(x, norm.pdf(x, mu, 1), label=f'μ={mu}')
axes[0].set_title('不同均值的高斯分布')
axes[0].legend()

# 不同方差
for sigma in [0.5, 1.0, 2.0]:
    axes[1].plot(x, norm.pdf(x, 0, sigma), label=f'σ={sigma}')
axes[1].set_title('不同方差的高斯分布')
axes[1].legend()

plt.tight_layout()
plt.savefig('gaussian_distributions.png', dpi=150)
plt.show()

在深度学习中的应用:

  • 权重初始化:He初始化、Xavier初始化都基于高斯分布
  • Batch Normalization:假设中间层的激活值近似高斯分布
  • VAE:隐变量服从标准高斯分布
  • 噪声注入:训练时添加高斯噪声作为正则化

2.2.4 指数分布与拉普拉斯分布

python
from scipy.stats import expon, laplace

x = np.linspace(-3, 3, 200)

# 指数分布(用于L2正则化的先验)
# 拉普拉斯分布(用于L1正则化的先验)
plt.plot(x, laplace.pdf(x, 0, 1/np.sqrt(2)), label='Laplace')
plt.plot(x, norm.pdf(x, 0, 1), label='Gaussian')
plt.legend()
plt.title('Laplace vs Gaussian 先验')
plt.show()

在深度学习中的应用:拉普拉斯分布作为权重的先验时,MAP估计等价于L1正则化;高斯分布作为先验时,等价于L2正则化。

2.3 信息论基础

2.3.1 自信息(Self-Information)

自信息度量单个事件的"信息量"或"惊讶程度":

I(x) = -log P(x)

概率越小的事件,发生时带来的信息量越大。

python
def self_information(p):
    return -np.log2(p)

# 抛硬币:正面朝上的信息量
print(f"公平硬币正面的信息量: {self_information(0.5):.2f} bits")  # 1.0 bit

# 罕见事件的信息量
print(f"概率0.01事件的信息量: {self_information(0.01):.2f} bits")  # 6.64 bits

2.3.2 信息熵(Entropy)

信息熵是随机变量不确定性的度量,等于自信息的期望:

H(X) = -Σ P(x) log P(x) = E[I(X)]
python
def entropy(p):
    """计算离散分布的熵"""
    return -np.sum(p * np.log2(p + 1e-10))

# 均匀分布的熵最大
p_uniform = np.array([0.25, 0.25, 0.25, 0.25])
print(f"均匀分布的熵: {entropy(p_uniform):.2f} bits")  # 2.0 bits

# 确定性分布的熵为0
p_certain = np.array([1.0, 0.0, 0.0, 0.0])
print(f"确定性分布的熵: {entropy(p_certain):.2f} bits")  # 0.0 bits

# 一般分布
p_general = np.array([0.5, 0.3, 0.15, 0.05])
print(f"一般分布的熵: {entropy(p_general):.2f} bits")  # 约1.49 bits

在深度学习中的应用:

  • 熵越大,分布越均匀,不确定性越高
  • 决策树使用信息增益(熵的减少)作为分裂标准
  • 强化学习中用熵正则化鼓励探索

2.3.3 交叉熵(Cross-Entropy)

交叉熵度量用分布q编码来自分布p的数据所需的平均额外比特数:

H(p, q) = -Σ P(x) log Q(x)
python
def cross_entropy(p, q):
    """计算交叉熵"""
    return -np.sum(p * np.log(q + 1e-10))

# 真实分布
p = np.array([0.7, 0.2, 0.1])

# 模型预测分布
q_good = np.array([0.65, 0.25, 0.10])
q_bad = np.array([0.1, 0.8, 0.1])

print(f"好的预测的交叉熵: {cross_entropy(p, q_good):.4f}")
print(f"差的预测的交叉熵: {cross_entropy(p, q_bad):.4f}")

在深度学习中的应用:交叉熵是分类任务的标准损失函数。最小化交叉熵等价于最大化似然。

python
import torch
import torch.nn as nn

# PyTorch 中的交叉熵损失
# 注意:nn.CrossEntropyLoss 内部包含了 softmax
logits = torch.tensor([[2.0, 1.0, 0.1]])  # 未经softmax的logits
target = torch.tensor([0])  # 真实类别

criterion = nn.CrossEntropyLoss()
loss = criterion(logits, target)
print(f"交叉熵损失: {loss.item():.4f}")

2.3.4 KL散度(Kullback-Leibler Divergence)

KL散度度量两个分布之间的"距离"(注意:不是真正的距离,不对称):

D_KL(P||Q) = Σ P(x) log(P(x)/Q(x)) = H(P, Q) - H(P)
python
def kl_divergence(p, q):
    """计算KL散度"""
    return np.sum(p * np.log((p + 1e-10) / (q + 1e-10)))

p = np.array([0.5, 0.3, 0.2])
q = np.array([0.4, 0.4, 0.2])

print(f"D_KL(P||Q) = {kl_divergence(p, q):.4f}")
print(f"D_KL(Q||P) = {kl_divergence(q, p):.4f}")
# 注意:KL散度不对称

在深度学习中的应用:

  • VAE:用KL散度约束隐变量分布接近标准高斯
  • 知识蒸馏:用KL散度度量学生模型和教师模型分布的差异
  • 策略梯度:TRPO/PPO用KL散度约束策略更新幅度
python
# VAE 中的 KL 散度
def vae_kl_loss(mu, log_var):
    """VAE中隐变量与标准正态分布的KL散度"""
    # 解析形式:-0.5 * Σ(1 + log(σ²) - μ² - σ²)
    kl = -0.5 * torch.sum(1 + log_var - mu.pow(2) - log_var.exp())
    return kl

2.4 最大似然估计

2.4.1 原理

最大似然估计(MLE)是参数估计的基本方法。给定观测数据,找到使数据出现概率最大的参数:

θ_MLE = argmax_θ P(data|θ) = argmax_θ Π P(x_i|θ)

取对数后变为求和(数值更稳定):

θ_MLE = argmax_θ Σ log P(x_i|θ)

2.4.2 高斯分布的MLE

python
# 高斯分布的最大似然估计
data = np.random.randn(1000) * 2 + 3  # 真实均值3,标准差2

# MLE 估计
mu_mle = np.mean(data)
sigma_mle = np.std(data)

print(f"真实参数: μ=3, σ=2")
print(f"MLE估计: μ={mu_mle:.3f}, σ={sigma_mle:.3f}")

2.4.3 MLE与交叉熵的关系

最小化交叉熵等价于最大化似然。这解释了为什么交叉熵是分类任务的标准损失函数。

python
import torch
import torch.nn.functional as F

# 二分类的MLE等价于最小化二元交叉熵
# 模型输出概率 p(y=1|x)
# 对数似然:Σ[y_i * log(p_i) + (1-y_i) * log(1-p_i)]
# 负对数似然 = 二元交叉熵

logits = torch.tensor([1.5, -0.5, 2.0, -1.0])
targets = torch.tensor([1.0, 0.0, 1.0, 0.0])

# 方法1:直接计算负对数似然
probs = torch.sigmoid(logits)
nll = -torch.mean(targets * torch.log(probs) + (1-targets) * torch.log(1-probs))

# 方法2:使用BCELoss
bce = F.binary_cross_entropy_with_logits(logits, targets)

print(f"负对数似然: {nll.item():.4f}")
print(f"BCE损失: {bce.item():.4f}")
# 两者相等

2.5 结构化概率模型

2.5.1 条件独立

如果 P(A,B|C) = P(A|C)·P(B|C),则A和B在给定C的条件下独立。条件独立可以大幅简化概率模型。

python
# 朴素贝叶斯假设:特征在给定类别下条件独立
# P(x1, x2, ..., xn | y) = Π P(xi | y)

2.5.2 贝叶斯网络

贝叶斯网络用有向无环图表示变量之间的条件独立关系。

python
# 简单的贝叶斯网络:天气 -> 洒水器 -> 草地湿
# P(Weather, Sprinkler, WetGrass) = 
#   P(Weather) · P(Sprinkler|Weather) · P(WetGrass|Weather, Sprinkler)

# 朴素贝叶斯分类器
from sklearn.naive_bayes import GaussianNB

X = np.random.randn(100, 5)
y = np.random.randint(0, 3, 100)

nb = GaussianNB()
nb.fit(X, y)
predictions = nb.predict(X[:5])
print(f"预测: {predictions}")

三、实战案例

3.1 案例一:交叉熵损失函数的手动实现

python
import numpy as np

def softmax(logits):
    """数值稳定的softmax"""
    exp_logits = np.exp(logits - np.max(logits, axis=1, keepdims=True))
    return exp_logits / np.sum(exp_logits, axis=1, keepdims=True)

def cross_entropy_loss(logits, targets):
    """交叉熵损失函数"""
    batch_size = logits.shape[0]
    probs = softmax(logits)
    
    # 取对数(加小常数防止log(0))
    log_probs = np.log(probs + 1e-10)
    
    # 取正确类别的对数概率
    correct_log_probs = log_probs[np.arange(batch_size), targets]
    
    # 平均损失
    loss = -np.mean(correct_log_probs)
    return loss

def cross_entropy_gradient(logits, targets):
    """交叉熵损失对logits的梯度"""
    batch_size = logits.shape[0]
    probs = softmax(logits)
    
    # 梯度 = probs - one_hot(targets)
    grad = probs.copy()
    grad[np.arange(batch_size), targets] -= 1
    grad /= batch_size
    return grad

# 测试
logits = np.array([[2.0, 1.0, 0.1],
                   [0.5, 2.0, 0.3],
                   [1.0, 0.5, 2.0]])
targets = np.array([0, 1, 2])

loss = cross_entropy_loss(logits, targets)
grad = cross_entropy_gradient(logits, targets)

print(f"交叉熵损失: {loss:.4f}")
print(f"梯度:\n{grad}")

# 数值梯度验证
epsilon = 1e-5
numerical_grad = np.zeros_like(logits)
for i in range(logits.shape[0]):
    for j in range(logits.shape[1]):
        logits_plus = logits.copy()
        logits_plus[i, j] += epsilon
        logits_minus = logits.copy()
        logits_minus[i, j] -= epsilon
        numerical_grad[i, j] = (cross_entropy_loss(logits_plus, targets) - 
                                cross_entropy_loss(logits_minus, targets)) / (2 * epsilon)

print(f"数值梯度:\n{numerical_grad}")
print(f"梯度差异: {np.max(np.abs(grad - numerical_grad)):.2e}")

3.2 案例二:KL散度在VAE中的应用

python
import torch
import torch.nn.functional as F

def vae_loss(recon_x, x, mu, log_var):
    """VAE的完整损失函数"""
    # 重构损失(二元交叉熵)
    recon_loss = F.binary_cross_entropy(recon_x, x, reduction='sum')
    
    # KL散度损失
    # D_KL(N(μ, σ²) || N(0, 1)) = -0.5 * Σ(1 + log(σ²) - μ² - σ²)
    kl_loss = -0.5 * torch.sum(1 + log_var - mu.pow(2) - log_var.exp())
    
    return recon_loss + kl_loss, recon_loss, kl_loss

# 模拟VAE训练
batch_size = 32
input_dim = 784
latent_dim = 20

# 模拟数据
x = torch.rand(batch_size, input_dim)
recon_x = torch.rand(batch_size, input_dim)  # 模拟重构
mu = torch.randn(batch_size, latent_dim)
log_var = torch.randn(batch_size, latent_dim) * 0.1

total_loss, recon_loss, kl_loss = vae_loss(recon_x, x, mu, log_var)
print(f"总损失: {total_loss.item():.2f}")
print(f"重构损失: {recon_loss.item():.2f}")
print(f"KL损失: {kl_loss.item():.2f}")

# 调整KL权重(β-VAE)
beta = 4.0
total_loss_beta = recon_loss + beta * kl_loss
print(f"β-VAE总损失 (β={beta}): {total_loss_beta.item():.2f}")

3.3 案例三:最大似然估计与过拟合

python
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm

# 生成数据
np.random.seed(42)
true_mu = 2.0
true_sigma = 1.0
n_samples = 20
data = np.random.randn(n_samples) * true_sigma + true_mu

# 最大似然估计
mu_mle = np.mean(data)
sigma_mle = np.std(data)

# 贝叶斯估计(带先验)
prior_mu = 0.0
prior_sigma = 2.0
# 后验均值是先验均值和MLE的加权平均
weight = n_samples * prior_sigma**2 / (n_samples * prior_sigma**2 + sigma_mle**2)
mu_bayes = weight * prior_mu + (1 - weight) * mu_mle

# 可视化
x = np.linspace(-2, 6, 200)
plt.figure(figsize=(10, 6))

plt.hist(data, bins=10, density=True, alpha=0.5, label='数据直方图')
plt.plot(x, norm.pdf(x, true_mu, true_sigma), 'g-', linewidth=2, label='真实分布')
plt.plot(x, norm.pdf(x, mu_mle, sigma_mle), 'b--', linewidth=2, label=f'MLE: μ={mu_mle:.2f}, σ={sigma_mle:.2f}')
plt.plot(x, norm.pdf(x, mu_bayes, true_sigma), 'r:', linewidth=2, label=f'Bayes: μ={mu_bayes:.2f}')

plt.xlabel('x')
plt.ylabel('概率密度')
plt.title('最大似然估计 vs 贝叶斯估计')
plt.legend()
plt.savefig('mle_vs_bayes.png', dpi=150)
plt.show()

print(f"真实参数: μ={true_mu}, σ={true_sigma}")
print(f"MLE估计: μ={mu_mle:.4f}, σ={sigma_mle:.4f}")
print(f"贝叶斯估计: μ={mu_bayes:.4f}")

四、本章小结

本章介绍了深度学习中必需的概率论和信息论知识:

概率基础:条件概率、贝叶斯定理、边缘概率是理解生成模型和贝叶斯方法的基础。

概率分布:伯努利分布、分类分布、高斯分布是深度学习中最常见的分布。softmax函数将logits转化为分类分布,sigmoid将logit转化为伯努利分布的参数。

信息论:熵度量不确定性,交叉熵度量分布差异,KL散度度量分布间的"距离"。交叉熵是分类任务的标准损失函数,KL散度在VAE和知识蒸馏中扮演核心角色。

最大似然估计:参数估计的基本方法。最小化交叉熵等价于最大化似然,这为分类任务使用交叉熵损失提供了理论依据。

结构化模型:条件独立假设可以大幅简化概率模型。朴素贝叶斯和贝叶斯网络是条件独立的典型应用。

概率论和信息论是深度学习的理论基石。理解它们,才能明白为什么模型这样设计、损失函数为什么这样选择、正则化为什么有效。


五、思考与练习

思考题

为什么分类任务用交叉熵损失比均方误差更好?从梯度的角度分析。

信息熵和热力学熵有什么联系和区别?

KL散度为什么不满足三角不等式?什么情况下可以替代为真正的距离度量?

贝叶斯定理中的先验选择对结果有什么影响?如何选择合理的先验?

最大似然估计为什么容易过拟合?贝叶斯方法如何解决这个问题?

编程练习

交叉熵实现:手动实现softmax和交叉熵损失,与PyTorch的实现对比,确保数值一致性。

KL散度可视化:绘制两个高斯分布之间的KL散度随参数变化的热力图。

MLE vs MAP:实现高斯分布的MLE和MAP估计,比较不同先验对结果的影响。

信息增益:在决策树中实现基于信息增益的特征选择。

β-VAE实验:改变β值,观察KL散度和重构质量的权衡。

2/10概率与信
0%