【系列(一)|互信息 & 变分推理:你背过 ELBO,但你真懂它为什么存在吗】
系列(一)|互信息 & 变分推理:你背过 ELBO,但你真懂它为什么存在吗
开头钩子
如果你学过 VAE,你一定见过这个公式:
ELBO=Eq(z∣x)[logp(x∣z)]−DKL(q(z∣x)∥p(z)) \text{ELBO} = \mathbb{E}_{q(z|x)}[\log p(x|z)] - D_{\text{KL}}(q(z|x) \| p(z)) ELBO=Eq(z∣x)[logp(x∣z)]−DKL(q(z∣x)∥p(z))
你也知道:
- ELBO 是 Evidence Lower BOund
- 最大化 ELBO ≈ 训练 VAE
但如果我问你:
“为什么一定要用 ELBO?为什么不能直接最大化 log p(x)?”
你是不是会卡住 3 秒?
👉 这说明你学的是"公式",不是"动机"。
这篇文章只解决一个问题
变分推理到底是怎么被"逼"出来的?
一、一切从一句大实话开始
我们想训练一个生成模型 p(x)p(x)p(x)。
理论上,你应该最大化:
logp(x) \log p(x) logp(x)
但:
p(x)=∫p(x,z) dz p(x) = \int p(x,z) \, dz p(x)=∫p(x,z)dz
❗这个积分是算不出来的
- zzz 是高维隐变量
- p(x,z)p(x,z)p(x,z) 是复杂的神经网络输出
- 没有解析解
- 数值积分直接爆炸
👉 所以 log p(x) 不可算。
二、人类面对"算不出来"时的三条路
- 数值积分 → 高维直接跪
- MCMC 采样 → 准,但慢到工程上不能用
- 变分推理 → 不算它,换一个目标
三、变分推理的核心思维(请刻进 DNA)
我不算 p(z∣x)p(z|x)p(z∣x),我造一个 q(z∣x)q(z|x)q(z∣x) 逼近它。
- p(z∣x)p(z|x)p(z∣x) 是真实后验(不可算)
- q(z∣x)q(z|x)q(z∣x) 是我自己定义的近似后验(可算)
👉 这就是"变分"两个字的来源:函数空间里的优化。
四、KL 散度的直觉(比定义重要)
DKL(q∥p)=Eq[logq−logp] D_{\text{KL}}(q \| p) = \mathbb{E}_{q}\left[ \log q - \log p \right] DKL(q∥p)=Eq[logq−logp]
翻译成人话:
KL = “你用 q 替代 p 会多损失多少信息”。
举个直觉例子
- ppp:真实分布
- qqq:你脑子里的猜测
👉 KL 小:说明你猜得很准
👉 KL 大:说明你在胡猜
五、关键问题来了(这里开始和所有教程不同)
我们想让 q(z∣x)≈p(z∣x)q(z|x) \approx p(z|x)q(z∣x)≈p(z∣x),自然想:
minDKL(q(z∣x)∥p(z∣x)) \min D_{\text{KL}}(q(z|x) \| p(z|x)) minDKL(q(z∣x)∥p(z∣x))
但展开 p(z∣x)p(z|x)p(z∣x):
p(z∣x)=p(x,z)p(x) p(z|x) = \frac{p(x,z)}{p(x)} p(z∣x)=p(x)p(x,z)
❗p(x) 又出现了
👉 我们为了算 p(z|x),又撞上了那个算不出来的 p(x)。
六、变分推理最关键的一步代数(真正精华)
展开 KL:
DKL(q(z∣x)∥p(z∣x))=Eq(z∣x)[logq(z∣x)−logp(z∣x)]=Eq(z∣x)[logq(z∣x)−logp(x,z)+logp(x)] \begin{aligned} D_{\text{KL}}(q(z|x) \| p(z|x)) &= \mathbb{E}_{q(z|x)}\left[ \log q(z|x) - \log p(z|x) \right] \\ &= \mathbb{E}_{q(z|x)}\left[ \log q(z|x) - \log p(x,z) + \log p(x) \right] \end{aligned} DKL(q(z∣x)∥p(z∣x))=Eq(z∣x)[logq(z∣x)−logp(z∣x)]=Eq(z∣x)[logq(z∣x)−logp(x,z)+logp(x)]
🔍 为什么 log p(x) 可以提出期望?
注意这个符号:
Eq(z∣x)[⋅]=∫q(z∣x)⋅(⋅) dz \mathbb{E}_{q(z|x)}[\cdot] = \int q(z|x) \cdot (\cdot) \, dz Eq(z∣x)[⋅]=∫q(z∣x)⋅(⋅)dz
👉 期望是对隐变量 zzz 求的,不是对 xxx。
而 p(x)p(x)p(x) 是什么?边缘似然。它的定义是:
p(x)=∫p(x,z) dz p(x) = \int p(x,z) \, dz p(x)=∫p(x,z)dz
积分一做完,zzz 就没了。 所以 logp(x)\log p(x)logp(x) 里面根本不含 zzz。
对一个与积分变量无关的量求期望:
Ez∼q[C]=∫q(z)⋅C dz=C⋅∫q(z) dz=C \mathbb{E}_{z \sim q}[C] = \int q(z) \cdot C \, dz = C \cdot \int q(z) \, dz = C Ez∼q[C]=∫q(z)⋅Cdz=C⋅∫q(z)dz=C
常数的期望,等于常数本身。
于是:
Eq(z∣x)[logq(z∣x)−logp(x,z)+logp(x)]= Eq(z∣x)[logq(z∣x)−logp(x,z)]+Eq(z∣x)[logp(x)]= Eq(z∣x)[logq(z∣x)−logp(x,z)]+logp(x) \begin{aligned} &\mathbb{E}_{q(z|x)}\left[ \log q(z|x) - \log p(x,z) + \log p(x) \right] \\ =\ &\mathbb{E}_{q(z|x)}\left[ \log q(z|x) - \log p(x,z) \right] + \mathbb{E}_{q(z|x)}[\log p(x)] \\ =\ &\mathbb{E}_{q(z|x)}\left[ \log q(z|x) - \log p(x,z) \right] + \log p(x) \end{aligned} = = Eq(z∣x)[logq(z∣x)−logp(x,z)+logp(x)]Eq(z∣x)[logq(z∣x)−logp(x,z)]+Eq(z∣x)[logp(x)]Eq(z∣x)[logq(z∣x)−logp(x,z)]+logp(x)
👉 重排后得到:
logp(x)=Eq(z∣x)[logp(x,z)−logq(z∣x)]⏟ELBO+DKL(q(z∣x)∥p(z∣x)) \log p(x) = \underbrace{\mathbb{E}_{q(z|x)}\left[ \log p(x,z) - \log q(z|x) \right]}_{\text{ELBO}} + D_{\text{KL}}(q(z|x) \| p(z|x)) logp(x)=ELBO Eq(z∣x)[logp(x,z)−logq(z∣x)]+DKL(q(z∣x)∥p(z∣x))
七、这一步的"顿悟解释"
盯住这个等式:
log p(x) = ELBO + KL
由于 KL ≥ 0:
ELBO≤logp(x) \text{ELBO} \le \log p(x) ELBO≤logp(x)
这就是 Evidence Lower Bound 的来源。
👉 更重要的是:
- logp(x)\log p(x)logp(x) 对 qqq 来说是常数
- 所以:
↑ELBO⇔↓DKL(q∥p) \uparrow \text{ELBO} \quad \Leftrightarrow \quad \downarrow D_{\text{KL}}(q \| p) ↑ELBO⇔↓DKL(q∥p)
八、于是问题被彻底转化了
| 原始目标 | 问题 | 变分目标 |
|---|---|---|
| minDKL(q∣p)\min D_{\text{KL}}(q | p)minDKL(q∣p) | ppp 不可算 | maxELBO\max \text{ELBO}maxELBO |
| 不可算 | → | 完全可算 |
九、ELBO 为什么可算?(核心)
ELBO:
Eq(z∣x)[logp(x,z)−logq(z∣x)] \mathbb{E}_{q(z|x)}\left[ \log p(x,z) - \log q(z|x) \right] Eq(z∣x)[logp(x,z)−logq(z∣x)]
每一项都是可算的:
- logp(x,z)\log p(x,z)logp(x,z):你定义的联合分布 =p(z)⋅p(x∣z)= p(z) \cdot p(x|z)=p(z)⋅p(x∣z)
- logq(z∣x)\log q(z|x)logq(z∣x):你定义的近似后验(比如 encoder)
- 期望:对 qqq 采样 zzz 后 Monte Carlo 估计
👉 真正不可算的只有 p(x)p(x)p(x),而 ELBO 成功绕开了它。
十、"期望"两个字,到底是怎么变成训练代码的?
你可能盯着 E\mathbb{E}E 心里发虚:
“我知道它是期望,可训练的时候电脑怎么算它?”
1️⃣ 期望符号的真实含义
Eq(z∣x)[f(z)]=∫f(z)⋅q(z∣x) dz \mathbb{E}_{q(z|x)}[f(z)] = \int f(z) \cdot q(z|x) \, dz Eq(z∣x)[f(z)]=∫f(z)⋅q(z∣x)dz
在计算机里,我们几乎从来不算积分。我们用 Monte Carlo 估计:
从 q(z∣x)q(z|x)q(z∣x) 里抽一堆 zzz 的样本,算出 f(z)f(z)f(z) 的值,然后取平均。
2️⃣ 用 VAE 的实际例子走一遍
假设你有一张输入图片 xxx(一张猫图)。
Step 1:Encoder 输出一个分布
Encoder 不是输出一个确定的 zzz,而是输出两个向量:
- μ(x)\mu(x)μ(x)(均值)
- σ(x)\sigma(x)σ(x)(标准差)
然后:
q(z∣x)=N(z;μ(x),σ2(x)) q(z|x) = \mathcal{N}(z; \mu(x), \sigma^2(x)) q(z∣x)=N(z;μ(x),σ2(x))
Step 2:从分布里采样 zzz
我们从这个高斯分布里抽一个具体的 zzz 向量,比如:
z = [0.23, -1.05, 0.87, ...]
Step 3:把 zzz 代入 logp(x,z)\log p(x,z)logp(x,z) 算一个数
注意:p(x,z)=p(z)⋅p(x∣z)p(x,z) = p(z) \cdot p(x|z)p(x,z)=p(z)⋅p(x∣z)
- p(z)p(z)p(z) 是标准正态分布,把 zzz 代入公式算出对数概率密度
- p(x∣z)p(x|z)p(x∣z) 是 decoder 输出分布,计算在真实 xxx 下的对数似然
于是你得到一个标量数值,比如 -3.42。
Step 4:同时计算 logq(z∣x)\log q(z|x)logq(z∣x)
把刚才采样的 zzz 代入 encoder 输出的高斯分布公式:
log_q_zx = -2.87
Step 5:得到这一个样本的 ELBO 贡献值
single_elbo_sample = log_p_xz - log_q_zx
3️⃣ 那期望呢?我只有一个样本啊!
在 SGD 训练中,我们通常只采一个 zzz(有时多个),然后用这一个样本的值作为期望的无偏估计。
即:
Eq(z∣x)[⋅]≈1L∑l=1L[logp(x,z(l))−logq(z(l)∣x)] \mathbb{E}_{q(z|x)}[\cdot] \approx \frac{1}{L} \sum_{l=1}^L \left[ \log p(x, z^{(l)}) - \log q(z^{(l)}|x) \right] Eq(z∣x)[⋅]≈L1l=1∑L[logp(x,z(l))−logq(z(l)∣x)]
实践中 L=1L=1L=1 非常常见。
4️⃣ 代码级直觉
# 输入:x (batch_size, input_dim)
# Encoder 输出分布的参数
mu, logvar = encoder(x)
std = exp(0.5 * logvar)
# 采样 z(重参数化)
eps = random_normal_like(mu)
z = mu + eps * std
# 计算 log q(z|x)
log_q = -0.5 * sum(1 + logvar - mu**2 - logvar.exp(), dim=1)
# Decoder 重建
x_recon = decoder(z)
log_p_x_given_z = log_likelihood(x, x_recon)
# 计算 log p(z)
log_p_z = -0.5 * sum(z**2, dim=1)
# log p(x,z)
log_p_xz = log_p_x_given_z + log_p_z
# ELBO 单个样本估计
elbo = log_p_xz - log_q
# 最终 loss 是负 ELBO
loss = -elbo.mean()
5️⃣ 一句必懂总结
“期望 Eq(z∣x)\mathbb{E}_{q(z|x)}Eq(z∣x)” 翻译成训练代码就是:
从 encoder 给出的分布里抽一个 zzz,算出目标值,然后把这当作整个期望的近似,扔进反向传播。
十一、ELBO 在干什么(物理直觉)
拆开 ELBO(另一种常见形式):
ELBO=Eq(z∣x)[logp(x∣z)]−DKL(q(z∣x)∥p(z)) \text{ELBO} = \mathbb{E}_{q(z|x)}[\log p(x|z)] - D_{\text{KL}}(q(z|x) \| p(z)) ELBO=Eq(z∣x)[logp(x∣z)]−DKL(q(z∣x)∥p(z))
- 第一项:重建能力(要能解释数据)
- 第二项:复杂度惩罚(不能让 qqq 太放飞)
👉 一句话总结 ELBO:
“既要解释数据,又不能乱猜隐变量。”
十二、为什么这是所有生成模型的地基
- VAE:qqq = encoder,ppp = decoder,直接优化 ELBO
- β\betaβ-VAE:在 KL 项前面加系数 β\betaβ
- 信息瓶颈(IB):ELBO 的约束变体
十三、一个你必须知道的边界
👉 什么时候变分推理会失效?
当 q(z∣x)q(z|x)q(z∣x) 的函数族太小,无论怎么优化 KL 都很大时。
这叫 approximation gap,是 VI 的结构性缺陷。
十四、可算性对照表
| 你要算的 | 可算吗 | 原因 |
|---|---|---|
| p(x)p(x)p(x) | ❌ | 积分不可算 |
| p(z∣x)p(z|x)p(z∣x) | ❌ | 分母是 p(x)p(x)p(x) |
| p(x,z)p(x,z)p(x,z) | ✅ | 你自己定义 |
| q(z∣x)q(z|x)q(z∣x) | ✅ | 你自己定义 |
| logp(x,z)\log p(x,z)logp(x,z) | ✅ | 直接代值 |
| Eq(z∣x)[⋅]\mathbb{E}_{q(z|x)}[\cdot]Eq(z∣x)[⋅] | ✅ | Monte Carlo 采样 |
| ELBO | ✅ | 全可算 |
| DKL(q∣p(z∣x))D_{\text{KL}}(q | p(z|x))DKL(q∣p(z∣x)) | ❌ | 含 p(z∣x)p(z|x)p(z∣x) |
| DKL(q(z∣x)∣p(z))D_{\text{KL}}(q(z|x) | p(z))DKL(q(z∣x)∣p(z)) | ✅ | p(z)p(z)p(z) 是先验 |
十五、总结
变分推理的核心思想是:
面对不可计算的真实后验 p(z∣x)p(z|x)p(z∣x),引入一个可计算的近似分布 q(z∣x)q(z|x)q(z∣x),
通过最小化两者 KL 散度,将问题转化为最大化 ELBO。
ELBO 是 logp(x)\log p(x)logp(x) 的可计算下界,由重建项和正则项组成。
整个过程的数学合法性建立在 logp(x)=ELBO+DKL(q∥p)\log p(x) = \text{ELBO} + D_{\text{KL}}(q \| p)logp(x)=ELBO+DKL(q∥p) 这个恒等式上。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)