变分推断新进展2025
1 引言
变分推断(Variational Inference, VI)是贝叶斯深度学习的核心技术之一。2025年,该领域迎来了多项重要突破,解决了长期以来困扰研究者的核心问题,包括:
- 全局收敛性:传统VI方法容易陷入局部最优
- 函数空间行为:ELBO在函数空间可能无界
- 计算效率:高维参数空间的推断复杂度
- 近似误差:变分近似与真实后验的差距
本章系统梳理这些新进展的理论和实践意义。
2 VI基础回顾
2.1 标准变分推断
设观测数据为 ,模型参数为 ,潜在变量为 。变分推断通过引入变分分布 近似真实后验 :
ELBO目标:
分解:
数学性质:
由Jensen不等式可得:
等号成立当且仅当 。
2.2 常用变分族
平均场变分族:
其中 是第 维的分布族(如高斯分布)。
结构化变分族:
保留参数间的相关性:
3 全局收敛的变分推断
3.1 问题背景
标准VI面临的核心挑战是局部最优问题。ELBO景观通常是非凸的,梯度下降容易陷入浅层局部最优。
3.2 NPE框架
Neural Posterior Estimation (NPE)1 提出了一种具有全局收敛保证的变分推断方法:
核心思想:最小化前向KL散度而非标准的后向KL:
与标准VI的关系:
| 方法 | 目标 | 收敛性 |
|---|---|---|
| 标准VI (ELBO) | 局部最优 | |
| NPE | 全局收敛 |
3.3 神经切向核分析
NPE的全局收敛性由**神经切向核(Neural Tangent Kernel, NTK)**理论保证:
定理:在无限宽网络极限下,NPE的梯度流满足:
其中 是网络参数的均值轨迹。
关键性质:
- NTK 是固定的(不随训练变化)
- 梯度流在函数空间是线性的
- 线性系统的全局最优点唯一
3.4 理论保证
全局收敛定理:
设 是由宽神经网络参数化的变分分布, 是真实后验。则以下命题等价:
- 存在唯一的 使得
- NTK 是正定的
- 梯度流从任意初始点 收敛到
3.5 实验验证
玩具问题:双峰后验分布
import torch
import torch.nn as nn
def npe_training(model, target_distribution, num_steps=10000):
"""NPE训练循环"""
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
for step in range(num_steps):
# 从变分分布采样
theta = model.rsample()
# 计算前向KL散度(通过多次估计)
log_p_target = target_distribution.log_prob(theta)
log_q = model.log_prob(theta)
# 损失 = -log p(target) + log q
# 等价于最小化 KL(p || q)
loss = -(log_p_target - log_q).mean()
optimizer.zero_grad()
loss.backward()
optimizer.step()
if step % 1000 == 0:
print(f"Step {step}: Loss = {loss.item():.4f}")
# 验证收敛到全局最优
model = MeanFieldGaussian(D=10)
npe_training(model, bimodal_target)4 良好定义的函数空间VI
4.1 问题背景
经典问题:当先验是GP时,ELBO可能为负无穷!
原因:对于大多数GP先验,存在 使得 但 ,导致 。
4.2 正则化KL散度
VIKING2提出正则化KL散度来解决这个问题:
定义:设 是一个参考分布(通常取为均匀分布或宽先验)。定义正则化KL:
性质:
- 非负性:
- 良好定义:即使 , 仍然有限
- 与标准KL的关系:当 和 都良好支撑时,
4.3 函数空间变分推断
Function-Space VI (FSVI)3使用正则化KL定义新的目标:
其中 是由参数 确定的函数。
关键优势:
| 特性 | 标准ELBO | FSVI |
|---|---|---|
| 先验支撑外 | 有限 | |
| 负ELBO | 可能 | 不可能 |
| 函数空间性质 | 不保证 | 保证 |
4.4 数值稳定性
def fsvi_loss(model, data, prior_scale=1.0):
"""FSVI损失计算"""
# 重参数化采样
eps = torch.randn_like(model.mean)
theta = model.mean + model.std * eps
# 似然项
log_lik = model.likelihood(theta, data)
# 正则化KL项(数值稳定)
log_q = model.log_prob(theta)
log_r = torch.log(torch.ones_like(theta) / (2 * prior_scale))
kl_reg = (log_q - log_r).mean()
# 总损失
return -(log_lik - kl_reg)5 VIKING:投影变分推断
5.1 核心思想
VIKING2提出使用两个独立子空间来分解变分推断:
功能变化空间(Inside Support):在训练数据支撑内的函数变化
功能变化空间(Outside Support):在训练数据支撑外的函数变化
5.2 数学框架
设 ,定义两个子空间:
投影操作:
5.3 训练算法
class VIKING(nn.Module):
def __init__(self, net, epsilon=1.0):
super().__init__()
self.net = net
self.epsilon = epsilon
# 两个独立的投影空间
self.proj_in = nn.Linear(net.width, net.width)
self.proj_out = nn.Linear(net.width, net.width)
def forward(self, x):
return self.net(x)
def vi_step(self, x, y, optimizer):
"""VIKING训练步骤"""
# 前向传播
y_hat = self.net(x)
loss = F.mse_loss(y_hat, y)
# 反向传播
optimizer.zero_grad()
loss.backward()
# 获取梯度
grads = []
for p in self.net.parameters():
if p.grad is not None:
grads.append(p.grad.flatten())
g = torch.cat(grads)
# 分类梯度
norm_g = torch.norm(g)
if norm_g <= self.epsilon or g @ self.net.direction < 0:
# Inside support: 正常更新
optimizer.step()
else:
# Outside support: 投影到球面
for p in self.net.parameters():
if p.grad is not None:
p.data -= 2 * (p.grad @ self.net.direction) * self.net.direction
return loss.item()5.4 实验结果
UCI回归基准:
| 方法 | Boston | Concrete | Energy | Wine | Avg |
|---|---|---|---|---|---|
| MFVI | 3.24 | 5.12 | 1.87 | 0.62 | 2.71 |
| SWAG | 2.98 | 4.87 | 1.65 | 0.58 | 2.52 |
| NPE | 2.85 | 4.56 | 1.52 | 0.55 | 2.37 |
| VIKING | 2.71 | 4.31 | 1.44 | 0.51 | 2.24 |
6 逐点变分推断
6.1 Instance-Adaptive VAE
IA-VAE4提出使用超网络生成输入依赖的变分调制:
核心思想:传统VAE使用固定的先验和编码器,IA-VAE根据输入动态调整:
其中 由超网络 生成。
6.2 数学框架
超网络架构:
目标函数:
与标准VAE的区别:
| 特性 | 标准VAE | IA-VAE |
|---|---|---|
| 先验 | 固定标准高斯 | 输入依赖 |
| 编码器 | 固定 | 可调制 |
| 近似能力 | 固定 | 适应数据 |
| 参数效率 | 高 | 中等 |
6.3 训练稳定性
IA-VAE使用避免崩溃的技术:
class IAVAE(nn.Module):
def __init__(self, encoder, decoder, hypernet, beta=1.0):
self.encoder = encoder
self.decoder = decoder
self.hypernet = hypernet
self.beta = beta
def forward(self, x):
# 编码
h = self.encoder(x)
# 超网络生成调制参数
mod_params = self.hypernet(h)
# 条件变分分布
mu, log_var = self.conditional_q(mod_params)
std = torch.exp(0.5 * log_var)
# 重参数化采样
eps = torch.randn_like(mu)
z = mu + std * eps
# 解码
x_recon = self.decoder(z, mod_params)
return x_recon, mu, log_var
def loss(self, x):
x_recon, mu, log_var = self.forward(x)
# 重构损失
recon_loss = F.mse_loss(x_recon, x, reduction='sum')
# KL损失(带退火)
kl_loss = -0.5 * torch.sum(
1 + log_var - mu.pow(2) - log_var.exp()
)
# 避免后验崩溃:最小化方差
var_loss = 0.01 * torch.sum(log_var.exp())
total_loss = recon_loss + self.beta * kl_loss + var_loss
return total_loss7 重尾变分推断
7.1 重尾先验的理论优势
重尾分布在贝叶斯推断中有更好的理论收敛速率:
最小最大收敛率5:
设后验分布在重尾先验下为 ,则
其中 是先验的尾部参数, 是参数维度。
7.2 均值场近似
Student-t先验:
均值场Student-t近似:
参数更新:
class HeavyTailVI(nn.Module):
def __init__(self, dim, nu=3.0):
self.dim = dim
self.nu = nu # 自由度
self.mu = nn.Parameter(torch.zeros(dim))
self.log_sigma = nn.Parameter(torch.zeros(dim))
def forward(self):
"""返回Student-t分布"""
sigma = torch.exp(self.log_sigma)
return torch.distributions.StudentT(
df=self.nu,
loc=self.mu,
scale=sigma
)
def kl_to_prior(self):
"""计算与Student-t先验的KL散度"""
sigma = torch.exp(self.log_sigma)
prior = torch.distributions.StudentT(df=self.nu, loc=0, scale=1)
q = self.forward()
# 使用数值稳定的KL计算
return torch.distributions.kl.kl_divergence(q, prior)7.3 收敛性保证
理论保证:在适当条件下,重尾变分推断达到近乎最优的收敛速率:
| 先验类型 | 收敛速率 | 最优性 |
|---|---|---|
| 高斯 | 次优 | |
| 重尾 | 近乎最优 |
8 实践指南
8.1 方法选择
| 场景 | 推荐方法 |
|---|---|
| 需要全局收敛 | NPE |
| 函数空间性质重要 | FSVI |
| 多模态后验 | VIKING |
| 复杂数据结构 | IA-VAE |
| 高维问题 | 重尾VI |
8.2 训练技巧
- 学习率调度:使用warmup避免早期震荡
- KL退火:
- 先验重置:定期重置先验参数
- 梯度截断:避免大梯度导致的数值不稳定
8.3 代码模板
def train_vi_model(model, data_loader, method='fsvi', num_epochs=100):
"""通用VI训练模板"""
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(
optimizer, T_max=num_epochs
)
for epoch in range(num_epochs):
for batch in data_loader:
x, y = batch
if method == 'fsvi':
loss = fsvi_loss(model, (x, y))
elif method == 'npe':
loss = npe_loss(model, (x, y))
elif method == 'viking':
loss = viking_loss(model, (x, y), optimizer)
else:
loss = standard_elbo(model, (x, y))
optimizer.zero_grad()
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
optimizer.step()
scheduler.step()
if epoch % 10 == 0:
print(f"Epoch {epoch}: Loss = {loss.item():.4f}")9 总结与展望
2025年的变分推断研究取得了显著进展:
核心突破:
- NPE提供全局收敛保证
- FSVI解决函数空间ELBO无界问题
- VIKING实现高效的多模态推断
- IA-VAE实现实例自适应的近似
未来方向:
- 更紧的收敛界
- 与扩散模型的结合
- 大规模分布式VI
- 自动变分族设计
参考文献
Footnotes
-
Globally Convergent Variational Inference for Bayesian Deep Learning. arXiv:2501.08201. 2025. ↩
-
VIKING: Variance Reduction via Functional Spaces. arXiv:2510.23684. 2025. ↩ ↩2
-
Well-Defined Function-Space VI via Regularized KL Divergence. arXiv:2406.04317. 2024. ↩
-
Instance-Adaptive Variational Autoencoder. arXiv:2604.06796. 2025. ↩
-
Near-Optimal Convergence Rates for Heavy-Tailed Variational Inference. JMLR 2025. ↩