VAE讲解

这段时间看了VAE的有关知识,但网上关于VAE的讲解较为理论复杂,我这里就记录一下自己的想法了。

定义

VAE从概率的角度描述隐空间与输入样本,它将样本的隐变量建模为概率分布, 而非像AE一样把隐变量看做是离散的值。

AE VS VAE

AE VS VAE}

损失函数

loss

我们假设隐变量的概率分布为标准正态分布 N ( 0 , 1 ) N(0, 1) N(0,1)(这种分布不是必须的,也可以是其它分布)。而描述正态分布需要有两个参数 μ x , σ x \mu_x, \sigma_x μx,σx,在encoder端使用神经网络来拟合这两个参数。在decoder端,使用神经网络来还原出原始图像。因此,VAE的损失函数分为两部分:

  • 正则化项,也就是KL Loss

  • 重构损失

L = L R e c o n + L K L = ∥ x − x ^ ∥ 2 + K L [ N ( μ x , σ x ) , N ( 0 , 1 ) ] = ∥ x − d ( z ) ∥ 2 + K L [ N ( μ x , σ x ) , N ( 0 , 1 ) ] \begin{aligned} L &= L_{Recon} + L_{KL} \\ &= \|x-\hat{x}\|^{2}+\mathrm{KL}[N(\mu_{x}, \sigma_{x}), N(0, 1)] \\ &= \|x-d(z)\|^{2}+KL[N(\mu_{x}, \sigma_{x}), N(0, 1)] \end{aligned} L=LRecon+LKL=xx^2+KL[N(μx,σx),N(0,1)]=xd(z)2+KL[N(μx,σx),N(0,1)]

关于 K L [ N ( μ x , σ x ) , N ( 0 , 1 ) ] KL\left[N\left(\mu_{x}, \sigma_{x}\right), N(0,1)\right] KL[N(μx,σx),N(0,1)]的推导如下:

K L ( N ( μ , σ 2 ) ∥ N ( 0 , 1 ) ) = ∫ 1 2 π σ 2 e − ( x − μ ) 2 2 σ 2 ( log ⁡ e − ( x − μ ) 2 2 σ 2 2 π σ 2 e − x 2 2 2 π ) d x = ∫ 1 2 π σ 2 e − ( x − μ ) 2 2 σ 2 log ⁡ { 1 σ 2 exp ⁡ { 1 2 [ x 2 − ( x − μ ) 2 σ 2 ] } } d x = 1 2 ∫ 1 2 π σ 2 e − ( x − μ ) 2 2 σ 2 [ − log ⁡ σ 2 + x 2 − ( x − μ ) 2 σ 2 ] d x = 1 2 ( − log ⁡ σ 2 + μ 2 + σ 2 − 1 ) \begin{aligned} & KL\left(N\left(\mu, \sigma^{2}\right) \| N(0,1)\right) \\ &= \int \frac{1}{\sqrt{2 \pi \sigma^{2}}} e^{\frac{-(x-\mu)^{2}}{2 \sigma^{2}} }\left(\log \frac{\frac{e^{ \frac{-(x-\mu)^{2}}{2 \sigma^{2}} }}{\sqrt{2 \pi \sigma^{2}}} }{\frac{e^{\frac{-x^{2}}{2}}}{\sqrt{2 \pi}} }\right) d x \\ &= \int \frac{1}{\sqrt{2 \pi \sigma^{2}}} e^{\frac{-(x-\mu)^{2}}{2 \sigma^{2}} } \log \left\{\frac{1}{\sqrt{\sigma^{2}}} \exp \left\{\frac{1}{2}\left[x^{2}- \frac{(x-\mu)^{2}}{\sigma^{2}} \right]\right\}\right\} d x \\ &= \frac{1}{2} \int \frac{1}{\sqrt{2 \pi \sigma^{2}}} e^{\frac{-(x-\mu)^{2}}{2 \sigma^{2}} }\left[-\log \sigma^{2}+x^{2}- \frac{(x-\mu)^{2}}{\sigma^{2}} \right] d x \\ &= \frac{1}{2}\left(-\log \sigma^{2}+\mu^{2}+\sigma^{2}-1\right) \end{aligned} KL(N(μ,σ2)N(0,1))=2πσ2 1e2σ2(xμ)2 log2π e2x22πσ2 e2σ2(xμ)2 dx=2πσ2 1e2σ2(xμ)2log{σ2 1exp{21[x2σ2(xμ)2]}}dx=212πσ2 1e2σ2(xμ)2[logσ2+x2σ2(xμ)2]dx=21(logσ2+μ2+σ21)

重参数技巧

我们从概率分布中采样出 z z z ,但是该过程是不可导的。VAE通过重参数化使得梯度不因采样而断裂。

reparams

总结

其实VAE可以看成一个做降维的model,我们希望把一个高维的特征投影到一个低维的流型上。而在VAE中,这个低维流型就是一个多元标准正态分布。为了使投影准确,于是通过希望每一个样本 X i X_i Xi的计算出来的期望与方差都接近与我们希望投影的分布,所以这里就有了KL Loss。至于重构损失,是可以使采样的时候更加准确,能够采样到我们在encode的时候投影到的点。

最佳实践

  • Pytorch实现: VAE 这篇博客实现了VAE,整体上代码简单易懂。在generation阶段,我们只需从学习到的概率分布中采样,然后送入decoder中解码,即可获得生成的图片。

  • 小小将的VAE实现,可以直接运行:https://github.com/xiaohu2015/nngen/blob/main/models/vae.ipynb


参考

<think>嗯,用户想了解如何使用变分自编码器(VAE),并且希望有一个实例教程。首先,我需要回顾一下VAE的基本原理,确保自己理解正确。VAE是一种生成模型,结合了自编码器和概率图模型,通过潜在空间的正则化来生成新数据。用户可能需要从数据准备、模型构建、训练到生成的完整流程。 接下来,我得考虑用户可能的背景。他们可能已经了解过自编码器,但对变分部分不太熟悉。因此,在教程中需要解释清楚重参数化技巧、KL散度损失等关键概念。同时,用户提供的引用中有提到使用Python和TensorFlow或PyTorch实现,所以需要选择一个框架,这里PyTorch可能更常见,所以决定用PyTorch来示例。 然后,数据准备部分,MNIST数据集是常用的,适合作为例子。需要说明如何加载数据、预处理,比如归一化到0-1之间,并转换成张量。接下来是模型结构,编码器和解码器的设计,隐变量z的生成,以及损失函数的计算,包括重构损失和KL散度。 在编写代码时,要确保语法正确,特别是LaTeX公式的格式,比如变量用$...$,独立公式用$$...$$。比如,KL散度的公式需要正确呈现。同时,注意引用用户提供的参考资料,比如引用[2]提到PyTorch实现,引用[3]解释VAE的结构,引用[4]的应用场景。 用户可能还关心实际应用,所以生成新图像的步骤和可视化部分很重要。此外,常见问题解答部分可以帮助他们解决训练中的实际问题,比如结果模糊或超参数调整。需要确保回答结构清晰,分步骤讲解,代码注释详细,方便用户跟随。 最后,生成的相关问题要覆盖原理、优化、应用等方面,帮助用户深入学习和应用VAE。需要检查是否有遗漏的关键点,比如损失函数的具体实现,或者训练循环中的细节,确保教程的完整性和准确性。</think>### 如何使用变分自编码器(VAE)实例教程 变分自编码器(VAE)是一种结合深度学习和概率图模型的生成方法,可用于数据生成、特征提取等任务。以下通过PyTorch实现MNIST手写数字生成的分步教程。 --- #### **1. 数据准备** 使用MNIST数据集,加载并预处理数据: ```python import torch from torchvision import datasets, transforms transform = transforms.Compose([transforms.ToTensor()]) train_data = datasets.MNIST(root='./data', train=True, download=True, transform=transform) train_loader = torch.utils.data.DataLoader(train_data, batch_size=128, shuffle=True) ``` 数据预处理将像素值归一化到$[0,1]$区间,便于模型训练[^2]。 --- #### **2. 模型构建** VAE包含编码器(推断潜在分布)和解码器(重构数据): ```python class VAE(torch.nn.Module): def __init__(self, input_dim=784, hidden_dim=400, latent_dim=20): super(VAE, self).__init__() # 编码器 self.fc1 = torch.nn.Linear(input_dim, hidden_dim) self.fc21 = torch.nn.Linear(hidden_dim, latent_dim) # 均值μ self.fc22 = torch.nn.Linear(hidden_dim, latent_dim) # 方差logσ² # 解码器 self.fc3 = torch.nn.Linear(latent_dim, hidden_dim) self.fc4 = torch.nn.Linear(hidden_dim, input_dim) def encode(self, x): h = torch.relu(self.fc1(x)) return self.fc21(h), self.fc22(h) def reparameterize(self, mu, logvar): std = torch.exp(0.5 * logvar) # 计算标准差σ eps = torch.randn_like(std) # 随机噪声ε return mu + eps * std # 重参数化技巧 def decode(self, z): h = torch.relu(self.fc3(z)) return torch.sigmoid(self.fc4(h)) # 输出概率值 def forward(self, x): mu, logvar = self.encode(x.view(-1, 784)) z = self.reparameterize(mu, logvar) return self.decode(z), mu, logvar ``` **关键点**: - 编码器输出潜在空间分布的均值$μ$和方差$σ^2$的对数($\log σ^2$) - 通过重参数化技巧$z = μ + ε \cdot σ$实现梯度传播[^3] --- #### **3. 损失函数** 损失函数包含重构损失(交叉熵)和KL散度: $$ \mathcal{L} = \mathbb{E}[\log p(x|z)] - \beta \cdot D_{KL}(q(z|x) \parallel p(z)) $$ ```python def loss_function(recon_x, x, mu, logvar, beta=1): BCE = torch.nn.functional.binary_cross_entropy(recon_x, x.view(-1, 784), reduction='sum') KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp()) return BCE + beta * KLD ``` 其中$\beta$用于平衡重构精度与潜在空间正则化强度[^4]。 --- #### **4. 模型训练** 设置优化器并训练模型: ```python device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = VAE().to(device) optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) for epoch in range(20): total_loss = 0 for batch_idx, (data, _) in enumerate(train_loader): data = data.to(device) optimizer.zero_grad() recon_batch, mu, logvar = model(data) loss = loss_function(recon_batch, data, mu, logvar) loss.backward() optimizer.step() total_loss += loss.item() print(f'Epoch {epoch}, Loss: {total_loss / len(train_loader.dataset):.2f}') ``` --- #### **5. 生成新数据** 从潜在空间采样生成图像: ```python import matplotlib.pyplot as plt with torch.no_grad(): sample = torch.randn(64, 20).to(device) generated = model.decode(sample).cpu() plt.figure(figsize=(8,8)) for i in range(64): plt.subplot(8,8,i+1) plt.imshow(generated[i].view(28,28), cmap='gray') plt.axis('off') ``` 生成的图像将呈现类似MNIST的手写数字样式。 --- #### **常见问题解答** **Q1: 为什么生成结果模糊?** A1: VAE倾向于生成平均化的结果,可通过调整$\beta$值或改用更复杂的解码器结构改进。 **Q2: 如何提高生成质量?** A2: 可尝试: 1. 增加网络深度 2. 使用卷积结构替代全连接层 3. 结合GAN的对抗训练方法(如VAE-GAN) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值