变分自编码器(Variational Autoencoder)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Cyril__Li/article/details/72801124

最近想了解一下生成模型(generative model),这两三天看了很多关于变分自编码器(Variational Autoencoder)的资料,发现VAE实现起来比较简单,但是因为没什么概率图模型的基础,对于它的理论感觉理解起来很费力,所以开始在空闲的时候看Coursera上面那门Koller的概率图模型的公开课

个人觉得Variational Autoencoder比较有用的资料:
1. Oliver Dürr的VAE的PPT(非常推荐,讲得很清晰)
2. Jaan Altossar 的VAE Tutorial

1. 结构

这里写图片描述

这样来看,变分子编码器的结构和传统自编码器的结构最大的区别就是变分子编码器的encoder和decoder输出的都是概率密度函数的参数。对于z而言已经假设它符合标准正态分布,因此encoder network的输出形状为(Batch_size, 2*latent_dims),其中一半表示latent variable z的均值,另一半表示方差。

需要注意

实际编程时,通常让encoder输出 z_log_sigma_sq=lnσ2 ,而不是直接输出 σ 。因为 σ 取值只能为正数, log_sigma_sq 取值为R,更适合作为网络的输出。
或者也可以用softplus激活函数,让网络输出处在0-1区间,来表示 σ

2. Reparameterization

在得到了z的概率密度函数参数之后,就可以对z进行采样,然而随机采样的话就无法使用误差反向传递来训练网络了,因此这里使用了Reparameterization Trick来得到z,即:

zi=μi+σi×ε

其中, ε 符合标准正态分布。

#定义计算图
...
eps_placeholder = tf.placeholder("float",shape=[None, latent_dims])
...
z_mean, z_log_sigma_sq = encoder_network()
z = tf.add(z_mean, tf.multiply(tf.sqrt(tf.exp(z_log_sigma_sq)),eps_placeholder))
...
# 训练
eps = np.random.normal(loc=0.0,scale=1.0,size=(batch_size,latent_dims])
# feed_dict={..., eps_placeholder:eps...}

3. 关于Decoder的输出

这里应该分为两种情况,一种是输入x为二值型的,另一种是输入x为连续的。

3.1 x为二值型

在Github上面有不少VAE的实现都是使用MNIST作为例子,然后在输入时可以把图片转换为二值的。
对于二值型的样本,decoder network的输出就认为是符合伯努利分布的,输出的就是值为1的概率,因此应该使用sigmoid函数,让输出在0-1区间内。

3.2 x为连续的

对于连续的样本,decoder network的输出认为是符合正态分布的,输出应该像z一样一半是均值,一般是方差,但在实现代码时,通常只输出均值。
如果输入样本是经过归一化,取值在0-1区间,decoder network的输出也应该用sigmoid函数。

4. 目标函数

目标函数分为两部分,一部分为Q(z|x)和标准正态分布的KL散度,另一部分可看作输入x和重构得到的 x˜ 的差距。

4.1 Q(z|x)和标准正态分布的KL散度

这里写图片描述

4.2 输入x和重构得到的 x˜ 的差距

对于二值型的,这一部分可以使用交叉熵。
对于连续型的,这一部分为Squared Error。

猜你喜欢

转载自blog.csdn.net/Cyril__Li/article/details/72801124