- 更新时间:2018-07-29
前言
作为一个坚守9年的V迷,谈VAE还是很兴奋的,虽然这次谈的是Variational AutoEncoder(变分自编码)。这几年,深度学习中的无监督学习越来越受到关注,其中以GAN和VAE最受欢迎,之前有介绍过AE(AutoEncoder)的详解一、详解二和AE实现,本文介绍变分自编码——VAE。
注:之前的名为VAE详解的半成品没有用markdown,编辑公式比较麻烦,索性copy过来重写了一个。
VAE介绍
变分自编码是一个使用学好的近似推断的有向模型,可以纯粹地使用基于梯度的方法进行训练。
AutoEncoder的基本原理是通过encode和decode实现,与PCA类似,在卷积的AutoEncoder中,encode通过卷积池化进行降维,decode通过反卷积反池化进行升维,目标是使输入和输出图片的差异性最小,这也使得自编码器生成的图片多与输入相似,无法生成“新"的图片,由此,2013年提出了新的生成模型——变分自编码。
上图是AutoEncoder的结构示意图,当训练得到Decoder之后,我们希望输入一个code,通过decoder生成一张图片,但实际上仅仅通过AutoEncoder得到的结果并不好。
但如果使用VAE,相比之下效果就会好很多。VAE的实现过程如下:与AE相比,encoder过程和decoder过程都不变,在中间加入了一些trick,encoder输出两个vector,假设原本AE中生成的code是十维,生成的两个即
(
m
1
,
m
2
,
m
3
,
⋯
 
,
m
10
)
(m_1,m_2,m_3, \cdots, m_{10})
(m1,m2,m3,⋯,m10) 和
(
σ
1
,
σ
2
,
σ
3
,
⋯
 
,
σ
10
)
(\sigma_1,\sigma_2,\sigma_3, \cdots, \sigma_{10})
(σ1,σ2,σ3,⋯,σ10) ,之后再从正态分布(normal distribution)中生成一个vector:
(
e
1
,
e
2
,
e
3
,
⋯
 
,
e
10
)
(e_1,e_2,e_3, \cdots, e_{10})
(e1,e2,e3,⋯,e10),执行如下计算:
(1)
c
i
=
e
x
p
(
σ
i
)
⋅
e
i
+
m
i
c_i=exp(\sigma_i) \cdot e_i + m_i \tag{1}
ci=exp(σi)⋅ei+mi(1) 从而生成
(
c
1
,
c
2
,
c
3
,
⋯
 
,
c
10
)
(c_1,c_2,c_3, \cdots, c_{10})
(c1,c2,c3,⋯,c10),再把
(
c
1
,
c
2
,
c
3
,
⋯
 
,
c
10
)
(c_1,c_2,c_3, \cdots, c_{10})
(c1,c2,c3,⋯,c10) 丢进decoder中得到输出,通过“使input和output越接近越好“这个目标来优化模型。
那上面的计算过程有什么作用呢?实际上,在AE的基础上通过encoder产生的向量,可以这么理解:
假如在AE中,一张满月的图片作为输入,模型得到的输出是一张满月的图片;一张弦月的图片作为输入,模型得到的是一张弦月的图片。当从满月的code和弦月的code中间sample出一个点,我们希望是一张介于满月和弦月之间的图片,但实际上,对于AE我们没办法确定模型会输出什么样的图片,因为我们并不知道模型从满月的code到弦月的code发生了什么变化。
而VAE做的事情,实际上就是在原本满月和弦月生成的code上面加了noise,即在某个数值区间内,每个点理论上都可以输出满月的图片;在某个数值区间内,每个点理论上都可以输出弦月的图片,当调整这个noise的值的时候,也就是改变了这个数值区间,如下图所示,当两个区间出现重合的公共点,那么理论上,这个点既应该像满月,又应该像弦月,因此输出的图片就应该兼具满月和弦月的图片特点,也就生成一张介于满月和弦月之间的月相,而这个月相,在原本的输入中是不存在的,即生成了新的图片。
上面说的noise,就是上面示意图中的乘积部分:
m
m
m 对应与原来AE中的code,
σ
\sigma
σ 是从输入图片中生成的,但它表示noise的variance,e是从正态分布中抽样得到的,二者相乘即得到了影响code的数值区间的noise,variance影响了noise的大小,而且是由encoder训练得到的,如果只考虑“使input和output越接近越好“这个目标来优化模型,那训练得到的variance为0时候模型理论最佳,也就变成了原来的AE。因此需要对这个计算过程做一个限制,如下:
(2)
m
i
n
i
m
i
z
e
∑
i
=
1
10
(
e
x
p
(
σ
i
)
−
(
1
+
σ
i
)
+
(
m
i
)
2
)
minimize\ \ \ \sum_{i=1}^{10}(exp(\sigma_i)-(1+\sigma_i)+(m_i)^2) \tag{2}
minimize i=1∑10(exp(σi)−(1+σi)+(mi)2)(2)
对于上式,
e
x
p
(
σ
i
)
exp(\sigma_i)
exp(σi) 的图像如下图蓝色所示,
1
+
σ
i
1+\sigma_i
1+σi 的图像如下图红色部分所示,即当
σ
i
\sigma_i
σi 为0时,二者的差会取得最小值,因此需要加上一个L-2正则项,强迫这个variance不能太小。
VAE过程有一个优势就是:可以通过调整code中的某维来确定code的维度所代表的东西,假设得到的code是十维的向量,我们控制其中的八维,来讨论省下的两维,如下图所示,先在坐标系中均匀采点,然后把取样的点连同固定的八维一起丢到decoder中,这样就可以观察这两维对于VAE生成图片的作用效果。
如下图所示,分别为人脸的生成映射和MNIST数据集上固定其中两维进行图像生成,从左侧的人脸图片中,可以猜测两维特征可能分别控制着人脸的角度和表情;右侧MNIST数据集中,两维特征可能控制着数字中笔画的弯曲程度和数字的倾斜程度。
本片博客主要介绍VAE的理解,后续会整理VAE的算法原理、TensorFlow实现以及其他几种AE结构~