变分自编码器介绍、推导及实现
0. 预备知识
0.1 信息量
在信息理论中,我们用以下式子来量化一个事件
的信息量
:
当
底数为 e 时,信息量的单位为 nat(奈特),当
底数为 2 时,信息量的单位为 bit(比特)。
0.2 信息熵(Entropy)
此外,如果用以下两个式子分别来表示随机变量
在离散和连续情况下的信息熵
:
信息熵可以看做是对信息量的期望。
0.3 K-L 散度(Kullback-Leibler divergence)
K-L 散度又被称为相对熵(relative entropy),是对两个概率分布间差异的非对称性度量。
假设
是随机变量 上的两个概率分布,则在离散和连续随机变量的情形下,相对熵的定义分别为:
注意!K-L 散度不是对称的,它不是描述两个分布之间的距离,因为按照上述定义,
0.4 贝叶斯公式(Bayes Rule)
这个就不多讲了,为了和下述的 notation 保持一致,公式表述如下
1. 什么是变分自编码器
变分自编码器的英文是 (variational auto-encoder,VAE),其实在将 VAE 之前,我们必须提一下自编码器(auto-encoder,AE)。
在 AE 的结构中包含一个编码器(encoder)和解码器(decoder),其中 encoder 的作用是将我们的数据空间
映射到另一个隐变量(latent variable)空间
上去,具体来说,我们的一个输入数据样本
将被被编码成一个 vector,这个 vector 中的每一维度就是一些该样本的属性;而 decoder 要干的事则刚好与 encoder 相反,它可以接受一个 latent vector,并且重新变回到原样本空间上去。至于具体怎么转化,这个很复杂,我们也不知道它中间到底是怎么变换的,怎么办呢?神经网络来帮忙,神经网络理论上就是可以拟合任何一个函数的,不管你有多复杂。
(图片来源网络,侵删)
如上图所示,举例类比我们人写数字的行为来说,我现在让你写一个 4,在你听到这句话之后且开始动笔之前,你会在大脑里想,哦,你让我写 4,4 应该先这样弯一下,而且最后有一竖,笔画应该写长点... 类似这种,whatever,这些你思考的属性就是 latent variable,也即 encode。然后,你的大脑再根据你所想的这些属性指导你去把这个 4 写出来,即 decode。至于大脑怎么指导这些空间变换的,谁知道呢!
说了这么多,终于可以开始将 VAE 了,它和 AE 的不同点就在于,AE 中间输出的是隐变量的具体取值,而 VAE 中间要输出的是隐变量的具体分布情况,这样一来,我们就可以从这个分布中另外取样,送入到 decoder,就可以生成类似输入样本
的其他样本
了,并且这两个会十分近似。 That is to say, the encoder in VAE will output the probability distribution of each latent attribution rather than telling us a single value to describe each latent state.
再举个例子,这个示例来源于 [1] Variational autoencoders, Jenemy Jordan,如果我们有个人脸的数据集,在 AE 中,我们希望它完成下图的工作:
(图片创作于 Jenemy Jordan,侵删)
即对每一个属性,给出一个确切的取值。比如上面的 smile 属性,现在取值是 0.99,那模型为什么输出一个 0.99 呢?为啥不是 0.98,0.97 等等呢?是的,这就是 VAE 干的事情,VAE 希望学习到关于该 smile 属性的概率分布,当然,该概率分布函数 y 取值最大时对应的 x 就是这里的 0.99,也即 AE 给出该属性的那个确切值,如下图所示:
(图片创作于 Jenemy Jordan,侵删)
好,那现在我知道当前这个人笑的灿烂程度是 0.99,并且长胡须的程度是 0.85,假如我现在想知道长胡须程度是 0.65 的人笑的灿烂程度是 0.89 的人脸会是怎样的样子怎么办呢?那就取样呗,反正 VAE 学习到了各个属性的分布,然后再送入 decoder 变换回来,就类型下图所示:
(图片创作于 Jenemy Jordan,侵删)
于是,VAE 的总体架构如下图所示:
好了,终于说完了 VAE 是在做什么,接下来我将完成数学理论推导,请务必理解推导过程,别担心,那很简单!
2. 数学理论推导
现在我们假设知道的确有这样的 latent variables,但是我们不知道它到底是一个怎样的分布,现在能够观测到的就是样本
,我们希望在给定
的条件下去推出
的分布,即
.
根据贝叶斯定理,可得:
然而,这个后验概率
是不可解的,因为无法计算
,根据全概率公式可知:
如果 z 是一个维度很高的变量,你想想是不是有无穷多重的积分,会变成大概这样的计算式子:
于是这里大致有两种方法求解: - ① 蒙特卡罗算法(Mote Carlo method),不断取样 z,取样越多 p(x) 越接近真实的分布。 - ② Variational Inference,既然
不可解,那我就尝试用一个可解的分布
去近似
,即 approximation 的方式。
注意一下,你可能会在其他资料中看到这里的表述是
而不是
,其实这里无关紧要,只取决于你如何解释它,因为当前的
是已经给出了的嘛, 请务必记住这点, 我个人还是习惯于写成
的形式!好的,故事从这里开始。
我们想让
去近似
,所以肯定希望这两个分布间的差异越小越好,K-L 散度就可以派上用场, 我们希望
而根据 K-L 散度的定义,可知:
暂停一下,回顾一下我们是要干嘛,最小化上面这一大串,
是已经给定的,所以虽然我不知道
是多少,但它的确肯定是个定值,于是最小化
等价于最小化最后两项,我们记作为
:
再次暂停,现在是要最小化
, 也等价于最大化
, 即最大化
这是啥?第一项就是说不断在 z 上采样,然后使得被重构的样本中重构
的几率最大;第二项就是说使得我们假设的后验证分布
和先验分布
尽量接近,这个式子也就差不多指引我们去构造一个 auto-encoder,所以这也是为什么这个模型叫 VAE 吧。
再深入研究一下
式:
第一项实际上是一个重建 error,为什么?好,我们说从
到
的转换是神经网络干的事情,它是一个函数,虽然说我们不知道它具体的表达式是什么,无论我输入一个怎样的 input,总是会给我一个相应的 output,所以
式的第一项中的
可以看作是
,假设 p 是一个正态分布,你自己想想会是什么!
loss!当然,如果你假设 p 是伯努利分布,那就是交叉熵了。
第二项,我们说是为了让我们假设的后验证分布
和先验分布
尽量接近,论文中假设 p(z) 是一个标准高斯分布,为什么这么假设呢?
The key is to notice that any distribution in d dimensions can be generated by taking a set of d variables that are normally distributed and mapping them through a sufficiently complicated function.
所以,在 decoder 部分,你可以看做神经网络的前几层是将一个关于 z 的正态分布映射到其他对应的 latent value 上去,也就好似传统 AE 中的 code vector 中一个个的 single value。
If f (z; q) is a multi-layer neural network, then we can imagine the network using its first few layers to map the normally distributed z’s to the latent values (like digit identity, stroke weight, angle, etc.) with exactly the right statitics. Then it can use later layers to map those latent values to a fully rendered digit.
为了好算,我们假设
也是高斯分布,然后就可以用一个闭式直接计算了。
3. 实现
在论文中,有提到一个 reparameterization trick, 主要是处理反向传播时的求导问题,这个就不细说了,最后参考文献中很多资料中都有提到。
下面用 Pytorch 在 MNIST 数据集上实现一下 VAE,代码已经上传到我的 Github,代码中很大部分都参考了网上的一些实现。
LiUzHiAn/VAE-Pytorchgithub.com
下面是一些图片重建和随机生成的结果,我只训练了 30 轮:
- 重建结果(依次为 10,20,30 轮的结果)
epoch-10
epoch-20
epoch-30
- 生成结果(依次为 10,20,30 轮的结果)
epoch-10
epoch-20
epoch-30
4. References
- 博客:
[1] Jenemy Jordan: Variational autoencoders
[2] Irhum Shafkat: Intuitively Understanding Variational Autoencoders
[3] 花式解释 AutoEncoder 与 VAE
[4] 张俊: 变分自编码器 VAE:原来是这么一回事
[5] Tensorflow: Convolutional Variational Autoencoder
- 视频及幻灯片:
[6] Ali Ghodsi: Deep Learning, Variational Autoencoder (Oct 12 2017)
[7] Stanford CS231n: Lecture on Variational Autoencoders
[8] Sherlock: Raymond Yeh, Junting Lou, Teck-Yian Lim: CS598LAZ - Variational Autoencoders
- 论文:
[9] Diederik P Kingma, Max Welling: Auto-Encoding Variational Bayes
[10] CARL DOERSCH, Tutorial on Variational Autoencoders, Carnegie Mellon / UC Berkeley, August 16, 2016 说在前面的话