变分自编码器(Variational Auto-Encoder,VAE),原论文《Auto-Encoding Variational Bayes》
目标:希望构建一个从隐变量Z
生成目标数据X
的模型,假设了Z
服从某些常见的分布(比如正态分布或均匀分布),然后希望训练一个模型X=g(Z)
,这个模型能够将原来的概率分布映射到训练集的概率分布,也就是说,目的是进行分布之间的变换。
那现在假设Z
服从标准的正态分布,那么我就可以从中采样得到若干个 Z 1 Z_1 Z1, Z 2 Z_2 Z2,…, Z n Z_n Zn,然后对它做变换得到 X 1 宝盖 = g ( Z 1 ) X_1宝盖=g(Z_1) X1宝盖=g(Z1), X 2 宝盖 = g ( Z 2 ) X_2宝盖=g(Z_2) X2宝盖=g(Z2),…, X n 宝盖 = g ( Z n ) X_n宝盖=g(Z_n) Xn宝盖=g(Zn),我们怎么判断这个通过g
构造出来的数据集,它的分布跟我们目标的数据集分布是不是一样的呢?有读者说不是有KL散度吗?当然不行,因为KL散度是根据两个概率分布的表达式来算它们的相似度的,然而目前我们并不知道它们的概率分布的表达式,我们只有一批从构造的分布采样而来的数据{ X 1 宝盖 X_1宝盖 X1宝盖, X 2 宝盖 X_2宝盖 X2宝盖,…, X n 宝盖 X_n宝盖 Xn宝盖},还有一批从真实的分布采样而来的数据{ X 1 X_1 X1, X 2 X_2 X2,…, X n X_n Xn}(也就是我们希望生成的训练集)。我们只有样本本身,没有分布表达式,当然也就没有方法算KL散度。
首先我们有一批数据样本{ X 1 X_1 X1, X 2 X_2 X2,…, X n X_n Xn},其整体用X来描述,我们本想根据{ X 1 X_1 X1, X 2 X_2 X2,…, X n X_n Xn}得到 X X X的分布 p ( X ) p(X) p(X),如果能得到的话,那我直接根据 p ( X ) p(X) p(X)来采样,就可以得到所有可能的 X X X了(包括{ X 1 X_1 X1, X 2 X_2 X2,…, X n X_n Xn}以外的),这是一个终极理想的生成模型了。当然,这个理想很难实现,于是我们将分布改一改
这里我们就不区分求和还是求积分了,意思对了就行。此时 p ( X ∣ Z ) p(X|Z) p(X∣Z)就描述了一个由 Z Z Z来生成 X X X的模型,而我们假设 Z Z Z服从标准正态分布,也就是 p ( Z ) = N ( 0 , I ) p(Z)=N(0,I) p(Z)=N(0,I)。如果这个理想能实现,那么我们就可以先从标准正态分布中采样一个 Z Z Z,然后根据 Z Z Z来算一个 X X X,也是一个很棒的生成模型。接下来就是结合自编码器来实现重构,保证有效信息没有丢失,再加上一系列的推导,最后把模型实现。框架的示意图如下:
其实,在整个VAE模型中,我们并没有去使用 p ( Z ) p(Z) p(Z)(隐变量空间的分布)是正态分布的假设,我们用的是假设 p ( Z ∣ X ) p(Z|X) p(Z∣X)(后验分布)是正态分布!!
回到本文,这时候每一个 X k X_k Xk都配上了一个专属的正态分布,才方便后面的生成器做还原。但这样有多少个 X X X就有多少个正态分布了。我们知道正态分布有两组参数:均值 μ μ μ和方差 σ 2 σ^2 σ2(多元的话,它们都是向量),那怎么找出专属于 X k X_k Xk的正态分布 p ( Z ∣ X k ) p(Z|X_k) p(Z∣Xk)的均值和方差呢?好像并没有什么直接的思路。那好吧,那我就用神经网络来拟合出来吧!这就是神经网络时代的哲学:难算的我们都用神经网络来拟合。
于是我们构建两个神经网络 μ k = f 1 ( X k ) , l o g σ k 2 = f 2 ( X k ) μ_k=f_1(X_k),logσ_k^2=f_2(X_k) μk=f1(Xk),logσk2=f2(Xk)来算它们了。我们选择拟合 l o g σ k 2 logσ_k^2 logσk2而不是直接拟合 σ k 2 σ_k^2 σk2,是因为 σ k 2 σ_k^2 σk2总是非负的,需要加激活函数处理,而拟合 l o g σ k 2 logσ_k^2 logσk2不需要加激活函数,因为它可正可负。到这里,我能知道专属于 X k X_k Xk的均值和方差了,也就知道它的正态分布长什么样了,然后从这个专属分布中采样一个 Z k Z_k Zk出来,然后经过一个生成器得到 X k 宝盖 = g ( Z k ) X_k宝盖=g(Z_k) Xk宝盖=g(Zk),现在我们可以放心地最小化 D ( X k 宝盖 , X k ) 2 D(X_k宝盖,X_k)^2 D(Xk宝盖,Xk)2,因为 Z k Z_k Zk是从专属 X k X_k Xk的分布中采样出来的,这个生成器应该要把开始的 X k X_k Xk还原回来。于是可以画出VAE的示意图:
让我们来思考一下,根据上图的训练过程,最终会得到什么结果。
首先,我们希望重构 X X X,也就是最小化 D ( X k 宝盖 , X k ) 2 D(X_k宝盖,X_k)^2 D(Xk宝盖,Xk)2,但是这个重构过程受到噪声的影响,因为 Z k Z_k Zk是通过重新采样过的,不是直接由encoder算出来的。显然噪声会增加重构的难度,不过好在这个噪声强度(也就是方差)通过一个神经网络算出来的,所以最终模型为了重构得更好,肯定会想尽办法让方差为0。而方差为0的话,也就没有随机性了,所以不管怎么采样其实都只是得到确定的结果(也就是均值),只拟合一个当然比拟合多个要容易,而均值是通过另外一个神经网络算出来的。
说白了,模型会慢慢退化成普通的AutoEncoder,噪声不再起作用。
这样不就白费力气了吗?说好的生成模型呢?
别急别急,其实VAE还让所有的 p ( Z ∣ X ) p(Z|X) p(Z∣X)都向标准正态分布看齐,这样就防止了噪声为零,同时保证了模型具有生成能力。怎么理解“保证了生成能力”呢?如果所有的 p ( Z ∣ X ) p(Z|X) p(Z∣X)都很接近标准正态分布 N ( 0 , I ) N(0,I) N(0,I),那么根据定义
这样我们就能达到我们的先验假设: p ( Z ) p(Z) p(Z)是标准正态分布。然后我们就可以放心地从 N ( 0 , I ) N(0,I) N(0,I)中采样来生成图像了。
那怎么让所有的 p ( Z ∣ X ) p(Z|X) p(Z∣X)都向 N ( 0 , I ) N(0,I) N(0,I)看齐呢?如果没有外部知识的话,其实最直接的方法应该是在重构误差的基础上中加入额外的loss:
因为它们分别代表了均值 μ k μ_k μk和方差的对数 l o g σ k 2 logσ_k^2 logσk2,达到 N ( 0 , I ) N(0,I) N(0,I)就是希望二者尽量接近于0了。不过,这又会面临着这两个损失的比例要怎么选取的问题,选取得不好,生成的图像会比较模糊。所以,原论文直接算了一般(各分量独立的)正态分布与标准正态分布的KL散度 K L ( N ( μ , σ 2 ) ∥ N ( 0 , I ) ) KL(N(μ,σ2)∥N(0,I)) KL(N(μ,σ2)∥N(0,I))作为这个额外的loss,计算结果为
VAE的本质是什么?VAE虽然也称是AE(AutoEncoder)的一种,但它的做法(或者说它对网络的诠释)是别具一格的。在VAE中,它的Encoder有两个,一个用来计算均值,一个用来计算方差,这已经让人意外了:Encoder不是用来Encode的,是用来算均值和方差的,这真是大新闻了,还有均值和方差不都是统计量吗,怎么是用神经网络来算的?
事实上,我觉得VAE从让普通人望而生畏的变分和贝叶斯理论出发,最后落地到一个具体的模型中,虽然走了比较长的一段路,但最终的模型其实是很接地气的:它本质上就是在我们常规的自编码器的基础上,对encoder的结果(在VAE中对应着计算均值的网络)加上了“高斯噪声”,使得结果decoder能够对噪声有鲁棒性;而那个额外的KL loss(目的是让均值为0,方差为1),事实上就是相当于对encoder的一个正则项,希望encoder出来的东西均有零均值。
那另外一个encoder(对应着计算方差的网络)的作用呢?它是用来动态调节噪声的强度的。直觉上来想,当decoder还没有训练好时(重构误差远大于KL loss),就会适当降低噪声(KL loss增加),使得拟合起来容易一些(重构误差开始下降);反之,如果decoder训练得还不错时(重构误差小于KL loss),这时候噪声就会增加(KL loss减少),使得拟合更加困难了(重构误差又开始增加),这时候decoder就要想办法提高它的生成能力了。
说白了,重构的过程是希望没噪声的,而KL loss则希望有高斯噪声的,两者是对立的。所以,VAE跟GAN一样,内部其实是包含了一个对抗的过程,只不过它们两者是混合起来,共同进化的。从这个角度看,VAE的思想似乎还高明一些,因为在GAN中,造假者在进化时,鉴别者是安然不动的,反之亦然。当然,这只是一个侧面,不能说明VAE就比GAN好。GAN真正高明的地方是:它连度量都直接训练出来了,而且这个度量往往比我们人工想的要好(然而GAN本身也有各种问题,这就不展开了)。
从这个讨论中,我们也可以看出,当然,每个 p ( Z ∣ X ) p(Z|X) p(Z∣X)是不可能完全精确等于标准正态分布,否则 p ( Z ∣ X ) p(Z|X) p(Z∣X)就相当于跟 X X X无关了,重构效果将会极差。最终的结果就会是, p ( Z ∣ X ) p(Z|X) p(Z∣X)保留了一定的 X X X信息,重构效果也还可以,并且 ( 2 ) (2) (2)近似成立,所以同时保留着生成能力。
最后,因为目前的VAE是无监督训练的,因此很自然想到:如果有标签数据,那么能不能把标签信息加进去辅助生成样本呢?这个问题的意图,往往是希望能够实现控制某个变量来实现生成某一类图像。当然,这是肯定可以的,我们把这种情况叫做Conditional VAE,或者叫CVAE。(相应地,在GAN中我们也有个CGAN。)
但是,CVAE不是一个特定的模型,而是一类模型,总之就是把标签信息融入到VAE中的方式有很多,目的也不一样。这里基于前面的讨论,给出一种非常简单的VAE。
在前面的讨论中,我们希望 X X X经过编码后, Z Z Z的分布都具有零均值和单位方差,这个“希望”是通过加入了KL loss来实现的。如果现在多了类别信息 Y Y Y,我们可以希望同一个类的样本都有一个专属的均值 μ Y μ^Y μY(方差不变,还是单位方差),这个 μ Y μ^Y μY让模型自己训练出来。这样的话,有多少个类就有多少个正态分布,而在生成的时候,我们就可以通过控制均值来控制生成图像的类别。事实上,这样可能也是在VAE的基础上加入最少的代码来实现CVAE的方案了,因为这个“新希望”也只需通过修改KL loss实现:
从贝叶斯观点出发
已知概率密度函数 p ( x ) p(x) p(x),那么 x x x的期望也就定义为:
如果要对它进行数值计算,也就是数值积分,那么可以选若干个有代表性的点 x 0 < x 1 < x 2 < ⋯ < x n x_0
这里不讨论“有代表性”是什么意思,也不讨论提高数值计算精度的方法。这样写出来,是为了跟采样计算对比。如果从 p ( x ) p(x) p(x)中采样若干个点 x 1 , x 2 , … , x n x_1,x_2,…,x_n x1,x2,…,xn,那么我们有:
我们可以比较 ( 2 ) (2) (2)跟 ( 3 ) (3) (3),它们的主要区别是 ( 2 ) (2) (2)中包含了概率的计算而 ( 3 ) (3) (3)中仅有 x x x的计算,这是因为在 ( 3 ) (3) (3)中 x i x_i xi是从 p ( x ) p(x) p(x)中依概率采样出来的,概率大的 x i x_i xi出现的次数也多,所以可以说采样的结果已经包含了 p ( x ) p(x) p(x)在里边,就不用再乘以 p ( x i ) p(x_i) p(xi)了。
这里通过直接对联合分布进行近似的方式,简明快捷地给出了VAE的理论框架。
出发点依然没变,这里再重述一下。首先我们有一批数据样本 x 1 , … , x n {x1,…,xn} x1,…,xn,其整体用 x x x来描述,我们希望借助隐变量 z z z描述 x x x的分布 p ( x ) 波浪线 p(x)波浪线 p(x)波浪线:
回顾一下前面关于VAE的一些原理。
在这部分内容中,我们试图对VAE的原理做细致的追问,以求能回答VAE为什么这样做,最关键的问题是,为什么这样做就可行。
这就得再分析一下我们对 q ( x ∣ z ) q(x|z) q(x∣z)的想法了,我们称 q ( x ∣ z ) q(x|z) q(x∣z)为生成模型部分,一般情况下我们假设它为伯努利分布或高斯分布,考虑到伯努利分布应用场景有限,这里只假设它是正态分布,那么:
其中 μ ( z ) μ(z) μ(z)是用来计算均值的网络, σ 2 ( z ) σ^2(z) σ2(z)是用来计算方差的网络,很多时候我们会固定方差,那就只剩一个计算均值的网络了。
注意, q ( x ∣ z ) q(x|z) q(x∣z)只是一个概率分布,我们从 q ( z ) q(z) q(z)中采样出 z z z后,代入 q ( x ∣ z ) q(x|z) q(x∣z)后得到 q ( x ∣ z ) q(x|z) q(x∣z)的具体形式,理论上我们还要从 q ( x ∣ z ) q(x|z) q(x∣z)中再采样一次才得到 x x x。但是,我们并没有这样做,我们直接把均值网络 μ ( z ) μ(z) μ(z)的结果就当成 x x x。而能这样做,表明 q ( x ∣ z ) q(x|z) q(x∣z)是一个方差很小的正态分布(如果是固定方差的话,则训练前需要调低方差,如果不是正态分布而是伯努利分布的话,则不需要考虑这个问题,它只有一组参数),每次采样的结果几乎都是相同的(都是均值 μ ( z ) μ(z) μ(z)),此时 x x x和 z z z之间“几乎”具有一一对应关系,接近确定的函数 x = μ ( z ) x=μ(z) x=μ(z)。
感谢大佬们的总结!
【来源】苏剑林. (Mar. 26, 2019). 《科学空间浏览指南(FAQ) 》[Blog post]. Retrieved from https://spaces.ac.cn/archives/6508
【参考】https://spaces.ac.cn/archives/5253
【参考】https://spaces.ac.cn/archives/5343
【参考】https://spaces.ac.cn/archives/5383
【参考】https://blog.csdn.net/mch2869253130/article/details/102885243
【参考】https://blog.csdn.net/mch2869253130/article/details/106725342