参考视频:https://www.bilibili.com/video/av15889450/?p=33
———————————————————————————
变分自编码器(Variational Autoencoder, VAE)是一种强大且富有影响力的生成模型(Generative Model),它在深度学习领域占据着核心地位。与传统的自编码器(Autoencoder, AE)旨在学习数据的压缩表示(降维)不同,VAE 的核心目标是学习数据的潜在概率分布,从而能够生成新的、与训练数据相似的数据。

其基本思路是把一堆真实样本通过编码器网络变换成一个理想的数据分布,然后这个数据分布再传递给一个解码器网络,得到一堆生成样本,生成样本与真实样本足够接近的话,就训练出了一个自编码器模型。那VAE(变分自编码器)就是在自编码器模型上做进一步变分处理,使得编码器的输出结果能对应到目标分布的均值和方差。
简单来说,VAE 结合了概率图模型(特别是变分推断)和神经网络的优点,构建了一个能够理解数据内在结构并据此进行创造的模型。
在这里插入图片描述

0、AE(auto-encoders)-自编码器

自编码器是一种数据维度压缩算法,通常用于构建一种能够输入样本并进行特征表达的神经网络和可以通过训练多层神经网络样本得到参数初始值。
在这里插入图片描述
自编码器是一种基于无监督学习的神经网络,目的在于通过不断调整参数,重构经过维度压缩的输入样本。输入层到中间层之间的映射称为编码,把中间层到输出层之间的映射称为解码。自编码器通常先通过编码得到压缩后向量,再通过解码进行重构。
在这里插入图片描述

1、VAE的设计思路

VAE最想解决的问题是什么?当然是如何构造编码器和解码器,使得图片能够编码成易于表示的形态,并且这一形态能够尽可能无损地解码回原真实图像。

这似乎听起来与PCA(主成分分析)有些相似,而PCA本身是用来做矩阵降维的:
在这里插入图片描述
如图,xxx本身是一个矩阵,通过一个变换WWW变成了一个低维矩阵ccc,因为这一过程是线性的,所以再通过一个WTW^TWT变换就能还原出一个x^\hat{x}x^,现在我们要找到一种变换WWW,使得矩阵xxxx^\hat{x}x^能够尽可能d的一致,这就是PCA做的事情。在PCA中找这个变换WWW用到的方法是SVD(奇异值分解)算法,这是一个纯数学方法,不再细述,因为在VAE中不再需要使用SVD,直接用神经网络代替。

回顾上述介绍,我们会发现PCA与我们想要构造的自编码器的相似之处是在于,如果把矩阵xxx视作输入图像,WWW视作一个编码器,低维矩阵ccc视作图像的编码,然后WTW^TWTx^\hat{x}x^分别视作解码器和生成图像,PCA就变成了一个自编码器网络模型的雏形。
在这里插入图片描述
现在我们需要对这一雏形进行改进。首先一个最明显能改进的地方是用神经网络代替WWW变换和WTW^TWT变换,就得到了如下Deep Auto-Encoder模型:
在这里插入图片描述
这一替换的明显好处是,引入了神经网络强大的拟合能力,使得编码(Code)的维度能够比原始图像(X)的维度低非常多。在一个手写数字图像的生成模型中,Deep Auto-Encoder能够把一个784维的向量(28*28图像)压缩到只有30维,并且解码回的图像具备清楚的辨认度(如下图)。
在这里插入图片描述
至此我们构造出了一个重构图像比较清晰的自编码模型,但是这并没有达到我们真正想要构造的生成模型的标准,因为,对于一个生成模型而言,解码器部分应该是单独能够提取出来的,并且对于在规定维度下任意采样的一个编码,都应该能通过解码器产生一张清晰且真实的图片。

我们先来分析一下现有模型无法达到这一标准的原因。
在这里插入图片描述
如上图所示,假设有两张训练图片,一张是全月图,一张是半月图,经过训练我们的自编码器模型已经能无损地还原这两张图片。接下来,我们在code空间上,两张图片的编码点中间处取一点,然后将这一点交给解码器,我们希望新的生成图片是一张清晰的图片(类似3/4全月的样子)。但是,实际的结果是,生成图片是模糊且无法辨认的乱码图。一个比较合理的解释是,因为编码和解码的过程使用了深度神经网络,这是一个非线性的变换过程,所以在code空间上点与点之间的迁移是非常没有规律的。
如何解决这个问题呢?我们可以引入噪声,使得图片的编码区域得到扩大,从而掩盖掉失真的空白编码点。
在这里插入图片描述
如上图所示,现在在给两张图片编码的时候加上一点噪音,使得每张图片的编码点出现在绿色箭头所示范围内,于是在训练模型的时候,绿色箭头范围内的点都有可能被采样到,这样解码器在训练时会把绿色范围内的点都尽可能还原成和原图相似的图片。然后我们可以关注之前那个失真点,现在它处于全月图和半月图编码的交界上,于是解码器希望它既要尽量相似于全月图,又要尽量相似于半月图,于是它的还原结果就是两种图的折中(3/4全月图)。
由此我们发现,给编码器增添一些噪音,可以有效覆盖失真区域。不过这还并不充分,因为在上图的距离训练区域很远的黄色点处,它依然不会被覆盖到,仍是个失真点。为了解决这个问题,我们可以试图把噪音无限拉长,使得对于每一个样本,它的编码会覆盖整个编码空间,不过我们得保证,在原编码附近编码的概率最高,离原编码点越远,编码概率越低。在这种情况下,图像的编码就由原先离散的编码点变成了一条连续的编码分布曲线,如下图所示。
在这里插入图片描述
那么上述的这种将图像编码由离散变为连续的方法,就是变分自编码的核心思想。下面就会介绍VAE的模型架构,以及解释VAE是如何实现上述构思的。

2、VAE的模型架构

在这里插入图片描述
上面这张图就是VAE的模型架构,我们先粗略地领会一下这个模型的设计思想。

在auto-encoder(AE)中,编码器是直接产生一个编码的,但是在VAE中,为了给编码添加合适的噪音,编码器会输出两个编码,一个是原有编码(m1,m2,m3),另外一个是控制噪音干扰程度的编码(σ1,σ2,σ3),第二个编码其实很好理解,就是为随机噪音码(e1,e2,e3)分配权重,然后加上exp(σi)的目的是为了保证这个分配的权重是个正值,最后将原编码与噪音编码相加,就得到了VAE在code层的输出结果(c1,c2,c3)。其它网络架构都与Deep Auto-encoder无异。

损失函数方面,除了必要的重构损失外,VAE还增添了一个损失函数(见上图Minimize2内容),这同样是必要的部分,因为如果不加的话,整个模型就会出现问题:为了保证生成图片的质量越高,编码器肯定希望噪音对自身生成图片的干扰越小,于是分配给噪音的权重越小,这样只需要将(σ1,σ2,σ3)赋为接近负无穷大的值就好了。所以,第二个损失函数就有限制编码器走这样极端路径的作用,这也从直观上就能看出来,exp(σi)-(1+σi)在σi=0处取得最小值,于是(σ1,σ2,σ3)就会避免被赋值为负无穷大。

上述我们只是粗略地理解了VAE的构造机理,但是还有一些更深的原理需要挖掘,例如第二个损失函数为何选用这样的表达式,以及VAE是否真的能实现我们的预期设想,即“图片能够编码成易于表示的形态,并且这一形态能够尽可能无损地解码回原真实图像”,是否有相应的理论依据。

下面我们会从理论上深入地分析一下VAE的构造依据以及作用原理。

3、VAE的作用原理

我们知道,对于生成模型而言,主流的理论模型可以分为隐马尔可夫模型HMM、朴素贝叶斯模型NB和高斯混合模型GMM,而VAE的理论基础就是高斯混合模型。
什么是高斯混合模型呢?就是说,任何一个数据的分布,都可以看作是若干高斯分布的叠加。
在这里插入图片描述
如图所示,如果P(X)P(X)P(X)代表一种分布的话,存在一种拆分方法能让它表示成图中若干浅蓝色曲线对应的高斯分布的叠加。有意思的是,这种拆分方法已经证明出,当拆分的数量达到512时,其叠加的分布相对于原始分布而言,误差是非常非常小的了。

于是我们可以利用这一理论模型去考虑如何给数据进行编码。一种最直接的思路是,直接用每一组高斯分布的参数作为一个编码值实现编码。
在这里插入图片描述
如上图所示,mmm代表着编码维度上的编号,譬如实现一个512维的编码,mmm的取值范围就是1,2,3……512。mmm会服从于一个概率分布P(m)P(m)P(m)(多项式分布)。现在编码的对应关系是,每采样一个mmm,其对应到一个小的高斯分布N(μm,Σm)N(μ_m ,Σ_m)N(μm,Σm)P(X)P(X)P(X)就可以等价为所有的这些高斯分布的叠加,即:
P(X)=∑mP(m)P(x∣m) P(X)=\sum_m P(m)P(x|m) P(X)=mP(m)P(xm)
其中,m∼P(m),x∣m∼N(μm,Σm)m\sim P(m),x|m \sim N(μ^m ,Σ^m)mP(m)xmN(μm,Σm)

上述的这种编码方式是非常简单粗暴的,它对应的是我们之前提到的离散的、有大量失真区域的编码方式。于是我们需要对目前的编码方式进行改进,使得它成为连续有效的编码。
在这里插入图片描述
现在我们的编码换成一个连续变量zzz,我们规定zzz服从正态分布N(0,1)N(0,1)N(0,1)(实际上并不一定要选用N(0,1)N(0,1)N(0,1),其他的连续分布都是可行的)。每对于一个采样zzz,会有两个函数μμμσσσ,分别决定zzz对应到的高斯分布的均值和方差,然后在积分域上所有的高斯分布的累加就成为了原始分布P(X)P(X)P(X),即:
P(x)=∫zP(z)P(x∣z)dz P(x)=\int_z P(z)P(x|z)dz P(x)=zP(z)P(xz)dz
其中z∼N(0,1)z\sim N(0,1)zN(0,1)x∣z∼N(μ(z),σ(z))x|z\sim N(μ(z),σ(z))xzN(μ(z),σ(z))

接下来就可以求解这个式子。由于P(z)P(z)P(z)是已知的,P(x∣z)P(x|z)P(xz)未知,而x∣z∼N(μ(z),σ(z))x|z\sim N(μ(z),σ(z))xzN(μ(z),σ(z)),于是我们真正需要求解的,是μμμσσσ两个函数的表达式。又因为P(x)P(x)P(x)通常非常复杂,导致μμμσσσ难以计算,我们需要引入两个神经网络来帮助我们求解。

第一个神经网络叫做Decoder,它求解的是μμμσσσ两个函数,这等价于求解P(x∣z)P(x|z)P(xz),因为x∣z∼N(μ(z),σ(z))x|z\sim N(μ(z),σ(z))xzN(μ(z),σ(z))
在这里插入图片描述
第二个神经网络叫做Encoder,它求解的结果是q(z∣x)q(z|x)q(zx)qqq可以代表任何分布。
在这里插入图片描述
值得注意的是,这引入第二个神经网路Encoder的目的是,辅助第一个Decoder求解P(x∣z)P(x|z)P(xz),这也是整个VAE理论中最精妙的部分,下面详细地解释其中的奥妙。

回到最开始要求解的目标式:
P(x)=∫zP(z)P(x∣z)dz P(x)=\int_z P(z)P(x|z)dz P(x)=zP(z)P(xz)dz

我们希望P(x)P(x)P(x)越大越好,这等价于求解:
MaxL=∑xlogP(x) Max L=\sum_x logP(x) MaxL=xlogP(x)

注意到(这里我们引入一个分布q(z∣x)q(z|x)q(zx),因为p(x∣z)p(x|z)p(xz)是求不出来的,q(z∣x)q(z|x)q(zx)可以是任何分布):
logP(x)=logP(x)∗∫zq(z∣x)dz=∫zq(z∣x)logP(x)dz=∫zq(z∣x)log(P(z,x)P(z∣x))dz=∫zq(z∣x)log(P(z,x)q(z∣x)P(z∣x)q(z∣x))dz=∫zq(z∣x)log(P(z,x)q(z∣x))dz+∫zq(z∣x)log(q(z∣x)P(z∣x))=∫zq(z∣x)log(P(z,x)q(z∣x))dz+KL(q(z∣x)∣∣P(z∣x)) logP(x) = logP(x)*\int_z q(z|x)dz\\=\int_z q(z|x)logP(x)dz\\=\int_z q(z|x)log(\frac{P(z,x)}{P(z|x)})dz\\=\int_z q(z|x)log(\frac{P(z,x)q(z|x)}{P(z|x)q(z|x)})dz\\=\int_z q(z|x)log(\frac{P(z,x)}{q(z|x)})dz+\int_z q(z|x)log(\frac{q(z|x)}{P(z|x)})\\=\int_z q(z|x)log(\frac{P(z,x)}{q(z|x)})dz+KL(q(z|x)||P(z|x)) logP(x)=logP(x)zq(zx)dz=zq(zx)logP(x)dz=zq(zx)log(P(zx)P(z,x))dz=zq(zx)log(P(zx)q(zx)P(z,x)q(zx))dz=zq(zx)log(q(zx)P(z,x))dz+zq(zx)log(P(zx)q(zx))=zq(zx)log(q(zx)P(z,x))dz+KL(q(zx)∣∣P(zx))

上式的第二项是KL散度,一个大于等于0的值,于是我们就找到了一个logP(x)的下界:
logP(x)>=∫zq(z∣x)log(P(z,x)q(z∣x))dz=∫zq(z∣x)log(P(x∣z)P(z)q(z∣x))dz logP(x)>=\int_z q(z|x)log(\frac{P(z,x)}{q(z|x)})dz=\int_z q(z|x)log(\frac{P(x|z)P(z)}{q(z|x)})dz logP(x)>=zq(zx)log(q(zx)P(z,x))dz=zq(zx)log(q(zx)P(xz)P(z))dz

我们把这个下界记作:
Lb=∫zq(z∣x)log(P(x∣z)P(z)q(z∣x))dz L_b = \int_z q(z|x)log(\frac{P(x|z)P(z)}{q(z|x)})dz Lb=zq(zx)log(q(zx)P(xz)P(z))dz

于是原式化为:
logP(x)=Lb+KL(q(z∣x)∣∣P(z∣x)) logP(x)=L_b+KL(q(z|x)||P(z|x)) logP(x)=Lb+KL(q(zx)∣∣P(zx))

接下来,VAE思维的巧妙设计就体现出来了。原本,我们需要求P(x∣z)P(x|z)P(xz)使得 logP(x)logP(x)logP(x)最大,现在引入了一个q(z∣x)q(z|x)q(zx),变成了同时求P(x∣z)P(x|z)P(xz)q(z∣x)q(z|x)q(zx)使得 logP(x)logP(x)logP(x)最大。不妨观察一下logP(x)logP(x)logP(x)LbL_bLb的关系:
在这里插入图片描述
一个有趣的现象是,当我们固定住P(x∣z)P(x|z)P(xz)时,因为logP(x)logP(x)logP(x)只与P(x∣z)P(x|z)P(xz)有关,所以logP(x)logP(x)logP(x)的值是会不变的,此时我们去调节q(z∣x)q(z|x)q(zx),使得LbL_bLb越来越高,同时KLKLKL散度越来越小,当我们调节到q(z∣x)q(z|x)q(zx)P(z∣x)P(z|x)P(zx)完全一致时,KLKLKL散度就消失为0,LbL_bLblogP(x)logP(x)logP(x)完全一致。
由此可以得出,不论logP(x)logP(x)logP(x)的值如何,我们总能够通过调节使得LbL_bLb等于logP(x)logP(x)logP(x),又因为LbL_bLblogP(x)logP(x)logP(x)的下界,所以求解Max logP(x)Max\ logP(x)Max logP(x)等价为求解Max LbMax\ L_bMax Lb

这个现象从宏观上来看也是很有意思,调节P(x∣z)P(x|z)P(xz)就是在调节Decoder,调节q(z∣x)q(z|x)q(zx)就是在调节Encoder。于是,VAE的训练逻辑就变成了,Decoder每前进一步,Encoder就调节成与其一致的样子,并且站在那拿“枪”顶住Decoder,这样Decoder在下次训练的时候就只能前进,不能退步了。

上述便是VAE的巧妙设计之处。再回到我们之前的步骤上,现在需求解Max LbMax\ L_bMax Lb

注意到:
Lb=∫zq(z∣x)log(P(z,x)q(z∣x))dz=∫zq(z∣x)log(P(x∣z)P(z)q(z∣x))dz=∫zq(z∣x)log(P(z)q(z∣x))dz+∫zq(z∣x)log(P(x∣z))dz=−KL(q(z∣x)∣∣P(z))+∫zq(z∣x)log(P(x∣z))dz L_b=\int_z q(z|x)log(\frac{P(z,x)}{q(z|x)})dz\\=\int_z q(z|x)log(\frac{P(x|z)P(z)}{q(z|x)})dz\\=\int_z q(z|x)log(\frac{P(z)}{q(z|x)})dz+\int_z q(z|x)log(P(x|z))dz\\=-KL(q(z|x)||P(z))+\int_z q(z|x)log(P(x|z))dz Lb=zq(zx)log(q(zx)P(z,x))dz=zq(zx)log(q(zx)P(xz)P(z))dz=zq(zx)log(q(zx)P(z))dz+zq(zx)log(P(xz))dz=KL(q(zx)∣∣P(z))+zq(zx)log(P(xz))dz

所以,求解Max LbMax\ L_bMax Lb,等价于求解KL(q(z∣x)∣∣P(z))KL(q(z|x)||P(z))KL(q(zx)∣∣P(z))的最小值和∫zq(z∣x)logP(x∣z)dz\int_z q(z|x)logP(x|z) dzzq(zx)logP(xz)dz的最大值。

我们先来求第一项,其实−KL(q(z∣x)∣∣P(z))-KL(q(z|x)||P(z))KL(q(zx)∣∣P(z))的展开式刚好等于(其中σi\sigma_iσi等同于下面的rir_irimim_imi对应下面的μi\mu_iμi):
∑i=1J(exp(σi)−(1+σi)+(mi)2) \sum_{i=1}^J(exp(\sigma_i)-(1+\sigma_i)+(m_i)^2) i=1J(exp(σi)(1+σi)+(mi)2)


具体的展开计算过程可以参阅《Auto-Encoding Variational Bayes》的Appendix B。下面给出简单证明:
假设:
先验P(z)=N(0,I)P(z)=N(0,I)P(z)=N(0,I)(标准正态分布);
后验q(z∣x)=N(μi,σi2)q(z|x)=N(\mu_i,\sigma_i^2)q(zx)=N(μi,σi2)

标准KLKLKL散度公式:
对于两个一位高斯分布q=N(μ1,σ12),p=N(μ2,σ22)q=N(\mu_1,\sigma_1^2),p=N(\mu_2, \sigma_2^2)q=N(μ1,σ12),p=N(μ2,σ22),有
KL(q∣∣p)=log(σ2σ1)+σ12+(μ1−μ2)22σ22−12 KL(q||p)=log(\frac{\sigma_2}{\sigma_1})+\frac{\sigma_1^2 + (\mu_1-\mu_2)^2}{2\sigma_2^2}-\frac{1}{2} KL(q∣∣p)=log(σ1σ2)+2σ22σ12+(μ1μ2)221
p=N(0,1)p=N(0,1)p=N(0,1)时,上式:
KL(q∣∣p)=−log(σ1)+σ12+μ122−12 KL(q||p)=-log(\sigma_1)+\frac{\sigma_1^2 + \mu_1^2}{2}-\frac{1}{2} KL(q∣∣p)=log(σ1)+2σ12+μ1221
即:
KL=12(σ12+μ12−1−logσ12) KL=\frac{1}{2}(\sigma_1^2 +\mu_1^2 -1 -log\sigma_1^2) KL=21(σ12+μ121logσ12)
论文中编码器输出均值μ\muμ和对数方差logσ2(记为r)log\sigma^2(记为r)logσ2(记为r):
ri=logσi2σi2=eri r_i = log\sigma_i^2 \\\sigma_i^2=e^{r_i} ri=logσi2σi2=eri
带入KL散度公式:
KL=12(eri+μ12−1−ri) KL=\frac{1}{2}(e^{r_i} +\mu_1^2 -1 - r_i) KL=21(eri+μ121ri)


于是,第一项式子就是VAE模型架构中第二个损失函数的由来。

接下来求第二项,注意到:
随机变量zzz服从分布q(z∣x)q(z|x)q(zx),期望的定义就是:
Eq(z∣x)[f(z)]=∫zq(z∣x)f(z)dz E_{q(z|x)}[f(z)]=\int_z q(z|x)f(z)dz Eq(zx)[f(z)]=zq(zx)f(z)dz
f(z)=logP(x∣z)f(z)=logP(x|z)f(z)=logP(xz),则:
Max ∫zq(z∣x)log(P(x∣z))dz=Max Eq(z∣x)[logP(x∣z)] Max\ \int_z q(z|x)log(P(x|z))dz\\=Max\ E_{q(z|x)}[logP(x|z)] Max zq(zx)log(P(xz))dz=Max Eq(zx)[logP(xz)]

上述的这个期望,也就是表明在给定q(z∣x)q(z|x)q(zx)(编码器输出)的情况下P(x∣z)P(x|z)P(xz)(解码器输出)的值尽可能高,这其实就是一个类似于Auto-Encoder的损失函数(方差忽略不计的话):
在这里插入图片描述
因此,第二项式子就是第二节VAE模型架构中第一个损失函数的由来。

综上,关于VAE模型架构中的理论证明部分至此全部介绍完毕。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐