由AE到生成模型VAE
- 由自编码器AE得到一个生成类模型:VAE
- 参考:
- 前言
- AE(Auto-Encoder)自编码器
- AE的结构与作用:
- AE不是生成模型
- VAE(Variational AutoEncoder) 变分自编码器
- VAE做出的改变
- VAE结构(VAE的前向传播)
- VAE的反向传播(损失函数)
- AE与VAE的区别
由自编码器AE得到一个生成类模型:VAE
参考:
1:AE、VAE:
2: VAE以及损失函数:https://zhuanlan.zhihu.com/p/345360992
前言
学习不仅仅在于学习本身,还有创新,深度学习也一样,不仅在于其强大的学习能力,更在于它的创新能力。
所以,我们将模型分为两类,一类是判别模型,一类是生成模型。
所谓判别模型,通常是利用训练样本来训练模型,然后利用该模型,对新的输入样本x,进行判别或预测,得到一个y。
而生成模型正好是其反过程,是根据一些规则y,来生成新样本x。
AE(Auto-Encoder)自编码器
AE的结构与作用:
它的主体结构是:
X————>Z————>Y
其中,X到Z的过程是编码(Encode)的过程,X是输入样本,Z是编码得到的潜在向量。
Z到Y的过程是一个解码(Decode)的过程
AE最主要的一个应用就是数据压缩:
很容易理解这个应用,因为上述整个过程其实是对X的一个压缩和解压缩,即先压缩X到Z,再由Z还原得到Y,这个Y应该和X“很像”。
怎么实现这个很像呢?
答:定义损失函数,通过神经网络进行优化即可。
这个损失函数就是输入样本X在压缩解压缩(编码解码)过程种损失掉的信息,所以AE事实上是一种有损的数据压缩
自编码器AE是一种无监督的学习
因为它无需label,只需要与data本身做loss即可。
AE不是生成模型
AE的整个网络结构可以看成两部分
一个由函数Z = f(X) 表示的编码器和一个生成重构的解码器Y = g(Z)。
而AE实现的是让 Y = g(f(X))≈ X ,所以事实上AE完成的是对输入样本X的一个重构
为什么AE不是生成模型呢呢?
因为潜在向量Z本质上还是从输入样本X种产生的,并没有其他约束,不能随意产生合理的潜在变量。
个人理解:其实也是因为AE是无监督学习,没有别的label自然无法生成别的样式。
VAE(Variational AutoEncoder) 变分自编码器
VAE做出的改变
VAE主要针对AE不能随意产生合理的潜在变量这一点做了改变,即针对Z进行了改变。
VAE对Z增加了一些约束,即对编码器增加了约束,要求:Z满足正态分布
Z~N(mean,var)
因为正态分布需要确定mean和var,用神经网络去拟合比用一些传统方法估计更加简单,而且效果也不错,所以选择神经网络拟合确定mean和var。
VAE结构(VAE的前向传播)
p.s.:这里得到Z是因为(那个忘了怎么读的符号下面用e代替嘿嘿):
e~N(0,1)
Z~N(mean,var)
(Z-mean)/sqrt(var) ~ N(0,1)
所以 Z = exp[log_sqrt(var)] * e + mean = exp(0.5 * log_var) * e+ mean
这里e是随机采样的,这就可以保证潜在空间的连续性、良好的结构性。而这些特性使得潜在空间的每个方向都表示数据中有意义的变化方向。
(潜在空间指潜在向量Z所在的空间)
VAE的反向传播(损失函数)
损失函数是衡量模型优劣的主要指标,VAE应从以下两个方面衡量:
①生成的新图像与原图像的相似度
②隐含空间的分布与正态分布的相似度
度量图像相似度一般采用交叉熵函数。
度量两个分布的相似度一般采用KL散度。
(KL(P||Q) = ΣP(xi)log(P(x1)/Q(xi))= -H(P(x)) +[-ΣP(xi)log(Q(xi))]= -H(P(x)) + [-H(P,Q)])即等于P的熵和PQ的交叉熵求和后取负值。
这两个度量构成了VAE的损失函数。
我们先看损失函数的python代码:
def loss_function_original(recon_x, x, mu, logvar):
BCE = F.binary_cross_entropy(recon_x, x.view(-1, 784), reduction='sum')
# 0.5 * sum(1 + log(sigma^2) - mu^2 - sigma^2)
KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
return BCE + KLD
注意,这里由于要采用BCE函数,即二分类的交叉熵,则需要将神经网络的输出限制在【0,1】之间,所以需要加一个sigmoid函数。
损失函数的几点可改变的地方:
1.事实上,这里的BCE和KLD是可以加上权重的,这样可以来权衡重构和生成在该项任务里的比例。
2.BCE可以换为L1或者L2 loss,L1效果会比L2好一点
3.如果不要KLD项会怎么样?
即忽视了重构项,使得模型学到了一组完全随机的标准正态分布,即高斯噪声。
AE与VAE的区别
实际上,在AE的基础上通过encoder产生的向量,可以这么理解:
假如在AE中,一张满月的图片作为输入,模型得到的输出是一张满月的图片;一张弦月的图片作为输入,模型得到的是一张弦月的图片。当从满月的code和弦月的code中间sample出一个点,我们希望是一张介于满月和弦月之间的图片,但实际上,对于AE我们没办法确定模型会输出什么样的图片,因为我们并不知道模型从满月的code到弦月的code发生了什么变化。
而VAE做的事情,实际上就是在原本满月和弦月生成的code上面加了noise噪声,即在某个数值区间内,每个点理论上都可以输出满月的图片;在某个数值区间内,每个点理论上都可以输出弦月的图片,当调整这个noise的值的时候,也就是改变了这个数值区间,如下图所示,当两个区间出现重合的公共点,那么理论上,这个点既应该像满月,又应该像弦月,因此输出的图片就应该兼具满月和弦月的图片特点,也就生成一张介于满月和弦月之间的月相,而这个月相,在原本的输入中是不存在的,即生成了新的图片。
所以,VAE通过神经网络学习来确定mean和var事实上就是在确定这个数值区间,即满月编码出来的潜在空间的数值区间和弦月编码出来的潜在空间的数值区间,而在这两个区间的交集,则即像满月,又像弦月,就实现了生成这一功效。
再以人脸做以下比较:
AE就是将人脸编码成几个特征(特征提取),每个特征都有一个数值。
而VAE则是将人脸编码成几个特征,每个特征都有一个数值区间的分布