第3章 PAE的数学推导:变分推断、ELBO及重参数化技巧
好,咱们进入硬核部分。PAE(Probabilistic Autoencoder)的核心不是编解码结构,而是它背后那套概率图模型——尤其是变分推断那一套。
说实话,我第一次看变分推断时,满脑子都是「这玩意儿到底凭什么能近似后验?」后来在项目中踩过几次坑,才算真正理解了它的套路。今天我把这套逻辑掰开揉碎,结合PAE一起讲明白。
3.1 从贝叶斯的困境说起
在PAE里,我们希望学到数据x的隐变量z的后验分布 p(z|x)。但真实后验往往算不出来——积分太复杂。
举个例子:假设z是10维隐变量,x是图片,那积分 ∫ p(x|z)p(z) dz 你根本没法解析算。我当年第一次跑高维数据时就卡在这儿,想着「是不是我数学太差」,后来发现大家都这样。
于是我们用变分推断:找一个容易计算的分布 q(z|x) 去逼近真实后验 p(z|x)。
好,问题来了——KL散度本身还带着p(z|x),而p(z|x)正是我们求不到的。怎么办?
3.2 ELBO登场——等价转换
我们写一下KL散度公式:
KL(q(z|x) || p(z|x)) = ∫ q(z|x) log[ q(z|x) / p(z|x) ] dz
展开 p(z|x) = p(x|z)p(z)/p(x),得到:
KL = ∫ q(z|x) log[ q(z|x) p(x) / (p(x|z)p(z)) ] dz
= log p(x) + ∫ q(z|x) log[ q(z|x) / p(x|z)p(z) ] dz
= log p(x) - ( ∫ q(z|x) log p(x|z) dz - KL(q(z|x) || p(z)) )
移项后得到:
log p(x) - KL = ELBO
其中 ELBO = E_{z~q}[log p(x|z)] - KL(q(z|x) || p(z))
这个ELBO就是证据下界(Evidence Lower BOund)。
3.3 变分自编码器与PAE的联系
PAE直接套用了VAE的变分框架:编码器输出 q(z|x)(通常是高斯分布的均值和方差),解码器负责 p(x|z)。但PAE在损失函数里引入了异常值惩罚项,这个咱们后面再细讲。
你先记着这结构:
| 组件 | 作用 |
|---|---|
| 编码器 (Encoder) | 将x映射到近似后验 q(z|x) 的参数(μ, σ) |
| 隐变量采样 | 从q(z|x)中采样一个z(需要重参数化) |
| 解码器 (Decoder) | 根据z重建x,计算 log p(x|z) |
| ELBO损失 | 最大化 ELBO = E[log p(x|z)] - KL(q||p) |
3.4 重参数化技巧——为什么你需要它?
你想想看,我们要求梯度来训练网络,但采样这个操作是不可导的。假设q(z|x)是正态分布 N(μ, σ²),你直接采样z ~ N(μ, σ²),那z这个随机节点的梯度没法传回μ和σ。
重参数化的解决方式很简单——把随机性分离出来:
z = μ + σ * ε, 其中 ε ~ N(0, 1)
现在z的可导部分来自μ和σ,随机性全由固定的ε提供。这样梯度可以顺利流过μ和σ节点。
具体做法:
- 编码器输出μ和logσ(取log是为了保证σ正数)
- 从标准正态分布采样ε
- 计算 z = μ + exp(logσ) * ε
- 把z传给解码器
代码片段看起来像这样:
def reparameterize(mu, logvar):
std = torch.exp(0.5 * logvar)
eps = torch.randn_like(std)
return mu + eps * std
这个技巧让整个PAE的ELBO损失变得可微,梯度才能往下传。
3.5 完整的训练损失
PAE的损失函数在ELBO基础上多了一个异常值约束项,但核心还是ELBO。咱们先写出标准ELBO损失(取负号变成最小化问题):
L_ELBO = - E_{z~q}[log p(x|z)] + KL(q(z|x) || p(z))
第一项是重建损失——对于连续数据常用MSE,对于离散数据用交叉熵。
第二项KL散度,在p(z)=N(0,1)且q(z|x)=N(μ, σ²)时,有闭合解:
KL = -0.5 * sum( 1 + log(σ²) - μ² - σ² )
这个公式你们可以手推一遍,挺有意思的。我在项目里直接写了这个函数:
def kl_divergence(mu, logvar):
return -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp(), dim=1)
整体损失加上PAE的异常值项(后面章节再展开),就是完整的训练目标。
3.6 一张图串起整个推导
下面我把变分推断→ELBO→重参数化这条线画成结构图,你一眼就能看清逻辑链。
3.7 实操中你需要注意什么
我把自己踩过的坑列出来,你少走弯路。
- KL退火: 训练初期KL项太强,模型直接忽略重建——我遇到过,重建出来的全是均值。解决办法:让KL权重从0慢慢升到1。
- logvar初始值: 千万别把logvar初始设成很大的正数,否则σ巨大,采样噪声过强。我一般初始成 -3 ~ -1。
- 数值稳定性: 计算KL时用
logvar.exp()可能溢出,建议用torch.exp(logvar).clamp(min=1e-8)。
3.8 小结
PAE的数学根基就是这三个东西:变分推断、ELBO、重参数化。变分推断给了我们一个可优化的下界;ELBO把优化目标拆成重建+正则两项;重参数化让整个流程可微、可学。