项目
MNIST 数据集上实现 VAE 模型
MNIST 数据集上实现 VAE 模型
理论知识
啥是 VAE 模型,最开始以为就是普通的压缩和复原。把高维特征压缩到一个低维向量,再把这个低维向量恢复成高维特征。但这是 auto encoder 做的事情。压缩和复原。VAE 的关键在于压缩成的低维隐向量不是一个确定的隐向量。他的隐向量是从一个范围内采样得到的。所以它生成的图像不是简单恢复原图,而是和原图具有同样风格的图片。这有什么用,可以生成训练集。
一个固定的隐向量到 隐向量从一个范围内采样,会引入很多问题:怎么确保随机采样的范围效果好?额外添加损失。(说的不准确,大致意思是有一个 KL 散度);神经网络中引入随机采样的模块,采样操作本身不好做反向传播,如何解决?重参数化技巧。
加深理解这个采样操作。
- encoder 的输出到底是什么?隐向量 Z 是怎么得到的?
输出是一个均值向量和方差向量。为啥是向量,因为隐向量不止一个维度,隐向量每一个维度的取值服从的分布就是 均值向量和 方差向量的第 i 个维度确定的分布;
编码器的作用负责把高维数据压缩进一个低维隐向量;具体来说就是对不同的输入数据X,输出一个分布;所有的分布要尽可能占满标准正态分布。
- decoder 采样是从先验分布还是后验分布啊?decoder 为啥要采样?
分情况。训练时,decoder 从后验分布(encoder 生成的 分布)采样,目的是学会”把输入 X 映射成的 Z 还原成原始图片“; 推理时,直接从先验分布(正态分布)采样。 明白了这一点就知道为啥我们希望先验分布和后验分布尽量保持一致了,为了让推理时 的采样落在自己熟悉的区域。那为啥要采样?复原图片需要数据。
训练时,希望 decoder 把不同的输入图片生成的隐向量投影在标准正态分布的不同区域
- KL 计算的是什么?
KL 散度计算的是每个样本对应的后验分布和先验分布之间的差距。然后总损失的 KL 项就是对所有的差距求和或者求平均。 这里每个样本对应的后验分布应该是正态分布的一部分。
- 此时再回答,KL 小,带来什么?KL 大呢?
KL 小,所有图片对应的后验分布都接近正态分布,取样,生成新图片,得到的新图片都差不多。比如 1,2,3 得到的图片都一个样。这就是后验崩塌。
KL 大,各个样本对应的后验分布和正态分布差距很大,甚至超出了正态分布;如此一来,推理时,decoder 从正态分布取样得到的区域都是自己训练时没有接触过的。生成的图片效果不好。
- encoder decoder 是由权重矩阵构成的吗
一般来说,encoder decoder 都是一层层神经网络构成;每一层包含权重矩阵,偏置,激活函数等等。VAE 的 decoder 有两个输出头,因为它输出两个向量,这是特殊之处。
- 怎么约束分布占满标准正态?
通过 KL 散度约束。KL 散度强制要求分布必须在正态分布。KL 的值大,约束能力不强,隐空间 跨度很大,decoder 生成效果差。为啥效果差,因为先验分布只是训练得到的分布的一部分,
- VAE 的损失函数:评价体系:重构损失与 KL 散度
重构损失,计算生成图片和原图的区别。大说明:说明模型的恢复能力不强;重构小:说明模型很好的学会了从输入复原输出。但这在 VAE 不一定是好事。VAE 不止追求长得像还要有自己的不同之处。
- ELBO 是什么
ELBO ,证据下界。核心思想是,真实目标很难直接优化,我们构造一个可以优化的下界。然后问题转化为最大化这个下界。
在生成模型里,最大化的是生成真实图片的概率尽可能大。这个概率的计算涉及无法计算的积分。
- VAE 生成图像可能会模糊的原因
把具有不同结构的图片映射到被约束的隐空间,会有一些区域是不同数字的融合。这就导致生图的时候会产生平均结果,导致图像模糊。
实验具体相关
- VAE 的核心过程
在 src models vae 里面。 encoder 把 784 维度映射到隐向量的维度 20,然后输出均值和对数方差。 重参数化得到 Z;decoder 有两层放缩,先把隐向量维度映射成 400,然后再恢复成 784 维度; decoder 有个 sigmoid 归一化,把像素值归一化到 0,1;因为加载 MNIST 的时候会进行归一化,然后送给 encoder。处理完图片之后再归一化,方便计算重构损失。
验证集其实也是在训练阶段使用,帮助我们选择合适的超参数配置,注意不会参与模型内部参数的更新。 比如 如果发现模型在训练集上效果越来越好但是验证集的效果差,就会提前终止训练。
- 我不理解为什么非要让 encoder 输出的分布要接近正态分布?为什么要这么设计,凭空想出来的吗?
先理解这样一件事:比如说隐向量是 N 维,我们输入的图片经过 encoder 编码之后就看作是 N 维空间的一个点;采样这个该位置这个点之后,decoder 可以复原出原图。如果没有 KL 散度约束,encoder 自由发挥,把图片编码到 N 维空间的任意一个位置;想生成图片时, 采样点就可能落在decoder 没有见过的区域,此时生出来的图片效果很差甚至无意义。 这个时候我们说隐空间是不连续的。
如果我们约束 encoder 把图片都尽量编码到正态分布,然后只在正态分布采样让 decoder 恢复,就能保证 采样点都是 decoder 见过的。
- 看效果
两个可视化结果。一个是从原图生成的重建图。一个是随机采样生成的图。重建图更清晰,因为它采样时服从的分布是原图经过 encoder 生成的,落在模型更熟悉的区域。随机采样生成的图,是 decoder 在 标准正态分布 里面取样,可能会落在数字类别之间,或者 decoder 不熟悉的区域,因此会更糊。
在二维隐向量中,绘制了一个图。怎么得到的?一张样本图,encoder把它压缩到二维隐向量,用压缩之后的两个期望做横纵坐标。 同一个类别的图片应该聚集在一起,因为结构相似的数字,压缩之后的期望也相近。0 6 相邻;4 9 相邻乃至有重叠,因为他们有部分结构相似。
关于一些问题:
- 我可以说,学了VAE 之后, 生图模型的本质 就是从一个高维分布采样吗? 我想知道里面的细节,得到一个分布之后,是如何用这个分布变成图片?像素点是如何构建的?
VAE 是从一个低维分布采样。具体来说,encoder 给出一个期望向量和对数方差向量,这两个向量共同定义了一个 N 维度正态分布(N 是隐向量的维度)。这个正态分布重参数化一下,然后再从这个N 维正态分布采样,采样得到的点送给 decoder。
采样之后得到一个 N 维隐向量,decoder 拿到这个隐向量z=[z1,…,zn],。decoder 会根据这N个值生成 784 个像素点,把这个像素点按照 28X28 排列就成了一张图。decoder 内部是多层权重矩阵和非线性激活函数组成的神经网络。