【干货】深入理解变分自编码器
【导读】自编码器是一种非常直观的无监督神经网络方法,由编码器和解码器两部分构成,自编码器近年来很受研究人员的欢迎。本文是机器学习工程师Jeremy撰写的一篇非常棒的博文,介绍了变分自编码器理论基础和工作原理,通过人脸示例帮助读者更直观的理解。本文强调了变分自编码器的理论推导和实现细节,在文末展示了变分自编码器作为生成模型的输出结果。希望深入理解变分自编码器的读者不妨读一读。
Variational autoencoders
变分自编码器
自编码器是发现数据的一些隐状态(不完整,稀疏,去噪,收缩)表示的模型。更具体地说,输入数据被转换成一个编码向量,其中每个维度表示从数据学到的属性。最重要的是编码器为每个编码维度输出单个值, 解码器随后接收这些值并尝试重新创建原始输入。
变分自编码器(VAE)提供了描述隐空间观察的概率方式。因此,我们不需要构建一个输出单个值来描述每个隐状态属性的编码器,而是要用编码器描述每个隐属性的概率分布。
▌直觉
举个例子,假设我们已经在一个大型人脸数据集上训练了一个Autoencoder模型, encoder的维度是6。理想情况下, 我们希望自编码器学习面部的描述性属性,比如肤色,人是否戴眼镜,从而能够用一些特征值来表示这些属性。
在上面的示例中,我们使用单个值来描述输入图像的隐属性。但是,我们其实更愿意用一个分布去表示每个隐属性。比如, 输入蒙娜丽莎的照片,我们很难非常自信的为微笑属性分配一个具体值, 但是用了变分自编码器, 我们有能比较自信的说微笑属性服从什么分布。
通过这种方法,我们现在将给定输入的每个隐属性表示为概率分布。当从隐状态解码时,我们将从每个隐状态分布中随机采样,来生成向量作为解码器的输入。
注意:对于变分自编码器,编码器有时被称为识别模型,而解码器有时被称为生成模型。
通过构造我们的编码器来输出一系列可能的值(统计分布),然后随机采样该值作为解码器的输入,我们能够学习到一个连续,平滑的隐空间。因此,在隐空间中彼此相邻的值应该与非常类似的重建相对应。而从隐分布中采样到的任何样本,我们都希望解码器理解, 并准确重构出来。
▌统计动机
假设存在一些生成观测值的隐藏变量。
我们只能看到,但我们想推断的特征。换句话说,我们想计算
。
不幸的是,计算
是相当困难的。
这通常是一个棘手的问题。但是,我们可以应用变分推断来估计这个值。
我们想用一个比较简单的分布
来近似
。如果我们可以确定
的参数,又能保证它与
非常相似,有时候就可以用
来作近似推理。
KL散度是衡量两个概率分布之间的差异的度量。因此,如果我们想确保
与
类似,我们可以使两个分布之间的KL散度最小化。
Ali Ghodsi博士在这里演示了一个完整的推导,结果表明最小化上述表达式即最大化以下表达式:
第一项代表重建的似然估计,第二项确保我们学习到的分布q与真实的先验分布p相似性。
https://www.youtube.com/watch?v=uaaqyVS9-rM&feature=youtu.be&t=19m42s
为了重新审视我们的图模型,我们可以使用来推断用于生成观察的可能隐变量(即隐状态)。我们可以进一步将此模型构造成神经网络架构,其中编码器学习从到的映射,并且解码器模型学习从到的映射。
这个网络的损失函数将包括两个项,一个惩罚重建误差(可以认为是最大化重建可能性,如前所述),第二项鼓励我们学习的分布
与真实的分布
相似。对于隐空间的每个维度,我们假设先验分布
遵循单位高斯分布。
▌实现
前面的章节,建立了变分自编码器结构的统计动机。在本节中,我将提供自己构建这种模型的实现细节。
与在标准自编码器中直接输出隐状态值不同,VAE的编码器模型的输出描述的是每个维度分布。既然我们假设先验p(z)服从正态分布,我们将输出两个向量来描述隐状态分布的均值和方差。如果我们要构建一个真正的多元高斯模型,我们需要定义一个协方差矩阵来描述每个维度是如何相关的。但是,我们将做一个简化的假设,即我们的协方差矩阵只在对角线上有非零值,这允许我们用简单的向量来描述这些信息
然后,我们的解码器将通过从这些定义的分布中抽样来生成一个隐向量,并开始重建原始输入。
但是,这个抽样过程需要额外的关注。在训练模型时,我们使用反向传播来计算网络中每个参数与最终输出损失之间的关系。但是,我们无法为随机抽样过程做到这一点。幸运的是,我们可以利用一种称为“Reparameterization ”的聪明想法,即从单位高斯随机抽样ε,然后将随机抽样的ε乘以隐分布的均值μ,并用隐分布的方差σ对其进行缩放。
通过这种Reparameterization ,我们现在可以优化分布的参数,同时仍然保持从该分布随机采样的能力。
注意:为了处理网络可能学到的σ为负值这一事实,我们通常会通过网络学习logσ并且指数化这个值来得到隐分布的方差。
▌隐空间的可视化
为了理解变分自编码器模型的含义及其与标准自编码器体系结构的差异,检验隐空间是必要的, 这篇博客文章介绍了关于这个主题的一个很好的讨论,我将在本节中对此进行总结。
变分自编码器的主要优点是我们能够学习输入数据的平滑隐状态表示。对于标准的自编码器,我们只需要学习一个编码,它允许我们重现输入。正如你在最左边的图中可以看到的,只关注重建损失确实允许我们分离出不同的类(在这种情况下是MNIST数字),这允许我们的解码器模型能够重现原始手写数字,但是在隐空间中可能数据的分布是不均匀的。换句话说,隐空间中的某些区域并不代表我们观察到的任何数据。
另一方面,如果我们只关心隐分布与先验分布类似(通过我们的KL散度损失项),我们最终将使用相同的单位高斯描述每个观测值,在随后的抽样和可视化, 就会像上面中间的图的样子。换句话说,我们没能描述原始数据。
但是,当两个式子同时优化时,我们即希望有接近先验分布的隐状态来表述属性,也希望重建误差比较小。
当我构建一个变分自编码器时,我喜欢检查数据中的几个样本的隐维度以查看分布的特征。
如果我们观察到隐分布非常狭窄,我们可以用参数β> 1赋予KL散度项更高的权重,鼓励网络学习更广泛的分布。这种简单的观察导致了一类新的模型 - disentangled variational autoencoders的发展。事实证明,通过更加强调KL散度项,我们也隐含地强调学习的隐维度是不相关的(通过我们对对角协方差矩阵的简化假设)。
▌变分自编码器作为生成模型
通过从隐空间采样,我们可以使用解码器网络形成一个生成模型,能够创建类似于训练过程中观察到的新数据。具体来说,我们将从先前的分布中采样,假定它遵循单元高斯分布。
下图显示了在MNIST手写数字数据集上训练的变分自编码器的解码器网络生成的数据。在这里,我们从二维高斯采样了一个网格值,并展示了解码器网络的输出。
正如你所看到的,每个独立的数字都存在于隐空间的不同区域,并顺利地从一个数字变换到另一个数字。如果您想要在两个观察点之间进行插值,这种平滑转换可能非常有用。