引言
笔记主要参考变分自编码器的原论文《Auto-Encoding Variational Bayes》,与苏神的博客
VAE模型
VAE的目标(与GAN相同):希望构建一个从隐变量生成目标数据的模型。
VAE的核心是:进行分布之间的变换。
VAE的Encoder有两个,一个用来计算均值,一个用来计算方差。
问题所在
但生成模型的难题是判断生成分布与真实分布的相似度。(即我们只知道抽样结果,不知道分布表达式)
大部分教程所述的VAE
模型思路是:先从标准正态分布中采样一个Z,然后根据Z来算一个X。
若VAE结构确实是这个图的话,我们其实完全不清楚:究竟经过重新采样出来的,是不是还对应着原来的。
其实,在整个VAE模型中,我们并没有去使用(隐变量空间的分布)是正态分布的假设,我们用的是假设(后验分布)是正态分布!
但是,训练好的神经网络
并且VAE会让所有的都向标准正态分布看齐:
真实的VAE
但是神经网络经过训练之后的方差会接近0。采样只会得到确定的结果。
因此还需要使所有的正态分布都向标准正态分布(模型的假设)看齐。为了使所有的P(Z|X)都向看齐,我们需要:
编码器:使用神经网络方法拟合参数
构建两个神经网络:$\mu_k=f_1(Xk), log{\sigma^2}=f_2(X_k)\mathcal{N}(0,I)$。
1 | z_mean = Dense(latent_dim)(h) |
针对两个损失的比例选取,使用KL散度作为额外的loss。上式的计算结果为:
$$\mathcal{L}{\mu,\sigma^2}=\frac{1}{2} \sum{i=1}^d \Big(\mu{(i)}^2 + \sigma{(i)}^2 - \log \sigma_{(i)}^2 - 1\Big)$$
1 | kl_loss = - 0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1) |
解码器:保证生成能力
我们最终的目标则是最小化误差。
解码器重构的过程是希望没噪声的,而则希望有高斯噪声的,两者是对立的。所以,VAE跟GAN一样,内部其实是包含了一个对抗的过程,只不过它们两者是混合起来,共同进化的。
reparameterization trick(重参数技巧)
在反向传播优化均值和方差的过程中,“采样”操作是不可导的,但是采样的结果是可导的。
因此可以利用标准正太分布采样出的直接估算。
1 | def sampling(args): |
于是“采样”操作不再参与梯度下降,改为采样的结果参与,使得整个模型可以训练。
DEMO:基于CNN和VAE的作诗机器人
模型结构
先将每个字embedding为向量,然后用层叠CNN来做编码,接着池化得到一个encoder的结果,根据这个结果生成计算均值和方差,然后生成正态分布并重新采样。在解码截断,由于现在只有一个encoder的输出结果,而最后要输出多个字,所以先接了多个不同的全连接层,得到多样的输出,然后再接着全连接层。
GCNN(Gated Convolutional Networks)
这里的CNN不是普通的CNN+ReLU,而是facebook提出的GCNN,其实就是做两个不同的、外形一样的CNN,一个不加激活函数,一个用sigmoid激活,然后把结果乘起来。这样一来sigmoid那部分就相当于起到了一个“门(gate)”的作用。