问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

自回归图像学习:AE、VAE与VQ-VAE的区别详解

创作时间:
作者:
@小白创作中心

自回归图像学习:AE、VAE与VQ-VAE的区别详解

引用
CSDN
1.
https://m.blog.csdn.net/qq_51083858/article/details/144631741

自回归图像学习是深度学习领域的重要研究方向,其中自动编码器(AE)、变分自动编码器(VAE)和向量量化变分自动编码器(VQ-VAE)是三种常见的模型。本文将从原理、特点和应用场景等多个维度对这三种模型进行对比分析。

AE:自动编码器

AE可以理解为一个单纯的图像压缩器,其编码器用来做特征提取,提取图像的隐变量;解码器用来重建图像,整体达到图像压缩的目标。

具有以下特点:

  1. 每次提取的图像特征是唯一的,固定的,因此无法用来做图像生成任务,因为每次重建的图像固定,如果想生成不同的图像只能手工在隐空间修改部分隐变量,而且这种修改容易生成非常错误的图像。

  2. 同一张图像经过AE处理,输出的隐变量和重建的图像都是固定的。

  3. 如果用训练集训练解码器,它会学习这些图像的固定分布,意味着解码器也只能接收符合这些分布的变量重建图像。

VAE:变分自动编码器

VAE和AE的区别在于其引入了分布,编码器不再输出隐变量,而是均值和方差两个值(注意此时Encoder只是输出两个网络值,而且期间计算并没有涉及到平均),然后又使用重参数化的技巧从标准正态分布中随机取了一个噪声,这个随机噪声结合刚刚的均值和方差就使得隐变量具有了随机性,相当于解码器从服从正态分布的隐变量集中随机采样生成图像。

这也就解释了为什么只有一个样本却能够计算出均值和方差:因为这里的均值和方差只是两个值,通过损失(KL损失和重建损失)使均值逐渐趋近于0,方差的对数趋近于0,这样的话隐变量的整体分布就趋近于标准正态分布。

# 构建编码器 均值和方差只是网络输出的两个值
x = Input(shape=(original_dim,))
h = Dense(intermediate_dim, activation='relu')(x)
z_mean = Dense(latent_dim)(h)
z_log_var = Dense(latent_dim)(h)  

重参数化中的随机噪声赋予了均值方差分布的意义

# 重参数化,重参数化中的随机噪声赋予了均值方差标准正态分布的意义
def sampling(args):
    z_mean, z_log_var = args
    epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim), mean=0., stddev=1.0)
    return z_mean + K.exp(z_log_var / 2) * epsilon  

两个loss的对抗理解:方差描述的是Z分布的离散程度,如果将方差理解为噪声强度,则KL损失的作用就是让模型生成时见到尽可能多的损失,参考下方评论:

VQ-VAE:变分自动编码器

VQ-VAE实际上是AE的变体,因为其编码器输出的是连续隐变量,而不是VAE的均值方差,VQ就是量化器,整体思想就是在AE输出连续变量后,将变量映射到一个Embedding层(codebook),这个codebook中的变量是离散的(即有限的,训练后固定的,个人理解codebook中变量的离散性并不是说值是整数)然后解码器处理这些离散变量生成图像。

原始自回归图像生成的缺点:

  1. 自回归文本生成因为文本自带先后顺序因此不用考虑先后顺序问题,但是图像是二维、三维图像,这里就需要先选择一个像素生成顺序,也就是自回归的顺序。例如(上到下左到右、中间到两边等)。

  2. 自回归模型是以前面的生成结果为条件预测当前生成结果,因此非常依赖前置结果,但是图像如果是逐像素预测的话前置结果会很多,例如128×128×3,这种长依赖导致自回归速度很慢且长依赖关系难以捕捉。

  3. 自回归生成只能处理离散变量,因此编码器结果也应该是离散的。

VQ-VAE的创新就是引入了codebook,编码器输出连续变量后,用最近邻搜索算法,得到与连续变量距离最近的codebook变量,将codebook中的这个变量输入到解码器,流程如下:

# ze是编码器输出的连续隐变量
ze = self.encoder(x)
embedding = self.vq_embedding.weight.data
N, C, H, W = ze.shape
K, _ = embedding.shape
embedding_broadcast = embedding.reshape(1, K, C, 1, 1)
ze_broadcast = ze.reshape(N, 1, C, H, W)
distance = torch.sum((embedding_broadcast - ze_broadcast)**2, 2)
# 最近邻搜索找到最相似的替代变量索引
nearest_neighbor = torch.argmin(distance, 1)
# 在codebook中找到索引对应的离散变量
zq = self.vq_embedding(nearest_neighbor).permute(0, 3, 1, 2)
# STE Straight-Through Estimator直通估计
decoder_input = ze + (zq - ze).detach()  

这种操作确实将编码器的输出离散化了,至于它为什么要映射到离散变量,VQ-VAE的作者是说离散的变量更适合图像生成(笔者还没完全理解)。

有一点需要注意的是,VQ-VAE本身不具备生成随机图像的能力,是PixelCNN/RNN赋予了随机生成的能力,否则VQ-VAE和AE一样只是压缩模型。

在loss反向传播的时候,因为解码器的直接输入是codebook中的离散向量Zq,因此需要一个方法将解码器对离散变量的更新反向映射到编码器的原始连续变量Ze上,于是采用了STE的方法:前向传播时,sg里的内容就是原本内容,即Ze(连续变量)+Zq-Ze=Zq(离散变量),反向传播时sg里的内容为0,变成了直接更新Ze。

codebook也是可训练的,codebook优化的目标应该是: 尽可能使得codebook中的每一个替代向量都能尽可能表示编码器输出的一类。比如【眼睛】这个的嵌入向量应该能替代编码器对所有风格的眼睛(凤眼、豹眼、桃花眼等)的编码输出。而且我们前面的反向传播中是用优化Ze替代优化Zq,这也要求两者不能相差很大。

更仔细一些,因为目标是让Embedding空间中的离散变量贴近编码器输出,因此应该是令Zq贴近Ze,而不是Ze贴近Zq(注意两者区别),实现的时候使两个的loss权重不同即可。下面loss设计中**应该γ<β,**在原论文中使用的是γ=0.25β。

以上就是对AE、VAE和VQ-VAE的简单理解,有误之处欢迎讨论指正,更深入的理解强烈推荐看这几篇博客以及代码:

  • 轻松理解 VQ-VAE:首个提出 codebook 机制的生成模型 | 周弈帆的博客
  • https://spaces.ac.cn/archives/6760
  • VQ的旋转技巧:梯度直通估计的一般推广 - 科学空间|Scientific Spaces
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号