变分自编码器(Variational Autoencoder, VAE)通俗教程

原文地址:http://www.dengfanxin.cn/?p=334git

1. 神秘变量与数据集

如今有一个数据集DX(dataset, 也能够叫datapoints),每一个数据也称为数据点。
咱们假定这个样本受某种神秘力量操控,可是咱们也无从知道这些神秘力量是什么?那么咱们假定这股神秘力量有n个,起名字叫power1,power2,,powern 吧,他们的大小分别是z1,z2,,zn ,称之为神秘变量表示成一个向量就是github

z=⎛⎝⎜⎜⎜⎜z1z2zn⎞⎠⎟⎟⎟⎟网络

z也起个名字叫神秘组合架构

一言以蔽之:神秘变量表明了神秘力量神秘组合关系。
用正经的话说就是:隐变量(latent variable)表明了隐因子(latent factor)的组合关系。函数

这里咱们澄清一下隶属空间,假设数据集DX是m个点,这m个点也应该隶属于一个空间,好比一维的状况,假如每一个点是一个实数,那么他的隶属空间就是实数集,因此咱们这里定义一个DX每一个点都属于的空间称为XS,咱们在后面提到的时候,你就再也不感到陌生了。学习

神秘变量z能够确定他们也有一个归属空间称为ZS。优化

下面咱们就要形式化地构造X与Z的神秘关系了,这个关系就是咱们前面说的神秘力量,直观上咱们已经很是清楚,假设咱们的数据集就是彻底由这n个神秘变量全权操控的,那么对于X中每个点都应该有一个n个神秘变量的神秘组合zj 来神秘决定。编码

接下来咱们要将这个关系再简化一下,咱们假设这n个神秘变量不是可以操控X的所有,还有一些其余的神秘力量,咱们暂时不考虑,那么就能够用几率来弥补这个缺失,为何呢?举个例子,假设咱们制造了一个机器能够向一个固定的目标发射子弹,咱们精确的计算好了打击的力量和角度,但因为某些难以控制的因素,好比空气的流动,地球的转动致使命中的目标没法达到精准的目的,而这些因素可能十分巨大和繁多,可是他们并非造成DX的主因素,根据大数定理,这些全部因素产生的影响能够用高斯分布的几率密度函数来表示。它长这样:
p(x|μ,σ2)=12π√σe12(xμσ)2 atom

μ=0 时,就变成了这样:
p(x|σ2)=12π√σex22σ2
这是一维高斯分布的公式,那么多维的呢?比较复杂,推导过程见知乎,长这样:
Formula
spa

无论怎样,你只要记住咱们如今没有能力关注所有的神秘变量,咱们只关心若干个可能重要的因素,这些因素的分布情况能够有各类假设,咱们回头再讨论他们的几率分布问题,咱们如今假定咱们对他们的具体分布状况也是一无所知,咱们只是知道他们处于ZS空间内。
前面说到了一个神秘组合,若是一个数据集X对应的神秘组合彻底同样,那么这个数据集就是一个单一的分类数据集,若是是多个,那么就是多分类数据集,但若是是一个连续的组合数据,那么就是一个有点分不清界限的复杂数据集,就比如,咱们这个数据集是一条线段的集合,线段的长度是惟一的神秘变量,那么只要长度在一个范围内连续变化,那么这个集合里的线段你就会发现分散的很均匀,你几乎没有办法区分开他们,也无法给他们分红几类,但若是这个长度值只能选择1,3,5,那么当你观察这个数据集的时候,你会发现他们会聚在三堆儿里。若是这个线段的生成彻底依靠的是计算机,那么每一堆儿都是彻底重合的,但若是是人画的,就可能由于偏差,无法彻底重合,这无法重合的部分就是咱们说的其余复杂因素,咱们一般用一个高斯分布来把它表明了。好,咱们已经基本清晰了,咱们该给这个神秘组合一个形式化的描述了。
假设有两个变量,zZSxXS ,存在一个肯定性函数族f(z;θ) ,族中的每一个函数由θΘ 惟一肯定,f:ZS×ΘXS ,当θ 固定,z是一个随机变量(几率密度函数为Pz(z) )时,那么f(z;θ) 就是定义在XS上的随机变量x,对应的几率密度函数能够写成g(x)。
那么咱们的目标就是优化θ 从而寻找到一个f,可以是随机变量x的采样和X很是的像。这里须要注意一下,x是一个变量,DX是已经现成的数据集,x不属于DX,我特地将名字起的有区分度。
这样,f就是那个神秘力量通道,他把这些神秘力量的力度,经过f变成了x变量,而这个x变量就是与数据集DX具备直接关系的随机变量。

设一个数据集为DX,那么这个数据集存在的几率为Pt(DX) ,则根据贝叶斯公式有:

Pt(DX)=Pxz(DX|z;θ)Pz(z)dz ; (1)

其中,Pxz(DX|z;θ) 是咱们新定义的几率密度函数,咱们前面知道f是将z映射成x,而x又与DX有某种直接的关系,这个直接关系能够表示成Px(DX|x) ,那么Pt(DX)=Px(DX|x)g(x)dx

这样咱们就直接定义个Pxz(DX|z;θ) 来替换Px(DX|x)g(x) ,从而表示z与DX的关系了。

好了,其实公式(1)就是咱们的神秘力量与观察到的数据集之间的神秘关系,这个关系的意思咱们直白的说就是:当隐秘变量按照某种规律存在时,就很是容易产生如今咱们看到的这个数据集。那么,咱们要作的工做就是当咱们假定有n个神秘力量时,咱们可以找到一个神奇的函数f,将神秘力量的变化转化成神奇的x的变化,这个x可以垂手可得地生成数据集DX。
从上面的描述里面咱们看到,f是生成转换函数,公式(1)不表示这种转换关系,而是这种关系的最大似然估计(maximum likelihood),它的意思是找到最有可能生成DX这个数据集的主导函数f。

接下来咱们回到讨论Pxz(DX|z;θ) 这个几率密度函数上来,咱们前面说过,若是z是所有的神秘力量,那么它产生的变量x就必定固定的,即当z取值固定时,x取值固定,可是现实中还有不少其余的因素,于是x的取值还与他们有关,他们的影响力,最终反映成了高斯函数,因此咱们大胆假定Pxz 是一个高斯分布的几率密度函数,即Pxz(DX|z;θ)=N(DX|f(x;θ),σ2I)

注意z的分布咱们依然是未知的。

假定咱们知道z如今取某一个或几个特定值,那么咱们就能够经过Gradient Descent来找到一个θ 尽可能知足z可以以极高的几率生成咱们但愿的数据集DX。再一推广,就变成了,z取值某一范围,但去几个特定值或某一取值范围是就面临z各类取值的几率问题,咱们回头再讨论这个棘手的问题,你如今只要知道冥冥之中,咱们彷佛能够经过学习参数θ 寻找最优解就好了。

OK,咱们还要说一个关键问题,就是咱们确信f是存在的,咱们认为变量与神秘变量之间的关系必定能够用一个函数来表示。

2. 变分自编码器(VAE)

本节,咱们探讨如何最大化公式(1)。首先,咱们要讨论怎样肯定神秘变量z,即z应该有几个维度,每一个维度的做用域是什么?更为较真的,咱们可能甚至要追究每一维度都表明什么?他们之间是否是独立的?每一个维度的几率分布是什么样的?

若是咱们沿着这个思路进行下去,就会陷入泥潭,咱们能够巧妙地避开这些问题,关键就在于让他们继续保持“神秘”!

咱们不关心每个维度表明什么含义,咱们只假定存在这么一群相互独立的变量,维度咱们也回到以前的讨论,咱们虽然不知道有多少,咱们能够假定有n个主要因素,n能够定的大一点,好比假设有4个主因素,而咱们假定有10个,那么最后训练出来,可能有6个长期是0。最后的问题须要详细讨论一下,比较复杂,就是z的几率分布和取值问题。

既然z是什么都不知道,咱们是否是能够寻找一组新的神秘变量w,让这个w服从标准正态分布N(0,I)I 是单位矩阵,而后这个w能够经过n个复杂函数,转换成z呢?有了神经网络这些也是可行的,假设这些复杂函数分别是h1,h2,,hn ,那么有z1=h1(w1),,zn=hn(wn) 。而z的具体分布是什么,取值范围是多少咱们也不用关心了,反正由一个神经网络去算。回想一下P(DX|z;θ)=N(DX|f(z;θ),σ2×I) ,咱们能够想象,若是f(z;θ) 是一个多层神经网络,那么前几层就用来将标准正态分布的w变成真正的隐变量z,后面几层才是将z映射成x,但因为w和z是一一对应关系,因此w某种意义上说也是一股神秘力量。就演化成w和x的关系了,既然w也是神秘变量,咱们就仍是叫回z,把那个以前咱们认为的神秘变量z忘掉吧。

好,更加波澜壮阔的历程要开始了,请坐好。

咱们如今已经有了

Pz(z)=N(0,I) ,

Pxz(DX|z;θ)=N(DX|f(x;θ),σ2I) ,

Pt(DX)=Pxz(DX|z;θ)Pz(z)dz ,

咱们如今就能够专心攻击f了,因为f是一个神经网络,咱们就能够梯度降低了。可是另外一个关键点在于咱们怎么知道这个f生成的样本,和DX更加像呢?若是这个问题解决不了,咱们根本都不知道咱们的目标函数是什么。

3. 设定目标函数

咱们先来定义个函数 Q(z|DX),数据集DX的发生,z的几率密度函数,即若是DX发生,Q(z|DX)就是z的几率密度函数,好比一个数字图像0,z隐式表明0的几率就很大,而那些表明1的几率就很小。若是咱们有办法搞到这个Q的函数表示,咱们就能够直接使用DX算出z的最佳值了。为何会引入Q呢?其实道理很简单,若是DX是x这个变量直接生成的,要想找回x的模型,就要引入一个几率密度函数T(x|DX),亦即针对DX,咱们要找到一个x的最佳几率密度函数。
如今的问题就变成了,咱们能够根据DX计算出Q(z|DX)来让他尽可能与理想的Pz(z|DX)尽可能的趋同,这就要引入更加高深的功夫了——相对熵,也叫KL散度(Kullback-Leibler divergence,用 D 表示)。

离散几率分布的KL公式

KL(pq)=p(x)logp(x)q(x)

连续几率分布的KL公式

KL(pq)=p(x)logp(x)q(x)dx

Pz(z|DX)Q(z|DX) 的KL散度为

D[Q(z|DX)Pz(z|DX)]=Q(z|DX)[logQ(z|DX)logPz(z|DX)]
也可写成
D[Q(z|DX)Pz(z|DX)]=EzQ[logQ(z|DX)logPz(z|DX)]

经过贝叶斯公式

Pz(z|DX)=P(DX|z)P(z)P(DX)
这里再也不给P起名,其实Pz(z)直接写成P(z)也是没有任何问题的,前面只是为了区分概念,括号中的内容已经足以表意。

D[Q(z|DX)Pz(z|DX)]=EzQ[logQ(z|DX)logP(DX|z)logP(z)]+logP(DX)

由于logP(DX) 与z变量无关,直接就能够提出来了,进而获得闪闪发光的公式(2):

logP(DX)D[Q(z|DX)P(z|DX)]=EzQ[logP(DX|z)]D[Q(z|DX)P(z)] ; (2)

公式(2)是VAE的核心公式,咱们接下来分析一个这个公式。
公式的左边有咱们的优化目标P(DX),同时携带了一个偏差项,这个偏差项反映了给定DX的状况下的真实分布Q与理想分布P的相对熵,当Q彻底符合理想分布时,这个偏差项就为0,而等式右边就是咱们可使用梯度降低进行优化的,这里面的Q(z|DX)特别像一个DX->z的编码器,P(DX|z)特别像z->DX的解码器,这就是VAE架构也被称为自编码器的缘由。

因为DX早已再也不有分歧,咱们在这里把全部的DX都换成了X。

咱们如今有公式(2)的拆分:
– 左侧第一项:logP(X)
– 左侧第二项:D(Q(z|XP(z|X))
– 右边第一项:EzQ[logP(X|z)]
– 右边第二项:D[Q(z|X)P(z)]

还有下面这些:
P(z)=N(0,I) ,
P(X|z)=N(X|f(z),σ2I) ,
Q(z|X)=N(z|μ(X),Σ(X))

咱们再明确一下每一个几率的含义:
P(X) ——当前这个数据集发生的几率,可是他的几率分布咱们是不知道,好比,X的空间是一个一维有限空间,好比只能取值0-9的整数,而咱们的 X = { 0, 1, 2, 3, 4 },那么当几率分布是均匀的时候,P(X)就是0.5,可是若是不是这个分布,就很差说是什么了,没准是0.1, 0.01,都有可能。P(X)是一个函数,就好像是一我的,当你问他X=某个值的时候,他能告诉发生的几率。
P(z) —— 这个z是咱们后来引入的那个w,还记得吗?他们都已经归顺了正态分布,若是z是一维的,那他就是标准正态分布N(0, I)。
P(X|z) —— 这个函数的含义是若是z给定一个取值,那么就知道X取某个值的几率,仍是举个例子,z是一个神奇的变量,能够控制在计算机屏幕上出现整个屏幕的红色而且控制其灰度,z服从N(0,1)分布,当z=0时表明纯正的红色,z越偏离0,屏幕的红色就越深,那么P(X|z)就表示z等于某个值时X=另外一值的几率,因为计算机是精确控制的,没有额外的随机因素,因此若是z=0可以致使X取一个固定色值0xFF0000,那么P(X=0xFF0000|z=0)=1,P(x!=0xFF0000|z=0) = 0,但若是现实世界比较复杂附加其余的随机因素,那么就可能在z肯定出来的X基础值之上作随机了。这就是咱们以前讨论的,大数定理,P(X|z)=N(X|f(x),σ2I) 。f(z)就是X与z直接关系的写照。
P(z|X) —— 当X发生时,z的几率是多少呢?回到刚才计算机屏幕的例子,就很是简单了P(z=0|X=0xFF0000) = 1, P(z!=0|X=0xFF0000) = 0,可是因为几率的引入,X|z能够简化成高斯关系,相反,也能够简化高斯关系。这个解释对下面的Q一样适用。
Q(z) —— 对于Q的分析和P的分析是同样的,只不过Q和P的不一样时,咱们假定P是那个理想中的分布,是真正决定X的最终构成的背后真实力量,而Q是咱们的亲儿子,试着弄出来的赝品,而且但愿在现实世界经过神经网络,让这个赝品可以尝试控制产生X。当这个Q真的行为和咱们理想中的P如出一辙的时候,Q就是上等的赝品了,甚至能够打出如假包换的招牌。咱们的P已经简化成N(0,I),就意味着Q只能向N(0, I)靠拢。
Q(z|X) —— 根据现实中X和Q的关系推导出的几率函数, 当X发生时,对应的z取值的几率分布状况。
Q(X|z) —— 现实中z发生时,取值X的几率。

咱们的目标是优化P(X),可是咱们不知道他的分布,因此根本无法优化,这就是咱们没有任何先验知识。因此有了公式(2),左边第二项是P(z|X)Q(z|X) 的相对熵,意味着X发生时现实的分布应该与咱们理想的分布趋同才对,因此整个左边都是咱们的优化目标,只要左边越大就越好,那么右边的目标就是越大越好。

右边第一项:EzQ[logP(X|z)] 就是针对面对真实的z的分布状况(依赖Q(z|X),由X->z的映射关系决定),算出来的X的分布,相似于根据z重建X的过程。
右边第二项:D[Q(z|X)P(z)] 就是让根据X重建的z与真实的z尽可能趋近,因为P(z)是明确的N(0, I),而Q(z|X)是也是正态分布,其实就是要让Q(z|X)趋近与标准正态分布。

如今咱们对这个公式的理解更加深刻了。接下来,咱们要进行实现的工做。

4. 实现

针对右边两项分别实现
第二项是Q(z|X)与N(0, I)的相对熵,X->z构成了编码器部分。
Q(z|x)是正态分布,两个正态分布的KL计算公式以下(太复杂了,我也推不出来,感兴趣的看[1]):

KL(N(μ,Σ)N(0,I))=12[log[det(Σ)]d+tr(Σ)+μTμ]

det 是行列式,tr 是算矩阵的秩,dI 的秩即d=tr(I)

变成具体的神经网络和矩阵运算,还须要进一步变化该式:

KL(N(μ,Σ)N(0,I))=12i[log(Σi)+Σi+μ2i1]
OK,这个KL咱们也会计算了,还有一个事情就是编码器网络,μ(X)Σ(X) 都使用神经网络来编码就能够了。

第一项是EzQ[logP(X|z)] 表明依赖z重建出来的数据与X尽可能地相同,z->X重建X构成了解码器部分,整个重建的关键就是f函数,对咱们来讲就是创建一个解码器神经网络。

到此,整个实现的细节就全都展示在下面这张图里了

111

因为这个网络传递结构的一个环节是随机采样,致使没法反向传播,因此聪明的前辈又将这个结构优化成了这样:

222

这样就能够对整个网络进行反向传播训练了。

具体的实现代码,我实如今了这里:

https://github.com/vaxin/TensorFlow-Examples/blob/master/examples/3_NeuralNetworks/variational_autoencoder.py

里面的每一步,都有配合本文章的对照解释。

5. 延伸思考

之因此关注VAE,是从文献[4]引起的,因为视觉早期的概念造成对于以后的视觉认知起了十分关键的做用,咱们有理由相信,在神经网络训练时,利用这种递进关系,先构建具备基础认知能力的神经网络,再作高级认知任务时会有极大的效果提高。但经过前面神秘变量的分析,咱们发现,为了充分利用高斯分布,咱们将w替换成了z,也就是说真正的隐变量隐藏在f的神经网络里面,而如今的z反而容易变成说不清楚的东西,这一不利于后续的时候,二来咱们须要思考,是否应该还原真实的z,从而在层次化递进上有更大的发挥空间。

[1] http://stats.stackexchange.com/questions/60680/kl-divergence-between-two-multivariate-gaussians[2] https://arxiv.org/abs/1606.05908[3] https://zhuanlan.zhihu.com/p/22464768[4] https://arxiv.org/abs/1606.05579

相关文章
相关标签/搜索