跳转至

14 - 贝叶斯方法

贝叶斯方法图

🎯 贝叶斯推断基础

贝叶斯定理

Text Only
P(θ|D) = P(D|θ) × P(θ) / P(D)

后验 ∝ 似然 × 先验

P(θ|D): 后验分布 - 看到数据后的参数分布
P(D|θ): 似然 - 参数给定下数据的概率
P(θ):   先验分布 - 看到数据前的参数信念
P(D):   证据 - 归一化常数

贝叶斯 vs 频率学派

Text Only
频率学派:
- 参数是固定但未知的常数
- 用最大似然估计(MLE)
- θ_MLE = argmax P(D|θ)

贝叶斯学派:
- 参数是随机变量,有分布
- 用贝叶斯推断
- 得到完整的后验分布 P(θ|D)

📊 共轭先验

概念

Text Only
如果先验和后验属于同一分布族,则称该先验为似然的共轭先验

常见共轭对:
- 似然: 二项分布 → 先验: Beta分布
- 似然: 正态分布 → 先验: 正态分布
- 似然: 泊松分布 → 先验: Gamma分布

Beta-二项分布示例

Python
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

# 先验: Beta(α, β)
alpha_prior, beta_prior = 2, 2

# 观测数据: 10次抛掷,7次正面
n_trials = 10
n_heads = 7

# 后验: Beta(α + k, β + n - k)
alpha_post = alpha_prior + n_heads
beta_post = beta_prior + n_trials - n_heads

# 可视化
x = np.linspace(0, 1, 100)
plt.plot(x, stats.beta.pdf(x, alpha_prior, beta_prior), label='Prior')
plt.plot(x, stats.beta.pdf(x, alpha_post, beta_post), label='Posterior')
plt.legend()
plt.show()

🧮 贝叶斯线性回归

模型定义

Text Only
似然: y ~ N(Xw, σ²I)
先验: w ~ N(0, λ⁻¹I)

后验: w|y ~ N(μ_n, Σ_n)
其中:
Σ_n = (λI + σ⁻²XᵀX)⁻¹
μ_n = σ⁻²Σ_nXᵀy

代码实现

Python
import numpy as np

class BayesianLinearRegression:
    def __init__(self, alpha=1.0, beta=1.0):  # __init__构造方法,创建对象时自动调用
        """
        alpha: 先验精度 (1/先验方差)
        beta: 噪声精度 (1/噪声方差)
        """
        self.alpha = alpha
        self.beta = beta
        self.mean = None
        self.cov = None

    def fit(self, X, y):
        """计算后验分布"""
        n_features = X.shape[1]

        # 后验协方差
        self.cov = np.linalg.inv(
            self.alpha * np.eye(n_features) +
            self.beta * X.T @ X
        )

        # 后验均值
        self.mean = self.beta * self.cov @ X.T @ y

        return self

    def predict(self, X, return_std=True):
        """预测分布"""
        y_mean = X @ self.mean

        if return_std:
            # 预测方差
            y_var = 1/self.beta + np.sum(X @ self.cov * X, axis=1)
            y_std = np.sqrt(y_var)
            return y_mean, y_std

        return y_mean

# 使用示例
from sklearn.datasets import make_regression
from sklearn.preprocessing import StandardScaler

X, y = make_regression(n_samples=100, n_features=2, noise=10)
X = StandardScaler().fit_transform(X)

model = BayesianLinearRegression(alpha=1.0, beta=0.1)
model.fit(X, y)

# 预测带不确定性
y_pred, y_std = model.predict(X)

🎯 高斯过程 (Gaussian Process)

核心思想

Text Only
定义函数上的分布,而非参数上的分布

任意有限点的函数值服从联合高斯分布

f ~ GP(m, k)

m(x): 均值函数
k(x, x'): 协方差函数(核函数)

常用核函数

Python
import numpy as np

def rbf_kernel(x1, x2, length_scale=1.0, sigma_f=1.0):
    """RBF/高斯核"""
    sqdist = (np.sum(x1**2, 1).reshape(-1, 1) +  # reshape重塑数组形状
              np.sum(x2**2, 1) - 2 * np.dot(x1, x2.T))  # np.dot计算点积/矩阵乘法
    return sigma_f**2 * np.exp(-0.5 * sqdist / length_scale**2)

def linear_kernel(x1, x2, sigma_b=0.0, sigma_v=1.0):
    """线性核"""
    return sigma_b**2 + sigma_v**2 * (x1 @ x2.T)

def periodic_kernel(x1, x2, period=1.0, length_scale=1.0):
    """周期核"""
    dist = np.abs(x1[:, None] - x2[None, :])
    return np.exp(-2 * (np.sin(np.pi * dist / period) / length_scale)**2)

高斯过程回归

Python
class GaussianProcess:
    def __init__(self, kernel=rbf_kernel, noise=1e-5):
        self.kernel = kernel
        self.noise = noise
        self.X_train = None
        self.y_train = None
        self.K = None

    def fit(self, X, y):
        self.X_train = X
        self.y_train = y

        # 计算训练集核矩阵
        self.K = self.kernel(X, X) + self.noise * np.eye(len(X))
        return self

    def predict(self, X_test, return_std=True):
        """预测后验分布"""
        # 计算测试集与训练集的核
        K_s = self.kernel(self.X_train, X_test)
        K_ss = self.kernel(X_test, X_test)

        # 计算后验均值和协方差
        K_inv = np.linalg.inv(self.K)
        mu_s = K_s.T @ K_inv @ self.y_train

        if return_std:
            cov_s = K_ss - K_s.T @ K_inv @ K_s
            std_s = np.sqrt(np.diag(cov_s))
            return mu_s, std_s

        return mu_s

# 使用示例
import matplotlib.pyplot as plt

# 训练数据
X_train = np.array([[1], [2], [3], [4], [5]])
y_train = np.sin(X_train).ravel()

# 测试点
X_test = np.linspace(0, 6, 100).reshape(-1, 1)

# 拟合GP
gp = GaussianProcess()
gp.fit(X_train, y_train)
mu, std = gp.predict(X_test)

# 可视化
plt.plot(X_test, mu, 'b-', label='Prediction')
plt.fill_between(X_test.ravel(), mu - 2*std, mu + 2*std, alpha=0.2)
plt.scatter(X_train, y_train, c='r', label='Training data')
plt.legend()
plt.show()

🔄 变分推断 (Variational Inference)

核心思想

Text Only
问题:后验分布 P(θ|D) 难以计算
解决:用一个简单的分布 Q(θ) 近似

优化目标:最小化 KL(Q||P)
= argmin KL(Q(θ) || P(θ|D))

等价于最大化 ELBO (Evidence Lower BOund):
ELBO = E_Q[log P(D|θ)] - KL(Q(θ) || P(θ))

变分自编码器 (VAE)

已在 19-生成模型深度解析.md 中详细介绍。


🎯 贝叶斯优化

应用场景

Text Only
黑盒函数优化:
- 超参数调优
- 实验设计
- A/B测试

特点:
- 函数评估昂贵
- 需要样本高效
- 平衡探索与利用

采集函数

Text Only
1. 期望改进 (Expected Improvement, EI)
2. 概率改进 (Probability of Improvement, PI)
3. 上置信界 (Upper Confidence Bound, UCB)
Python
from skopt import gp_minimize
from skopt.space import Real, Integer
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

# 定义搜索空间
space = [
    Integer(10, 200, name='n_estimators'),
    Integer(2, 20, name='max_depth'),
    Real(0.01, 1.0, name='min_samples_split')
]

# 目标函数
def objective(params):
    n_estimators, max_depth, min_samples_split = params
    model = RandomForestClassifier(
        n_estimators=n_estimators,
        max_depth=max_depth,
        min_samples_split=min_samples_split,
        random_state=42
    )
    score = cross_val_score(model, X, y, cv=5).mean()
    return -score  # 最小化负准确率

# 贝叶斯优化
result = gp_minimize(
    objective,
    space,
    n_calls=50,
    random_state=42
)

print(f"最佳参数: {result.x}")
print(f"最佳得分: {-result.fun:.4f}")

💡 总结

Text Only
贝叶斯方法优势:
✅ 天然的不确定性量化
✅ 小样本场景表现好
✅ 避免过拟合
✅ 可解释性强

贝叶斯方法挑战:
❌ 计算复杂度高
❌ 后验推断困难
❌ 先验选择主观

实践建议:
1. 从贝叶斯线性回归开始
2. 掌握高斯过程用于不确定性建模
3. 使用变分推断处理复杂模型
4. 贝叶斯优化用于超参数调优

下一步:学习 15-其他监督学习算法.md,了解更多经典算法!