VAE 变分自编码器

本文深入探讨了变分自编码器(VAE)的工作原理,详细解释了如何通过假设后验分布为正态分布来实现从隐变量到目标数据的生成模型。文章涵盖了分布变换、模型构建、重构误差最小化及KL散度的概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VAE

学习+整理
来源:
https://www.spaces.ac.cn/archives/5253
https://www.cnblogs.com/blogofnickchen/p/7221641.html

分布变换

VAE和GAN它们两个的目标基本是一致的——希望构建一个从隐变量Z生成目标数据X的模型,但是实现上有所不同。更准确地讲,它们是假设了Z服从某些常见的分布(比如正态分布或均匀分布),然后希望训练一个模型X=g(Z)X=g(Z),这个模型能够将原来的概率分布映射到训练集的概率分布,也就是说,它们的目的都是进行分布之间的变换。

VAE 变分自编码器

首先我们有一批数据样本 X 1 , … , X n {X1,…,Xn} X1,,Xn,其整体用 X X X来描述,我们本想根据 X 1 , … , X n {X1,…,Xn} X1,,Xn得到 X X X的分布 p ( X ) p(X) p(X),如果能得到的话,那我直接根据 p ( X ) p(X) p(X)来采样,就可以得到所有可能的 X X X了(包括{X1,…,Xn}{X1,…,Xn}以外的),这是一个终极理想的生成模型了。当然,这个理想很难实现,于是我们将分布改一改

p ( X ) = ∑ z p ( X ∣ Z ) p ( Z ) p(X) = \sum_zp(X|Z)p(Z) p(X)=zp(XZ)p(Z)

这里我们就不区分求和还是求积分了,意思对了就行。此时 p ( X ∣ Z ) p(X|Z) p(XZ)就描述了一个由Z来生成X的模型,而我们假设Z服从标准正态分布,也就是 p ( Z ) = N ( 0 , 1 ) p(Z) = N(0, 1) p(Z)=N(0,1)。如果这个理想能实现,那么我们就可以先从标准正态分布中采样一个Z,然后根据Z来算一个X,也是一个很棒的生成模型。接下来就是结合自编码器来实现重构,保证有效信息没有丢失,再加上一系列的推导,最后把模型实现。

在整个VAE模型中,我们并没有去使用 p ( Z ) p(Z) p(Z)(隐变量空间的分布)是正态分布的假设,我们用的是假设 p ( Z ∣ X ) p(Z|X) p(ZX)(后验分布)是正态分布!!

具体来说,给定一个真实样本Xk,我们假设存在一个专属于Xk的分布p(Z|Xk)(学名叫后验分布),并进一步假设这个分布是(独立的、多元的)正态分布。为什么要强调“专属”呢?因为我们后面要训练一个生成器X=g(Z),希望能够把从分布p(Z|Xk)采样出来的一个Zk还原为Xk。如果假设p(Z)是正态分布,然后从p(Z)中采样Z,那么我们怎么知道这个Z对应于哪个真实的X呢?现在p(Z|Xk)专属于Xk,我们有理由说从这个分布采样出来的Z应该要还原到Xk中去。

这时候每一个Xk都配上了一个专属的正态分布,才方便后面的生成器做还原。但这样有多少个X就有多少个正态分布了。我们知道正态分布有两组参数:均值μ和方差σ2(多元的话,它们都是向量)。用神经网络来拟合出专属于Xk的正态分布p(Z|Xk)的均值和方差!

构建两个神经网络 μ k = f 1 ( X k ) , log ⁡ σ 2 = f 2 ( X k ) \mu_k = f_1(X_k), \log\sigma^2 = f_2(X_k) μk=f1(Xk),logσ2=f2(Xk)来算它们。选择拟合 log ⁡ σ 2 \log\sigma^2 logσ2而不是直接拟合 σ 2 \sigma^2 σ2,是因为 σ 2 \sigma^2 σ2总是非负的,需要加激活函数处理,而拟合 log ⁡ σ 2 \log\sigma^2 logσ2不需要加激活函数,因为它可正可负。

最小化 D ( X k ^ , X k ) 2 D(\hat{X_k}, X_k)^2 D(Xk^,Xk)2

在这里插入图片描述

分布标准化

最小化 D ( X k ^ , X k ) 2 D(\hat{X_k}, X_k)^2 D(Xk^,Xk)2会使方差为0,方差为零就等于没有噪声了。VAE让所有的都向标准正态分布看齐,防止噪声为零,保证模型具有生成能力。方法是在重构误差的基础上加入额外的loss:

和 L μ = ∣ ∣ f 1 ( X k ) ∣ ∣ 2 和 L σ 2 = ∣ ∣ f 2 ( X k ) ∣ ∣ 2 和L_{\mu} = ||f_1(X_k)||^2 和 L_{\sigma^2} = ||f_2(X_k)||^2 Lμ=f1(Xk)2Lσ2=f2(Xk)2

因为它们分别代表了均值和方差的对数,达到标准分布就是希望它们尽量接近于0。对于这个两个损失的比例怎么选取,原论文直接算一般(各分量独立的)正态分布与标准正态分布的KL散度 K L ( N ( μ , σ 2 ) ∣ ∣ N ( 0 , 1 ) ) KL(N(\mu, \sigma^2)||N(0, 1)) KL(N(μ,σ2)N(0,1))作为这个额外的loss。

KL散度 Kullback-Leibler Divergence

在统计应用中,我们经常需要用一个简单的,近似的概率分布 f ∗ f^∗ f来描述
观察数据 D 或者另一个复杂的概率分布f。这个时候,我们需要一个量来衡量我们选择的近似分布 f ∗ f^∗ f相比原分布f究竟损失了多少信息量,这就是KL散度起作用的地方。

一个概率分布对应的熵的表达: H = − ∑ i = 1 N p ( x i ) ⋅ log ⁡ p ( x i ) H = -\sum_{i=1}^Np(x_i)\cdot \log p(x_i) H=i=1Np(xi)logp(xi)

在Variational Inference中,我们希望能够找到一个相对简单好算的概率分布q,使它尽可能地近似我们待分析的后验概率p(z|x),其中z是隐变量,x是显变量。在这里我们的“loss函数”就是KL散度,他可以很好地测量两个概率分布之间的距离。如果两个分布越接近,那么KL散度越小,如果越远,KL散度就会越大。

### 变分自编码器VAE)的原理 变分自编码器(Variational Autoencoder, VAE)是一种基于概率生成模型的方法,其核心思想是通过引入变分推断技术来学习数据的潜在分布[^1]。相比于传统的自编码器仅关注于重构输入数据的能力,VAE 进一步考虑了潜在空间的概率特性。 #### 潜在空间与先验分布 VAE 的设计假设潜在变量 \(z\) 遵循某种已知的概率分布(通常为标准正态分布 \(P(z) \sim N(0, I)\)[^5])。这种设定允许我们在训练过程中优化一个目标函数——变分下界(ELBO),以确保潜在变量的实际分布尽可能接近预定义的先验分布[^3]。 #### 训练目标 VAE 的训练目标可以通过最大化 ELBO 来描述,即最小化以下损失函数: \[ L(x; \theta, \phi) = D_{KL}(Q_\phi(z|x)||P(z)) - E_{z \sim Q_\phi}[log(P_\theta(x|z))] \] 其中, - \(D_{KL}\) 表示 KL 散度,衡量潜在变量的真实分布 \(Q_\phi(z|x)\) 和先验分布 \(P(z)\) 之间的差异; - \(E_{z \sim Q_\phi}[log(P_\theta(x|z))]\) 是重构误差项,反映解码器从潜在变量重建原始数据的效果[^4]。 --- ### VAE 的实现细节 以下是 VAE 实现的一个典型 Python 示例: ```python import torch import torch.nn as nn import torch.optim as optim class VAE(nn.Module): def __init__(self, input_dim=784, hidden_dim=256, latent_dim=2): super(VAE, self).__init__() # Encoder layers self.fc_enc = nn.Sequential( nn.Linear(input_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, latent_dim * 2) # Output mean and log variance ) # Decoder layers self.fc_dec = nn.Sequential( nn.Linear(latent_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, input_dim), nn.Sigmoid() # Ensure output is between 0 and 1 ) def reparameterize(self, mu, log_var): std = torch.exp(0.5 * log_var) eps = torch.randn_like(std) return mu + eps * std def forward(self, x): h = self.fc_enc(x) mu, log_var = torch.chunk(h, chunks=2, dim=-1) z = self.reparameterize(mu, log_var) recon_x = self.fc_dec(z) return recon_x, mu, log_var def loss_function(recon_x, x, mu, log_var): reconstruction_loss = nn.BCELoss(reduction='sum')(recon_x, x) kl_divergence = -0.5 * torch.sum(1 + log_var - mu.pow(2) - log_var.exp()) return reconstruction_loss + kl_divergence # Example usage model = VAE() optimizer = optim.Adam(model.parameters(), lr=1e-3) # Dummy data (MNIST-like example) data = torch.rand((64, 784)) recon_data, mu, log_var = model(data) loss = loss_function(recon_data, data, mu, log_var) loss.backward() print(f"Total Loss: {loss.item()}") ``` 此代码展示了如何构建一个简单的 VAE 并计算对应的损失函数。`reparameterization trick` 被用于使梯度能够流经随机抽样操作[^4]。 --- ### 应用场景 VAE 在多个领域具有广泛的应用价值,主要包括但不限于以下几个方面: 1. **图像生成**:利用 VAE 学习到的数据潜在分布,可以生成新的逼真图像[^4]。 2. **异常检测**:通过对正常数据的学习,识别偏离常规模式的样本[^2]。 3. **降维可视化**:将高维数据投影至低维潜在空间以便观察和分析。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值