为什么它们在创作您自己的生成文本、艺术甚至音乐方面如此有用
与将神经网络用作回归器或分类器的更标准用法相比,变分自动编码器(VAEs)是强大的生成模型,现在的应用范围已经多种多样,从生成虚假人脸到生成纯合成音乐。
本文将探讨VAE是什么,为什么它能够如此有效地工作的直觉,以及作为各种媒体强大生成工具的用途。
但首先,为什么选择VAEs?
探索特定输入数据的一种变体[1]
当使用生成模型时,您可能只想生成一个随机的、新的输出,看起来类似于训练数据,您当然也可以使用VAEs来实现这一点。但更常见的情况是,您希望修改或探索已有数据的变化,并且不仅仅是以随机的方式,而是朝着期望的、具体的方向。这就是VAEs比目前其他任何方法都更有效的地方。
解码标准自动编码器
自动编码器网络实际上是一对相连的网络,一个编码器和一个解码器。编码器网络接收输入并将其转换为更小、更密集的表示,解码器网络可以使用该表示将其转换回原始输入。
如果您对编码器网络不熟悉,但熟悉卷积神经网络(CNNs),那么您很可能已经知道编码器的作用。
CNN内部的编码器[[a\]](https://commons.wikimedia.org/wiki/File:Typical%5Fcnn.png)
任何CNN的卷积层接收一张大图像(例如,大小为299x299x3的秩为3的张量),并将其转换为更紧凑、更密集的表示(例如,大小为1000的秩为1的张量)。然后,全连接分类器网络使用这种密集表示来对图像进行分类。
编码器类似,它只是一个接收输入并生成一个更小表示(_编码)的网络,其中包含足够的信息,以便网络的下一部分将其处理成所需的输出格式。通常,编码器与网络的其他部分一起训练,通过反向传播进行优化,以生成特定于手头任务的编码。在CNN中,生成的1000维编码是专门用于分类的。
Autoencoders将这个想法稍微颠倒过来,通过使编码器生成专门用于重建自身输入的编码。
一个标准的自编码器
整个网络通常作为一个整体进行训练。损失函数通常是输出和输入之间的均方误差或交叉熵,称为 重构损失,惩罚网络生成与输入不同的输出。
由于编码器(简单地说就是中间隐藏层的输出)的单元远少于输入,编码器必须选择丢弃信息。编码器学会在有限的编码中尽可能保留相关信息,并智能地丢弃无关部分。解码器学会获取编码并正确地将其重构为完整图像。它们共同构成一个自编码器。
标准自动编码器的问题
标准自编码器学习生成紧凑的表示并很好地重构其输入,但除了一些应用如去噪自编码器外,它们相当有限。
自动编码器在生成方面的根本问题在于,它们将输入转换为的潜在空间以及编码向量所在的位置可能不是连续的,也不容易进行插值。
仅针对重建损失进行优化
例如,在MNIST数据集上训练自动编码器,并可视化来自2D潜在空间的编码,可以揭示出不同簇的形成。这是有道理的,因为每种图像类型的不同编码使解码器更容易解码它们。如果你只是“复制”相同的图像,这是可以的。
但是当你构建一个_生成_模型时,你不想准备去_复制_你输入的相同图像。你想要从潜在空间中随机抽样,或者在连续的潜在空间中生成输入图像的变化。
如果空间存在不连续性(例如,簇之间存在间隙),并且您从那里进行采样/生成变化,解码器将简单地生成不现实的输出,因为解码器根本不知道如何处理潜在空间的那个区域。在训练过程中,它从未看到来自潜在空间该区域的编码向量。
变分自动编码器
变分自动编码器(VAEs)具有一项基本独特的特性,使它们与普通自动编码器有所区别,正是这一特性使它们在生成建模中如此有用:它们的潜在空间是 经过设计的 连续的,可以轻松进行随机采样和插值。
它通过一种乍看起来相当令人惊讶的方式实现了这一点:使其编码器不输出大小为_n_的编码向量,而是输出两个大小为n的向量:一个均值向量μ和另一个标准差向量σ。
变分自动编码器
它们构成了长度为n的随机变量向量的参数,其中μ和σ的第_i_个元素分别是第_i_个随机变量X i的均值和标准差,我们从中取样以获得采样编码,然后将其传递给解码器:
随机生成编码向量
这种随机生成意味着,即使是相同的输入,均值和标准差保持不变,由于采样,每次编码的实际结果都会有所不同。
直观地,均值向量控制输入的编码应该围绕哪里中心,而标准差控制“区域”,即编码可以从均值偏离多少。由于编码是从“圆圈”(分布)内的任何位置随机生成的,解码器学习到潜在空间中的一个点不仅指代该类别的一个样本,而且附近的所有点也指代同一类别。这使得解码器不仅可以解码潜在空间中的单个特定编码(使可解码的潜在空间不连续),还可以解码略有变化的编码,因为在训练期间解码器暴露于同一输入的编码的一系列变化。在代码中:
用于采样均值和标准差的代码
模型现在通过改变一个样本的编码来暴露于一定程度的局部变化,从而在局部尺度上产生平滑的潜在空间,即对于相似的样本。理想情况下,我们希望在不太相似的样本之间也有重叠,以便在类别之间进行插值。然而,由于向量 μ 和 σ 可以取任何值,编码器可以学习为不同类别生成非常不同的 μ,将它们聚集在一起,并最小化 σ,确保编码本身在同一样本上变化不大(即解码器的不确定性较小)。这使得解码器能够有效地重构训练数据。
我们理想情况下想要的是编码,_所有_编码尽可能接近,同时仍然保持独特性,以实现平滑插值,并且能够构建_新_样本。
为了强制执行这一点,我们引入了Kullback–Leibler散度(KL散度2)到损失函数中。两个概率分布之间的KL散度简单地衡量它们相互的_分歧_有多大。在这里最小化KL散度意味着优化概率分布参数**(μ和σ)**,使其与目标分布密切相似。
对于VAE,KL损失等同于X中所有分量X_i~N(μ_i, σ_i²)与标准正态分布之间的所有KL散度之和。当μ_i = 0,σ_i = 1时,KL损失最小化。
直观地,这种损失鼓励编码器将所有编码(对于所有类型的输入,例如所有MNIST数字)均匀分布在潜在空间的中心周围。如果它试图通过将它们聚集到特定区域远离原点来“作弊”,它将受到惩罚。
现在,仅使用KL损失会导致潜在空间中的编码密集地随机放置在潜在空间的中心附近,几乎不考虑相邻编码之间的相似性。解码器发现从这个空间解码任何有意义的东西几乎是不可能的,因为实际上并没有任何含义。
使用纯KL散度损失进行优化
然而,将这两者优化在一起会产生一个潜在空间,通过聚类保持局部尺度附近编码的相似性,但在全局范围内,与潜在空间原点非常密集(与原始轴进行比较)。
同时使用重构损失和KL散度损失进行优化
直观地说,这是重建损失的_聚类形成_特性和KL损失的_密集打包_特性达到的平衡,形成了解码器可以解码的不同聚类。这很棒,因为这意味着在随机生成时,如果你从与编码向量相同的先验分布_N_(0, I)中采样一个向量,解码器将成功解码它。而且如果你在插值,聚类之间没有突然的间隙,而是解码器可以理解的_特征平滑混合_。
最终损失函数
矢量算术
那么我们究竟如何产生我们所说的这些平滑插值呢?从现在开始,在潜在空间中进行简单的向量运算。
在样本之间插值
例如,如果您希望在两个样本之间生成一个新样本,只需找到它们均值(μ)向量之间的差异,将差异的一半添加到原始值中,然后简单地解码即可。
为示例添加新功能
关于生成_特定特征_,比如在脸上生成眼镜怎么样?找到两个样本,一个带眼镜,一个不带,从编码器获取它们的编码向量,并保存差异。将这个新的“眼镜”向量添加到任何其他人脸图像中,并解码。
从这里去哪里?
有许多进一步的改进可以在变分自动编码器上进行。确实,您可以用卷积-反卷积编码器-解码器对替换标准的全连接稠密编码器-解码器,比如这个项目[4],以生成出色的合成人脸照片。
生成名人相似照片
你甚至可以使用LSTM编码器-解码器对来自序列禺禺的数据进行训练(使用seq2seq架构的修改版本),以生成合成文本,甚至在MIDI样本之间进行插值,例如Google Brain的Magenta的MusicVAE 5":
VAEs 适用于各种类型的数据,顺序或非顺序,连续或离散,甚至带标签或完全无标签,使它们成为功能强大的生成工具。希望您现在了解 VAEs 的工作原理,并能够在自己的生成尝试中使用它们。