动态贝叶斯网络
概述
动态贝叶斯网络(Dynamic Bayesian Networks, DBN)是贝叶斯网络在时序数据上的扩展,用于建模随时间演化的随机系统。与隐马尔可夫模型(HMM)等专门的时序模型相比,DBN提供了一个统一的框架,可以灵活地表示各种时序依赖关系12。
DBN的核心思想:将时间维度显式地纳入图结构,通过在相邻时间片之间添加边来建模时间依赖性。
1. DBN基础定义
1.1 形式化定义
DBN由以下要素组成:
- 时间片数量 :序列长度
- 节点集合 :时刻 的随机变量集合
- 时间片内结构 :片内条件独立性(相当于贝叶斯网络结构)
- 时间片间结构 :片间条件依赖(过渡模型)
- 初始分布 : 时的先验分布
DBN的关键假设是马尔可夫假设:给定当前状态,过去状态与未来状态条件独立。
1.2 展开表示
DBN可以通过”展开”(Unrolling)转换为有限或无限的静态贝叶斯网络:
时间片1: X1₁ ──► X1₂
│
▼
时间片2: X2₁ ──► X2₂
│
▼
时间片3: X3₁ ──► X3₂
展开后的网络包含所有时间片的节点和片间边,每条边代表条件概率关系。
1.3 DBN与HMM的关系
HMM可以视为DBN的特例:
HMM结构:
Y₁ Y₂ Y₃ ... Yₙ (观测)
│ │ │ │
▼ ▼ ▼ ▼
X₁──►X₂──►X₃──►...──►Xₙ (隐状态)
| 特性 | HMM | DBN |
|---|---|---|
| 隐状态 | 单一离散变量 | 可以是多个变量 |
| 观测变量 | 单一变量 | 可以是多个变量 |
| 观测依赖 | 仅依赖当前隐状态 | 可依赖多个时间片 |
| 结构 | 固定 | 可自定义 |
2. DBN结构设计
2.1 马尔可夫阶数
DBN的阶数定义了过去对未来的影响范围:
| 阶数 | 定义 | 示例 |
|---|---|---|
| 0阶 | 仅依赖当前状态 | $P(X_{t+1} |
| 1阶 | 依赖最近1个状态 | $P(X_{t+1} |
| k阶 | 依赖最近k个状态 | $P(X_{t+1} |
2.2 过渡模型
时间片间条件概率表(CPT) 定义了状态转移:
例如,一阶马尔可夫链的过渡模型:
2.3 发射模型
观测变量与隐状态的条件概率分布:
常见发射模型:
- 高斯发射:
- 多项发射:
- 混合发射:高斯混合模型(GMM)
3. DBN推断算法
3.1 前向-后向算法
DBN的核心推断任务是计算边缘概率和后验概率。
前向算法
计算前向变量 :
def forward_algorithm(observations, init_prob, trans_mat, emit_mat):
"""
前向算法计算 P(X_t | Y_{1:t})
参数:
observations: 观测序列 [Y_1, ..., Y_T]
init_prob: 初始概率 [P(X_1=i)]
trans_mat: 转移矩阵 [P(X_{t+1}=j|X_t=i)]
emit_mat: 发射矩阵 [P(Y_t|X_t=i)]
返回:
alphas: 前向变量 [α_1, ..., α_T]
"""
T = len(observations)
num_states = len(init_prob)
alphas = []
# 初始化: α_1(i) = P(X_1=i) * P(Y_1|X_1=i)
alpha = init_prob * emit_mat[:, observations[0]]
alphas.append(alpha)
# 递归: α_{t+1}(j) = [Σ_i α_t(i) * A_{ij}] * B_j(Y_{t+1})
for t in range(1, T):
# 过渡
alpha = np.dot(alpha, trans_mat)
# 发射
alpha = alpha * emit_mat[:, observations[t]]
# 归一化(数值稳定性)
alpha = alpha / np.sum(alpha)
alphas.append(alpha)
return alphas后向算法
计算后向变量 :
def backward_algorithm(observations, trans_mat, emit_mat):
"""
后向算法计算 P(Y_{t+1:T} | X_t)
返回:
betas: 后向变量 [β_1, ..., β_T]
"""
T = len(observations)
num_states = trans_mat.shape[0]
betas = [np.ones(num_states)]
# 初始化: β_T(i) = 1
for t in range(T-2, -1, -1):
# 发射和转移
beta_next = betas[0] * emit_mat[:, observations[t+1]]
# 反向过渡
beta = np.dot(trans_mat, beta_next)
betas.insert(0, beta)
return betas3.2 滤波与平滑
| 任务 | 定义 | 方法 |
|---|---|---|
| 滤波 | $P(X_t | Y_{1:t})$ |
| 预测 | $P(X_{t+k} | Y_{1:t})$ |
| 平滑 | $P(X_t | Y_{1:T})$ |
平滑公式(Rauch-Tung-Striebel RTS算法):
平滑增益(smoother gain):
3.3 粒子滤波
当状态空间连续或高维时,使用序贯蒙特卡洛方法。
def particle_filter(observations, num_particles, state_prior, transition_fn, emission_fn, obs_likelihood):
"""
粒子滤波算法
参数:
observations: 观测序列
num_particles: 粒子数量
state_prior: 初始状态采样函数
transition_fn: 状态转移函数 p(x'|x)
emission_fn: 观测采样函数 p(y|x)
obs_likelihood: 观测似然函数 p(y|x)
"""
T = len(observations)
particles = [state_prior(num_particles)] # 初始粒子
weights = [np.ones(num_particles) / num_particles]
for t in range(T):
# 1. 预测:采样新的粒子
new_particles = transition_fn(particles[-1])
# 2. 更新:计算重要性权重
likelihoods = obs_likelihood(observations[t], new_particles)
new_weights = weights[-1] * likelihoods
new_weights = new_weights / np.sum(new_weights)
# 3. 重采样(如果ESS过低)
ess = 1 / np.sum(new_weights ** 2)
if ess < num_particles / 2:
indices = np.random.choice(num_particles, size=num_particles, p=new_weights)
new_particles = new_particles[indices]
new_weights = np.ones(num_particles) / num_particles
particles.append(new_particles)
weights.append(new_weights)
return particles, weights4. DBN参数学习
4.1 完全数据情况
当状态序列 完全可观测时,使用计数法:
4.2 不完全数据:EM算法
当状态不可观测时,使用Baum-Welch算法(DBN的EM版本):
E步:计算每个时间点每个状态的后验概率
M步:更新参数
4.3 变分推断
当EM难以计算时,使用变分方法近似后验:
变分自由能:
5. 应用实例
5.1 语音识别:GMM-HMM的DBN视角
传统GMM-HMM可以表示为DBN:
GMM发射 转移
┌──────────┐ ┌──────────┐
│ c₁,μ₁,Σ₁│ │ A₁₁ │
◄─►│ c₂,μ₂,Σ₂│◄──►│ A₁₂ │
│ ... │ │ ... │
└──────────┘ └──────────┘
观测Y 隐状态S
5.2 机器人定位:Kalman滤波的DBN表示
线性高斯系统的状态空间模型:
对应的DBN结构:
X_t ──► X_{t+1} (线性转移)
│
▼
Y_t (线性发射)
5.3 金融时序:随机波动率模型
DBN可以建模隐波动率 的时序演化。
6. DBN与其他时序模型的关系
6.1 DBN vs HMM
| 特性 | HMM | DBN |
|---|---|---|
| 状态维度 | 单一离散变量 | 多维,可连续 |
| 观测维度 | 单一变量 | 多变量 |
| 转移结构 | 固定一阶马尔可夫 | 可自定义 |
| 推断复杂度 | 取决于网络结构 |
6.2 DBN vs RNN/LSTM
| 特性 | DBN | RNN/LSTM |
|---|---|---|
| 表示方式 | 概率图模型 | 神经网络 |
| 不确定性 | 原生支持 | 需额外建模 |
| 可解释性 | 因果结构透明 | 黑盒 |
| 推断 | 精确/近似 | 近似 |
| 扩展性 | 随状态空间指数增长 | 可处理大状态空间 |
6.3 DBN vs SSM
状态空间模型(State Space Model)与DBN在形式上等价:
- 连续SSM:
- 离散SSM:
- DBN:图结构化的状态空间模型
7. 代码实现:完整DBN框架
import numpy as np
from typing import List, Tuple, Callable, Optional
class DynamicBayesianNetwork:
"""动态贝叶斯网络实现"""
def __init__(self, init_prob: np.ndarray, trans_mat: np.ndarray, emit_mat: np.ndarray):
"""
初始化DBN
参数:
init_prob: 初始概率分布 [N_states]
trans_mat: 转移矩阵 [N_states, N_states]
emit_mat: 发射矩阵 [N_states, N_obs] 或 [N_states] 对于连续
"""
self.init_prob = init_prob
self.trans_mat = trans_mat
self.emit_mat = emit_mat
self.num_states = len(init_prob)
def forward(self, observations: List[int]) -> Tuple[np.ndarray, float]:
"""前向算法"""
T = len(observations)
alphas = np.zeros((T, self.num_states))
# 初始化
alphas[0] = self.init_prob * self.emit_mat[:, observations[0]]
alphas[0] = alphas[0] / np.sum(alphas[0])
# 递归
for t in range(1, T):
alphas[t] = np.dot(alphas[t-1], self.trans_mat)
alphas[t] = alphas[t] * self.emit_mat[:, observations[t]]
alphas[t] = alphas[t] / np.sum(alphas[t])
log_likelihood = np.sum(np.log(np.dot(alphas[-1], np.ones(self.num_states))))
return alphas, log_likelihood
def backward(self, observations: List[int]) -> np.ndarray:
"""后向算法"""
T = len(observations)
betas = np.ones((T, self.num_states))
for t in range(T-2, -1, -1):
betas[t] = np.dot(self.trans_mat,
self.emit_mat[:, observations[t+1]] * betas[t+1])
betas[t] = betas[t] / np.sum(betas[t])
return betas
def forward_backward(self, observations: List[int]) -> Tuple[np.ndarray, np.ndarray]:
"""前向后向算法"""
alphas, _ = self.forward(observations)
betas = self.backward(observations)
# 平滑
gammas = alphas * betas
gammas = gammas / gammas.sum(axis=1, keepdims=True)
# 平滑转移
xis = np.zeros((len(observations)-1, self.num_states, self.num_states))
for t in range(len(observations)-1):
for i in range(self.num_states):
for j in range(self.num_states):
xis[t,i,j] = alphas[t,i] * self.trans_mat[i,j] * \
self.emit_mat[j, observations[t+1]] * betas[t+1,j]
xis[t] = xis[t] / xis[t].sum()
return gammas, xis
def viterbi(self, observations: List[int]) -> Tuple[List[int], float]:
"""Viterbi解码"""
T = len(observations)
delta = np.zeros((T, self.num_states))
psi = np.zeros((T, self.num_states), dtype=int)
# 初始化
delta[0] = self.init_prob * self.emit_mat[:, observations[0]]
# 递归
for t in range(1, T):
for j in range(self.num_states):
trans_probs = delta[t-1] * self.trans_mat[:, j]
delta[t, j] = np.max(trans_probs) * self.emit_mat[j, observations[t]]
psi[t, j] = np.argmax(trans_probs)
# 回溯
path = [np.argmax(delta[-1])]
for t in range(T-1, 0, -1):
path.insert(0, psi[t, path[0]])
log_prob = np.log(np.max(delta[-1]))
return path, log_prob8. 总结与展望
核心要点
- DBN提供统一框架:将各种时序概率模型纳入统一的图结构框架
- 灵活性与可解释性:可以自定义状态维度和依赖关系
- 推断算法成熟:前向-后向、粒子滤波等成熟方法可用
- 学习挑战:参数学习在高维情况下面临计算复杂度问题
未来方向
- 变分DBN:处理高维连续状态
- 深度DBN:与神经网络结合的混合模型
- 因果DBN:加入因果推断能力
- 在线DBN:实时学习和推断
参考资料
相关主题
- bayesian-networks — 贝叶斯网络基础
- hidden-markov-model — 隐马尔可夫模型
- variational-inference — 变分推断
- markov-chain — 马尔可夫链基础
- probabilistic-graphical-models-comprehensive — 概率图模型综合指南