VAE
VAE
本文是[Architecture with Code]系列的第一篇。鉴于中文网路上已有许多对于网路架构的精到的解读,而开源社区也不乏许多非常好的网络实现。但是文字解读如何精妙,也不免会忽略一些代码实现中具体的地方;代码实现如何紧凑,也难免缺少引导,让人难以把握其中的脉络。另外,我想读者们每每看到论文中说基准测试得分提升了多少,也很想亲自一试它的神奇。本系列的目的,在于通过文字理清脉络,通过代码展现具体实现。文末附有代码地址,感兴趣的读者可以一键运行这个架构。
事不宜迟,我们开始正题。
引入
VAE(变分自动编码器)适用于图像生成。使用解卷积层,可以从单列特征向量恢复出二维图像。
图1.从列向量恢复出图像,使用输出结果和原始图像的均方误差作为损失,这样通过一轮一轮的训练,图像的信息就被保留在了网络参数中。
假设输入的列向量有n×1维,如果使用one-hot编码,则理论上这个解卷积网络中至多可以存储n幅图像的信息。例如[1,0,0,0]代表鸡,[0,1,0,0]代表猪,[0,0,1,0]代表鱼,[0,0,0,1]代表牛。
为了扩展网络的能力,将one-hot编码换成普通的实数向量,例如[3.3, 4.5, 2.1, 9.8]表示一张猫的图片,[3.4, 2.1, 6.7, 4.2]表示一张狗的图片,这些向量被称为隐变量(latent variables)。如下图所示,一张图片对应的隐变量是用图像编码器(卷积神经网络)获得的。
图2.隐变量和编码器、解码器。原始图像经过编码器得到低维的隐变量,隐变量经过解码器解码恢复出原始图像。
上面的架构已经可以让网络进行训练了,不过目前这个架构以图片为输入,以(质量通常更差的)图片作为输出,并没有什么意义,因为目前还不知道如何抛开图像编码器得到隐变量。
一个简单的解决方法是对隐变量加以约束。如果编码器生成的隐变量服从正态分布,那么生成图像时只需要从正态分布中采样生成隐变量就可以了,不需要编码器。
这种约束可以设计在在损失函数中,让网络在图片的重构准确度和隐层变量与高斯分布的拟合度上进行权衡。一方面,重构精确度可以用均方误差衡量,分布拟合度可以用KL散度来衡量。
$D_{ { {\mathrm {KL} } } }(P|Q)=\sum _{i}P(i)\ln {\frac {P(i)}{Q(i)} }.!$
$KL(N(\mu, \sigma), N(0, 1)) = \log \frac{1}{\sigma} + \frac{\sigma^2 + \mu^2}{2} - \frac{1}{2}$
即按概率P求得的P和Q的对数商的平均值。KL散度仅当概率P和Q各自总和均为1,且对于任何i皆满足Q(i)>0,P(i)>0才有意义。
1 | generation_loss = mean(square(generated_image - real_image)) |
图3.将隐层变量看做服从均值为z_mean,方差为z_stddev的正态分布
利用均值和标准差,从正态分布中采样就可以获得隐变量输入生成网络
1 | samples = tf.random_normal([batchsize,n_z],0,1,dtype=tf.float32) |
下期我们会释出带有详细注释的代码,敬请期待。