介绍
变分自编码器(VAEs)是显式设计用于捕捉给定数据集的潜在概率分布并生成新样本的生成模型。它们采用了一个由编码器-解码器结构组成的架构。编码器将输入数据转换为潜在形式,解码器旨在基于这个潜在表示重构原始数据。VAE被编程为最小化原始数据和重构数据之间的差异,使其能够理解底层数据分布并生成符合相同分布的新样本。
VAEs的一个显著优势是它们能够生成类似于训练数据的新数据样本。由于VAE的潜在空间是连续的,解码器可以生成在训练数据点之间平滑插值的新数据点。VAEs在密度估计和文本生成等各个领域都有应用。
本文是数据科学博文马拉松的一部分。
变分自编码器的架构
一个VAE通常由两个主要组件组成:一个编码器连接和一个解码器连接。编码器网络将输入数据转换为低维的“秘密空间”,通常被称为“秘密代码”。
可以研究使用各种神经网络拓扑结构(如全连接或卷积神经网络)来实现编码器网络。所选择的架构基于数据的特性。编码器网络生成必要的参数,如高斯分布的均值和方差,以用于采样和生成潜在代码。
同样,研究人员可以使用各种类型的神经网络构建解码器网络,其目标是从提供的潜在代码中重构原始数据。
变分自编码器的架构示例:fen
![]()
VAE包括一个编码器网络,将输入数据映射到潜在代码,并且包括一个解码器网络,通过将潜在代码转换回重构数据来进行逆操作。通过进行这个训练过程,VAE学习到了一个优化的潜在表示,捕捉了数据的基本特征,从而实现精确的重构。
关于正则化的直觉
除了架构方面,研究人员还对潜在代码应用正则化,使其成为VAE的重要元素。这种正则化通过鼓励潜在代码的平滑分布而防止过拟合,而不仅仅是简单地记住训练数据。
正则化不仅有助于生成在训练数据点之间平滑插值的新数据样本,还有助于VAE生成类似于训练数据的新数据。此外,这种正则化还防止解码器网络完美地重构输入数据,促进学习更一般的数据表示,增强VAE生成多样化数据样本的能力。
在VAE中,研究人员通过将Kullback-Leibler(KL)散度项纳入损失函数来数学表达正则化。编码器网络生成高斯分布的参数(如均值和对数方差),用于对潜在代码进行采样。VAE的损失函数包括计算学习到的潜在变量的分布与先验分布(正态分布)之间的KL散度。研究人员将KL散度项纳入损失函数中,以鼓励潜在变量具有与先验分布类似的分布。
KL散度的公式如下:
KL(q(z∣x)∣∣p(z)) = E[log q(z∣x) − log p(z)]
![]()
总之,VAE中的正则化起着增强模型生成新数据样本的能力并减轻过拟合训练数据风险的关键作用。
VAE的数学细节
概率框架和假设
VAE的概率框架可以概括如下:
潜在变量
这对于在使用一个相对简单(通常是指数)的条件分布来构建的模型内表示它们至关重要。它由一个概率分布和两个变量组成:p(x, z)。虽然变量x在考虑的数据集中是可见的,但变量z不是。总的概率分布可以表示为p(x, z) = p(x|z)p(z)。
观测变量
我们有一个观测变量x,假设它遵循一个似然分布p(x|z)(例如,伯努利分布)。
似然分布
L(x, z)是一个依赖于两个变量的函数。如果我们固定x的值,似然函数可以被理解为表示特定固定x的z的概率分布。然而,如果我们固定z的值,似然函数不应被看作x的概率分布。在大多数情况下,它不符合分布的特性,例如总和为1。尽管如此,存在某些情况下,似然函数可以正式满足分布的条件,并满足总和为1的要求。
潜变量和可观测变量的联合分布如下:p(x,z) = p(x|z)p(z)。联合概率分布表示多个随机变量的概率分布。
VAE的主要目的是理解潜变量的真实后验分布,表示为p(z|x)。VAE通过使用编码器网络,利用学习到的近似分布q(z|x)来近似真实的后验分布。
后验分布
在贝叶斯统计学中,后验概率指的是在获得新信息后,一个事件发生的调整或更新概率。通过应用贝叶斯定理来计算后验概率,更新先验概率。
VAE通过最大化Evidence Lower Bound (ELBO)来学习模型参数:
ELBO = E[log(p(x|z))] – KL(q(z|x)||p(z))
ELBO由两个项组成。第一个项是重构项,它计算VAE正确恢复输入数据的能力。第二个项是KL方差,定义了估计的后验分布(q(z|x))和先验分布(p(z))之间的差异。
通过采用概率框架,VAE模型假设输入数据来自特定的概率分布的潜空间。其目标是通过最大化输入数据的似然来学习真实的后验分布。
变分推断公式
VAE中变分推断的公式如下:
- 近似后验分布:我们有后验分布的近似值q(z|x)。
- 真实后验分布:我们有真实的后验分布p(z|x)。
目标是找到一个接近真实分布(p(z|x))的类似分布(q(z|x)),使用KL散度方法来进行比较。
在VAE训练过程中,我们尝试通过增加Evidence Lower Bound (ELBO)来最小化KL散度,ELBO是重构项和KL散度的组合。重构项评估模型重构输入数据的能力,而KL散度衡量近似分布和真实分布之间的差异。
![]()
模型中的神经网络
神经网络通常用于实现VAE,其中编码器和解码器组件都被实现为神经网络。在训练过程中,VAE调整编码器和解码器网络的参数,以最小化两个关键组成部分:重构误差和变分分布与真实后验分布之间的KL散度。这个优化任务通常使用随机梯度下降或其他适当的优化算法来完成。
变分自动编码器执行
在进行变分自动编码器(VAE)的配置之前,首先要了解基本概念是至关重要的。尽管VAE的实现可能很复杂,但我们可以通过遵循一个逻辑和连贯的结构来简化学习。
我们的方法将逐渐引入基本概念,并逐步深入实现细节。我们将采用实践方法来增强理解,并在学习过程中提供说明性示例。
数据准备
提供的代码包括加载MNIST数据集,这是一个广泛应用于机器学习和计算机视觉任务的数据集。该数据集包含了60,000张手写数字(0-9)的灰度图像,每张图像的尺寸为28×28像素,以及它们对应的标签,表示每张图像所代表的数字。这使得我们能够将图像与它们对应的类别或名称进行关联。为了准备用于训练的输入数据,代码对所有像素值进行归一化,即将其除以255。此外,我们还重新塑造输入数据以增加批次维度。这个预处理步骤确保你正确地格式化了数据以进行模型训练。
import tensorflow as tf
import numpy as np
(x_train, y_train)
,(x_test, y_test) =
tf.keras.datasets.mnist.load_data()
# 对输入数据进行归一化
x_train = x_train / 255.
# 重新塑造输入数据以增加批次维度
x_train = x_train.reshape((-1, 28*28))
x_test = x_test.reshape((-1, 28*28))
模型定义
在VAE模型中,我们有一个编码器和一个解码器一起工作。编码器使用两个带有ReLU激活函数的全连接层将输入图像映射到潜在空间。另一方面,解码器以潜在向量作为输入,使用两个全连接层重构原始图像。
input_dim = 28*28
hidden_dim = 512
latent_dim = 128
编码器架构
encoder_input = tf.keras.Input(shape=(input_dim,))
encoder_hidden = tf.keras.layers.Dense(hidden_dim, activation='relu')(encoder_input)
latent = tf.keras.layers.Dense(latent_dim)(encoder_hidden)
encoder = tf.keras.Model(encoder_input, latent)
解码器架构
decoder_input = tf.keras.Input(shape=(latent_dim,))
decoder_hidden = tf.keras.layers.Dense(hidden_dim, activation='relu')(decoder_input)
decoder_output = tf.keras.layers.Dense(input_dim)(decoder_hidden)
decoder = tf.keras.Model(decoder_input, decoder_output)
VAE架构
inputs = tf.keras.Input(shape=(input_dim,))
latent = encoder(inputs)
outputs = decoder(latent)
vae = tf.keras.Model(inputs, outputs)
训练模型
为了训练VAE,我们使用Adam优化器和二元交叉熵损失函数。训练是以小批量进行的,对于每个图像计算损失并进行梯度反向传播。重复这个过程。
loss_fn = tf.keras.losses.BinaryCrossentropy()
optimizer = tf.keras.optimizers.Adam()
num_epochs = 50
for epoch in range(num_epochs):
for x in x_train:
x = x[tf.newaxis, ...]
with tf.GradientTape() as tape:
reconstructed = vae(x)
loss = loss_fn(x, reconstructed)
grads = tape.gradient(loss, vae.trainable_variables)
optimizer.apply_gradients(zip(grads, vae.trainable_variables))
print(f'Epoch {epoch+1}/{num_epochs}, Loss: {loss.numpy():.4f}')
输出:
Epoch 1: Loss - 0.3559
Epoch 2: Loss - 0.3550
.
.
.
生成样本
在这个更新的代码中,我们将latent_samples变量重新定义为形状为(5, latent_dim),使其能够生成五个随机样本而不是十个。我们还修改了for循环,使其迭代五次,显示五个生成的样本而不是十个。此外,我们调整了subplot函数,将生成的样本以一行五列的网格排列。
# 生成样本
latent_samples = tf.random.normal(shape=(5, latent_dim))
generated_samples = decoder(latent_samples)
# 绘制生成的样本
import matplotlib.pyplot as plt
for i in range(5):
plt.subplot(1, 5, i+1)
plt.imshow(generated_samples[i].numpy().reshape(28, 28), cmap='gray')
plt.axis('off')
plt.show()
输出:
![]()
当您运行此代码时,它将生成一个展示类似于MNIST测试集中的五张图片的图形。该系统将以网格排列的方式展示这些照片,一行五列。系统将以灰度显示它们,使用“灰度”颜色映射,并且没有坐标轴。
潜空间可视化
要了解VAE的潜在空间,您可以按照以下步骤进行:
- 使用VAE对训练数据进行编码,将其投影到潜在空间中。
- 使用t-SNE等降维技术,将高维的潜在空间映射到适合可视化的二维空间。
- 在二维空间中绘制数据点,以便对潜在空间进行视觉探索。
通过按照这个过程,您可以有效地可视化和理解VAE中潜在空间的潜在结构和分布。
import tensorflow as tf
from sklearn.manifold import TSNE
latent_vectors = encoder(x_train).numpy()
latent_2d = TSNE(n_components=2).fit_transform(latent_vectors)
# 绘制潜在空间
plt.scatter(latent_2d[:, 0], latent_2d[:, 1], c=y_train, cmap='viridis')
plt.colorbar()
plt.show()
输出:
![]()
通过可视化其潜在空间来了解Variational Autoencoder(VAE)训练数据的结构和组织。这种可视化技术为理解数据中的潜在模式和关系提供了有价值的手段。
结论
变分自动编码器(VAE)是一种增强型的自动编码器,它通过引入正则化技术来减轻过拟合,并确保潜在空间具有良好的生成性能。作为一种生成系统,VAE与生成对抗网络有着相似的目标。与传统的自动编码器一样,VAE由编码器和解码器组成。其训练的目标是最小化编码-解码数据与原始输入之间的重构误差。
主要要点
- 变分自动编码器(VAEs)可以学习重构和生成提供的数据集的新样本。
- 通过利用潜在空间,VAEs可以连续且平滑地表示数据,从而实现对输入数据的变化生成。
- VAE的架构包括将输入数据映射到潜在空间的编码器网络,负责从潜在空间重构数据的解码器网络以及将重构误差和正则化项结合的损失函数。
- VAEs在图像生成、异常检测和半监督学习任务中展示了其实用性。
常见问题
本文中显示的媒体不归Analytics Vidhya所有,仅由作者自行决定使用。