从零开始理解 Belief Propagation:贝叶斯网络上的消息传递
从 Pearl 的报警网络到一般因子图上的近似推断
Reading: 假设你有一个报警系统:入室盗窃(burglary)或地震(earthquake)都可能触发报警器(alarm)。听到 alarm 后,邻居 John 和 Mary 可能会打电话给你。现在你接到 John 的电话——到底发生了什么事?是 burglary 还是 earthquake?这个问题本质上是要计算 $\Pr(\text{burglary} \mid \text{John calls})$。本文从概率论第一原理出发,用这个经典例子引出 Belief Propagation(信念传播)——一种在概率图模型上高效做推断的算法。
两个基础概率定理
Belief Propagation 只用到了两条概率定理。整个算法都是这两条规则的反复应用。
加法规则(边缘化)
如果知道联合分布 $\Pr(X, Y)$,但只关心 $X$,就加掉 $Y$:
$$ \Pr(X = x) = \sum_{y} \Pr(X = x, Y = y) $$这叫边缘化。名字很形象——把概率表的"边"加起来,消去一个维度。
乘法规则(条件概率)
$$ \Pr(X, Y) = \Pr(X \mid Y) \cdot \Pr(Y) $$等价形式——贝叶斯定理:
$$ \Pr(Y \mid X) = \frac{\Pr(X \mid Y) \cdot \Pr(Y)}{\Pr(X)} $$Key Observation: 加法规则负责"消去"隐变量;乘法规则负责"组合"独立证据。BP 的全部消息更新公式都来自这两条规则的交替使用。
一个经典例子:Pearl 的报警网络
网络结构
这是 Judea Pearl 在 1988 年提出的经典贝叶斯网络,也是概率图模型教学中的 Hello World。
五个二元变量,结构如下:
|
|
箭头方向表示因果依赖:
- 入室盗窃($B \in {\text{true}, \text{false}}$)以一定概率触发报警
- 地震($E \in {\text{true}, \text{false}}$)也以一定概率触发报警
- 报警($A \in {\text{true}, \text{false}}$)触发后,John 和 Mary 各自以一定概率打电话
条件概率表(CPT)
先验概率:
$$ \Pr(B = \text{true}) = 0.001, \qquad \Pr(E = \text{true}) = 0.002 $$报警器的触发概率:
$$ \Pr(A = \text{true} \mid B, E) = \begin{cases} 0.95 & \text{if } B=\text{T}, E=\text{T} \\ 0.94 & \text{if } B=\text{T}, E=\text{F} \\ 0.29 & \text{if } B=\text{F}, E=\text{T} \\ 0.001 & \text{if } B=\text{F}, E=\text{F} \end{cases} $$邻居打电话的概率:
$$ \Pr(J = \text{true} \mid A) = 0.90, \qquad \Pr(M = \text{true} \mid A) = 0.70 $$推断问题
John 打电话来了。问:入室盗窃的概率是多少?
$$ \Pr(B = \text{true} \mid J = \text{true}) $$直接从定义出发,用加法规则展开:
$$ \Pr(B \mid J) \propto \sum_{E} \sum_{A} \sum_{M} \Pr(B, E, A, J, M) $$联合分布按网络结构因子化:
$$ \Pr(B, E, A, J, M) = \Pr(B) \cdot \Pr(E) \cdot \Pr(A \mid B, E) \cdot \Pr(J \mid A) \cdot \Pr(M \mid A) $$代入后对 $E, A, M$ 求和——一共 $2^3 = 8$ 项,手工可算。但当网络扩大到几百个节点时,暴力求和就是天文数字。
Formal Definition: 给定变量集合 $\mathcal{X} = {X_1, \dots, X_N}$ 和观测 $\mathcal{E}$,推断目标是边缘后验 $\Pr(X_i \mid \mathcal{E})$。在贝叶斯网络中,联合分布因子化为 $\Pr(\mathcal{X}) = \prod_i \Pr(X_i \mid \text{parents}(X_i))$。直接边缘化的复杂度对变量数指数增长。
因子图:把联合分布画成二分图
BP 更自然地工作在一个无向的二分图结构上——因子图(factor graph)。
转化规则
将贝叶斯网络转化为因子图:每个条件概率 $\Pr(X_i \mid \text{parents}(X_i))$ 变成一个因子节点,每个变量变成一个变量节点。因子节点 $\psi_F$ 的值等于对应的条件概率值。
报警网络的因子图结构:
|
|
(这里 $\psi_B$ 和 $\psi_E$ 是先验因子,各自只连一个变量,通常省略不画出。)
每个因子节点对应一个局部函数:
$$ \psi_B(b) = \Pr(B = b), \quad \psi_E(e) = \Pr(E = e) $$$$ \psi_A(a, b, e) = \Pr(A = a \mid B = b, E = e) $$
$$ \psi_J(j, a) = \Pr(J = j \mid A = a), \quad \psi_M(m, a) = \Pr(M = m \mid A = a) $$
全局联合分布就是所有因子之积:
$$ \Pr(B, E, A, J, M) = \psi_B(B) \cdot \psi_E(E) \cdot \psi_A(A, B, E) \cdot \psi_J(J, A) \cdot \psi_M(M, A) $$Formal Definition: 因子图 $\mathcal{G} = (\mathcal{V}, \mathcal{F}, \mathcal{E})$ 是一个二分图。$\mathcal{V}$ 是变量节点集,$\mathcal{F}$ 是因子节点集,$\mathcal{E}$ 是边集。边 $(X_i, \psi_F) \in \mathcal{E}$ 表示 $\psi_F$ 是 $X_i$ 的函数。全局函数 $\Phi(\mathcal{V}) = \prod_{F \in \mathcal{F}} \psi_F(\text{neighbors}(F))$。
为什么用二分图
二分图的优势在于清晰地分离了"变量"和"函数"两种角色:
- 变量节点负责存储和转发消息(不做计算)
- 因子节点负责接收消息并计算新的消息(做真正的计算)
这种分离使消息更新规则变得极其对称。
树状图上的精确边缘化:手工推导
报警网络的因子图是一棵树——没有环。在树上,边缘概率可以通过两轮消息传递精确计算。
Collect 阶段:从叶子到根
以计算 $A$ 的边缘分布为例,固定 $J = \text{true}$ 作为观测。写出边缘化公式并重新排列求和顺序是理解 BP 的关键一步。
从全联合分布开始:
$$ \Pr(A \mid J) \propto \sum_{B,E,M} \psi_B(B) \cdot \psi_E(E) \cdot \psi_A(A, B, E) \cdot \psi_J(J, A) \cdot \psi_M(M, A) $$注意到 $\psi_J(J, A)$ 和 $\psi_M(M, A)$ 都只依赖于 $A$(加上它们各自的观测变量),而 $\psi_B, \psi_E, \psi_A$ 一组涉及 $B, E$。利用乘法分配律重排求和:
$$ \begin{aligned} \Pr(A \mid J) \propto \; &\psi_J(J, A) \\ &\times \underbrace{\left[\sum_M \psi_M(M, A)\right]}_{\text{消息 } \mu_{\psi_M \to A}} \\ &\times \underbrace{\left[\sum_B \sum_E \psi_B(B) \cdot \psi_E(E) \cdot \psi_A(A, B, E)\right]}_{\text{消息 } \mu_{\psi_A \to A}} \end{aligned} $$这就是 BP 的全部秘密: 全局求和被拆成了三个局部求和,每个只涉及原始问题中的一个小子集。三个求和可以独立完成,然后结果相乘。
消息 1:从 $\psi_M$ 到 $A$
$$ \mu_{\psi_M \to A}(a) = \sum_{m \in \{\text{T},\text{F}\}} \psi_M(m, a) $$对 $a=\text{true}$:
$$ \mu_{\psi_M \to A}(\text{T}) = \Pr(M=\text{T} \mid A=\text{T}) + \Pr(M=\text{F} \mid A=\text{T}) = 0.70 + 0.30 = 1.0 $$对 $a=\text{false}$:
$$ \mu_{\psi_M \to A}(\text{F}) = \Pr(M=\text{T} \mid A=\text{F}) + \Pr(M=\text{F} \mid A=\text{F}) = 0.01 + 0.99 = 1.0 $$都是 1.0——因为 $\psi_M$ 这条支路没有观测约束时,它对 $A$ 的中立信息就是均匀的。
消息 2:从 $B, E$ 方向到 $A$
$$ \mu_{\psi_A \to A}(a) = \sum_{b \in \{\text{T},\text{F}\}} \sum_{e \in \{\text{T},\text{F}\}} \psi_A(a, b, e) \cdot \psi_B(b) \cdot \psi_E(e) $$对 $a=\text{true}$,代入数字:
$$ \begin{aligned} \mu_{\psi_A \to A}(\text{T}) =& \; 0.95 \times 0.001 \times 0.002 \\ &+ 0.94 \times 0.001 \times 0.998 \\ &+ 0.29 \times 0.999 \times 0.002 \\ &+ 0.001 \times 0.999 \times 0.998 \end{aligned} $$逐项计算:
$$ \begin{aligned} &= 0.0000019 \\ &\quad + 0.0009381 \\ &\quad + 0.0005794 \\ &\quad + 0.0009970 \\ &\approx 0.0025164 \end{aligned} $$对 $a=\text{false}$:
$$ \begin{aligned} \mu_{\psi_A \to A}(\text{F}) =& \; 0.05 \times 0.001 \times 0.002 \\ &+ 0.06 \times 0.001 \times 0.998 \\ &+ 0.71 \times 0.999 \times 0.002 \\ &+ 0.999 \times 0.999 \times 0.998 \end{aligned} $$$$ \begin{aligned} &= 0.0000001 \\ &\quad + 0.0000599 \\ &\quad + 0.0014186 \\ &\quad + 0.9960060 \\ &\approx 0.9974846 \end{aligned} $$合并消息
$$ \begin{aligned} \Pr(A=\text{T} \mid J) &\propto \psi_J(J=\text{T}, A=\text{T}) \times 1.0 \times 0.0025164 \\ &= 0.90 \times 0.0025164 = 0.002265 \\ \Pr(A=\text{F} \mid J) &\propto \psi_J(J=\text{T}, A=\text{F}) \times 1.0 \times 0.9974846 \\ &= 0.10 \times 0.9974846 = 0.099748 \end{aligned} $$归一化:
$$ \Pr(A=\text{T} \mid J=\text{T}) = \frac{0.002265}{0.002265 + 0.099748} \approx 0.0222 $$即约 2.22%——John 打电话来了,但报警器响的概率仍然很低。这是因为 burglary 和 earthquake 本身的先验概率极小(0.1% 和 0.2%),John 的误报率(10%)也使得"John 打来电话"本身不是一个很强的信号。
进一步:计算 $B$ 的后验
通过 $A$ 的结果可以继续向上传播,计算 $\Pr(B \mid J)$。从 $A$ 到 $\psi_A$ 的消息是上面算出的后验 $\Pr(A \mid J)$,再结合 $\psi_B$ 和 $\psi_E$ 的消息即可得到 $B$ 的边缘。
这个"接力"过程清晰地展示了 BP 的核心思想:每条消息都是对上游信息的总结,下游节点只需要乘上新的消息,不需要重新处理原始数据。
Sum-Product BP 算法的正式定义
两种消息
变量 → 因子消息(乘法规则的应用):
$$ \mu_{X \to \psi_F}(x) = \prod_{\psi_{F'} \in \mathcal{N}(X) \setminus \{\psi_F\}} \mu_{\psi_{F'} \to X}(x) $$这是"除了你之外,其他因子对我的看法"——乘积运算组合了条件独立的证据源。
因子 → 变量消息(加法 + 乘法规则的应用):
$$ \mu_{\psi_F \to X}(x) = \sum_{\text{neighbors} \setminus \{X\}} \psi_F(\text{all neighbors}) \cdot \prod_{Y \neq X} \mu_{Y \to \psi_F}(y) $$这是"固定 $X=x$ 时,综合其他变量的当前信念,这个因子对 $x$ 的认可程度"。先乘(组合其他变量的信念)再加(消去它们的值)。
边缘分布
消息收敛后,变量 $X$ 的边缘分布:
$$ \Pr(X = x) \propto \prod_{\psi_F \in \mathcal{N}(X)} \mu_{\psi_F \to X}(x) $$算法流程
|
|
树 vs 有环:Loopy BP
报警网络是树,一轮消息传递即可精确收敛。但大多数现实问题的因子图含有环。
环的影响
考虑一个三角形环:$X, Y, Z$ 两两相连,因子 $\psi_1(X,Y), \psi_2(Y,Z), \psi_3(Z,X)$。消息从 $X$ 出发,经过 $Y \to Z \to X$ 绕一圈回来——$X$ 收到了自己之前发出去的消息,相当于证据被重复计数。
- 收敛性:不保证。消息可能震荡、发散或在两个状态间周期跳跃。
- 精确性:收敛到的是近似后验,不是精确解。
这称为 Loopy BP。
收敛诊断与缓解
实践中常用的改进:
阻尼(Damping): 消息更新时不完全替换旧值,而是做加权平均:
$$ \mu_{\psi_F \to X}^{(t+1)} = \alpha \cdot \mu_{\psi_F \to X}^{\text{new}} + (1 - \alpha) \cdot \mu_{\psi_F \to X}^{(t)} $$$\alpha \in (0, 1]$ 是阻尼系数。$\alpha=0.5$ 是常用起点。阻尼可以抑制震荡,但会减慢收敛速度。
残差调度(Residual Scheduling): 不等所有消息都更新,而是优先更新"变化最大"的消息。定义消息残差:
$$ \text{Res} = \|\mu_{\psi_F \to X}^{\text{new}} - \mu_{\psi_F \to X}^{\text{old}}\|_1 $$每次选择残差最大的消息所在的边进行更新。这种调度方式在有环图上通常比同步更新收敛更快。
收敛判据: 当所有消息残差的最大值低于阈值(如 $10^{-6}$)时停止。
一个数值实验
在三角形环上运行 Loopy BP:
- $\psi_1(x,y) = \exp(-(x-y)^2/2\sigma^2)$(鼓励 $x$ 和 $y$ 接近)
- $\psi_2(y,z) = \exp(-(y-z)^2/2\sigma^2)$
- $\psi_3(z,x) = \exp(-(z-x)^2/2\sigma^2)$
当 $\sigma$ 较小时(强约束),BP 可能在两个对称解之间震荡。引入阻尼后收敛到靠近真实后验的近似解。当 $\sigma$ 较大时(弱约束),BP 快速收敛且近似误差很小。
Log-Domain BP:数值稳定性的关键
为什么要取对数
消息是一堆概率的乘积。当因子较多时,消息值会指数级趋近于零——很快就超出浮点数精度范围。
以报警网络为例,$\Pr(B=\text{T}) = 0.001$ 本身已经很小。如果网络有 20 个低概率事件相乘,结果会下溢到 0.0。
解决方案: 在对数域中运行 BP。定义:
$$ \ell_{X \to \psi_F}(x) = \log \mu_{X \to \psi_F}(x), \quad \ell_{\psi_F \to X}(x) = \log \mu_{\psi_F \to X}(x) $$对数域中的消息更新
变量→因子消息的乘法变成加法:
$$ \ell_{X \to \psi_F}(x) = \sum_{\psi_{F'} \neq \psi_F} \ell_{\psi_{F'} \to X}(x) $$因子→变量消息的"先乘后加"变成"先加后指数-对数":
$$ \ell_{\psi_F \to X}(x) = \log \sum_{\text{neighbors} \setminus \{X\}} \exp\left( \log \psi_F + \sum_{Y \neq X} \ell_{Y \to \psi_F}(y) \right) $$其中 $\log \sum \exp$ 需要用 LogSumExp 技巧稳定计算:
$$ \log(e^{a_1} + e^{a_2}) = \max(a_1, a_2) + \log(1 + e^{-|a_1 - a_2|}) $$Log-Domain BP 的Python 骨架
|
|
关键点:全程只在最后一步转回概率域,中间所有消息都在对数域中处理。
从 BP 到信念
BP 收敛后,每个变量 $X_i$ 得到一个 $k$ 维概率向量 $\mathbf{b}_i$(belief),称为信念:
$$ \mathbf{b}_i = [\Pr(X_i = \text{val}_1), \Pr(X_i = \text{val}_2), \dots, \Pr(X_i = \text{val}_k)] $$信念的三种用途
-
最大后验(MAP)估计:$\arg\max \mathbf{b}_i$——最可能的值。在报警网络中,$B$ 的 MAP 估计是"false"(因为 $\Pr(B=\text{T} \mid J) \approx 0.02$,远小于 0.98)。
-
置信度:$\max \mathbf{b}_i$——对估计的确定程度。$\mathbf{b}_i$ 越尖(一个值概率接近 1),置信度越高。
-
软信息:整个分布作为下游算法的输入。例如,用 BP 的输出初始化 MCMC 采样器可以大幅加速收敛。
报警网络的信念变化
| 变量 | 先验 ($\Pr$) | 给定 $J=\text{T}$ 后 ($\Pr$) | 变化倍数 |
|---|---|---|---|
| $B=\text{T}$ | 0.001 | ~0.02 | 20x |
| $E=\text{T}$ | 0.002 | ~0.05 | 25x |
| $A=\text{T}$ | ~0.003 | ~~0.022 | ~7x |
| $M=\text{T}$ | ~0.0027 | ~0.017 | ~6x |
有趣的现象:$B$ 和 $E$ 的概率增长倍数最大(~20-25x),但由于先验极低,后验绝对值仍然很小。这就是贝叶斯推断的直观体现——“证据支持了某种可能性,但不一定足以翻转先验判断”。
BP 在 LDPC 译码中的应用
LDPC 码简介
低密度奇偶校验码(LDPC)是一种线性纠错码。一个 $(n,k)$ LDPC 码用 $m = n-k$ 个奇偶校验方程定义,每个方程涉及一小部分码字比特。这些校验方程自然地构成一个因子图:
- 变量节点:$n$ 个码字比特 $c_1, \dots, c_n$
- 因子节点:$m$ 个校验方程 $f_1, \dots, f_m$
- 边:如果比特 $c_j$ 参与了校验 $f_i$,则连边
BP 译码
接收端收到带噪信号 $y$。译码任务是找到最可能的发送码字 $c$。
因子节点 $f_i$ 的势函数是"校验方程是否满足"的指示函数:
$$ \psi_i(c_{\mathcal{N}(i)}) = \begin{cases} 1 & \text{if } \bigoplus_{j \in \mathcal{N}(i)} c_j = 0 \\ 0 & \text{otherwise} \end{cases} $$其中 $\bigoplus$ 是二进制异或。
BP 消息在此上下文中被称为"置信传播译码":消息 $\mu_{c_j \to f_i}$ 是比特 $c_j$ 的软判决(“我认为自己是 0 的概率是 0.8,是 1 的概率是 0.2”);消息 $\mu_{f_i \to c_j}$ 是校验 $f_i$ 对 $c_j$ 的外部约束(“基于其他比特的当前信念和你必须满足的校验方程,你应该更偏向 0”)。
LDPC 码的因子图虽然含有环,但设计良好的 LDPC 码环长至少为 6,且图极其稀疏。BP 译码在这些图上接近最优性能。
一个具体例子
一个简单的 (3,1) 重复码:$c_1 = c_2 = c_3$。三个比特,两个校验方程:$c_1 \oplus c_2 = 0$,$c_1 \oplus c_3 = 0$。
因子图:
|
|
假设接收到的软信息为 $y = [0.8, -2.1, 1.5]$(正数偏向 0,负数偏向 1,绝对值表示置信度)。
初始化:$\mu_{c_j \to f_i}$ 从 $y$ 计算得到:
$$ \Pr(c_j = 0 \mid y_j) = \frac{1}{1 + \exp(-2y_j/\sigma^2)} $$第一轮 BP 迭代:
- $f_1$ 收到 $c_1$ 和 $c_2$ 的消息,计算:$c_1=0$ 且 $c_2=0$,或者 $c_1=1$ 且 $c_2=1$ 才能使校验成立。$f_1$ 据此向两端发送更新的消息。
- $f_2$ 类似地在 $c_1$ 和 $c_3$ 之间交换信息。
- 两轮迭代后,三个比特的信念趋于一致——译码成功。
Key Observation: LDPC 译码是 BP 最具规模的工业应用。5G NR 标准中使用的 LDPC 码块长度为上千比特,BP 译码器在几十轮迭代内完成译码。这得益于因子图的稀疏性(每个校验只涉及 3-6 个比特)以及 BP 消息运算的局部性。
BP 与 MCMC 的对比
BP 不是唯一的推断方法。另一种主流方法是马尔可夫链蒙特卡洛(MCMC)采样。
| 维度 | BP | MCMC(Metropolis-Hastings) |
|---|---|---|
| 输出 | 精确/近似边缘分布 | 来自后验的样本集合 |
| 收敛保证 | 树上精确;有环图上无保证 | 渐近保证收敛到真实后验 |
| 收敛速度 | 通常 10-100 轮 | 可能需要 $10^4$-$10^6$ 次采样 |
| 环的影响 | 导致近似误差 | 不影响正确性(只影响混合速度) |
| 高维问题 | 节点数增长时消息数线性增长 | 维度增加时混合时间指数增长 |
| 确定性 | 确定性算法(给定初值) | 随机算法(每次运行结果不同) |
| 调试难度 | 低(可逐消息追踪) | 高(需诊断收敛性) |
何时用 BP: 图是树状的、或者环长但稀疏、或者需要快速得到合理估计。
何时用 MCMC: 图高度有环且约束极强、或者后验多峰需要全面探索、或者需要保证渐近精确。
在实践中,BP 和 MCMC 可以互补:先运行 BP 得到信念,用信念构造一个好的提议分布(proposal distribution),再用 MCMC 做精调——这正是"近似推断 + 精调"的两阶段范式。
消息调度的艺术
BP 的收敛速度和质量高度依赖于消息更新的顺序。主要有三种调度策略:
1. flooding(同步更新)
每轮同时更新所有消息。简单、并行性好,但可能收敛慢。
2. serial(串行更新)
每轮按固定顺序逐个更新消息。刚更新的消息立即在本轮后续计算中被使用——信息传播更快。串行通常比同步收敛快约 2 倍。
3. residual belief propagation(RBP)
优先更新残差最大的消息。RBP 在有环图上往往收敛更快,但每步需要额外计算残差排序。
|
|
应用图景
BP 的应用远不止教学示例和 LDPC 译码:
| 领域 | 应用 | 图规模 | 图结构 |
|---|---|---|---|
| 通信 | Turbo 码、LDPC 码译码 | $10^3$-$10^4$ 节点 | 稀疏,有长环 |
| 计算机视觉 | 立体匹配、图像分割、去噪 | $10^5$-$10^6$ 节点 | 网格图(大量短环) |
| NLP | 句法分析、词性标注 | $10^2$-$10^3$ 节点 | 链状/树状 |
| 生物信息学 | 系统发育树、蛋白质结构预测 | $10^2$-$10^4$ 节点 | 树为主 |
| 统计物理 | Ising 模型、自旋玻璃 | $10^3$-$10^6$ 节点 | 网格/随机图 |
| 密码学 | 侧信道分析、LWE 私钥恢复 | $10^2$-$10^3$ 节点 | 随机双二部图 |
Key Observation: BP 在图的环结构和变量稀疏性之间取得了一种微妙的平衡。当因子度数小(变量对之间的约束是局部的)且环长足够大(消息在绕环回来时已经足够"衰减"),BP 的近似质量接近精确。
总结
| 概念 | 一句话 |
|---|---|
| 边缘化 | 加掉不关心的变量 |
| 因子图 | 把联合分布拆成局部函数乘积,画成二分图 |
| 消息 | 一个节点对另一个节点关于变量取值的"看法" |
| Sum-Product 规则 | 乘法组合独立证据,加法消去隐变量 |
| 树 vs 有环 | 树上精确;有环上近似,但实践中常有效 |
| Log-domain BP | 对数域中运行避免数值下溢 |
| 调度 | 串行更新比同步快;残差调度在有环图上更稳 |
| 信念 | BP 输出的软概率分布,可用于硬判决或下游算法 |
Belief Propagation 的核心思想极其简洁:利用条件独立性把全局求和拆成局部消息传递。 它不是一个万能的推断算法——有环图上的近似误差在某些问题中不可接受——但它在通信(LDPC/Turbo 译码)、计算机视觉(立体匹配)、统计物理(Ising 模型)等领域都做出了里程碑式的贡献。
进一步: BP 输出软信息。当需要做硬判决时——从一组离散候选值中选出最优组合——坐标下降是一个高效的精调工具。见同系列《从零开始理解坐标下降》。