参考文献:

[1] Kingma D P, Welling M. Auto-encoding variational bayes[J]. arXiv preprint arXiv:1312.6114, 2013.

[2] Doersch C. Tutorial on variational autoencoders[J]. arXiv preprint arXiv:1606.05908, 2016.

[3] 变分自编码器(一):原来是这么一回事 - 科学空间|Scientific Spaces

[4] 一个例子搞清楚(先验分布/后验分布/似然估计)_一个例子搞清楚(先验分布/后验分布/似然估计)-CSDN博客

[5] 直观解读KL散度的数学概念 - 简书 (jianshu.com)

[6] Kullback-Leibler Divergence Explained — Count Bayesie

[7] VAE变分自编码机详解——原理篇 - 知乎 (zhihu.com)

[8] 贝叶斯估计浅析 - xueliangliu - 博客园 (cnblogs.com)

目录

基本概念介绍

从 AutoEncoder 到 VAE

自编码器

变分自编码器做出的改变

VAE 原理思路入门

我们想做什么

变分下界引入与推导

变分下界的理解

VAE 模型架构介绍

根据潜在空间确定模型架构

对模型架构进行调整

重参数技巧

VAE 模型总结


本文章已于2025年11月24日进行修订加注,以前写的还是有很多遗漏的地方,感谢读者指出

基本概念介绍

上述文章有先后顺序,如果对相关概念不了解,推荐从上到下简单看一看。

从 AutoEncoder 到 VAE

让我们默认了您之前已经简单了解了编码器/解码器架构,这将更好理解下面的文章。当然,不了解也没关系

自编码器

  • 书面上,自编码器是一种无监督学习的神经网络结构,它试图学习输入数据的紧凑表示(编码),然后通过解码器将该表示还原为输入数据。自编码器包括一个编码器网络和一个解码器网络。

    5b78b35522a64b81acddac0bd45d6dd7.png

    • 编码器接收输入的数据后对其编码,我们可以理解为它在提取输入数据的关键信息。其生成的编码,也就是中间变量,我们称之为潜在表示,用 h 来表示。h 之后会进入解码器,得到最终的输出。即:

      • 编码器(Encoder):将输入数据映射到低维潜在空间,捕捉输入数据的重要特征。

      • 解码器(Decoder): 将编码的潜在表示映射回原始输入空间,重构原始数据。

变分自编码器做出的改变

  • 那么变分自编码器(VAE)和自编码器差别在哪里呢?我认为最大的改变就是潜在表示。在自编码器中,潜在表示是一个固定值,而 VAE 中,潜在表示则是一个不确定变量,或者换一个说法,是一个概率分布

  • 在 VAE 中,编码器不再只学习提取输入数据的编码信息,而是去学习获取输入数据的概率分布。在原始论文中,我们设定这一概率分布为正态分布,模型也就变成了这样:

    625fa51c44a542048619905da6b14d3b.png

    • 与此同时,中间量我们不再叫潜在变量,而是称为潜在空间(也称潜在分布,隐变量等),并使用 Z 来表示,用来凸显其是一个变化的量。

    • 解码器要做的工作就是如何从这样的概率分布中采样还原成最终的输出。

VAE 原理思路入门

我们从熟知的模型延伸到 VAE,从而对它的思路以及独特之处做了简单的了解。下面我们将从头介绍一下 VAE 的大体思路。

我们想做什么

  • 要做一个生成模型,首先我们看生成式模型的“梦想”。我们有一批数据样本 {x_1, …, x_n},其所在的集合我们用 X 来表示,我们本想根据 {x_1, …, x_n} 得到 X 的分布 p(x),如果能得到的话,那我直接根据 p(x) 来采样,就可以生成所有可能的 x 了(包括 {x_1, …, x_n} 以外的,这不就是在真正地“生成”新的数据么),这就算是一个终极理想的生成模型了。

  • 当然,这个“梦想”很难实现,于是我们整了一个迂回的策略。具体而言,我们可以借助一个简单的分布 p(z) ,建立其中 z 和 x 的对应关系,也就是 p(x|z),然后把所有的 z 全都拉过来积分,这样不就能求 p(x) 了嘛!如果真的有了这样的一个映射,那我们在推理的时候就可以先从简单分布中采样得到 z,然后走这个映射,然后就可以生成最终的目标 p(x|z) 了!这样的生成方式貌似也不错,整个过程就变成了z~p(z) → x~p(x|z)。于是乎,p(x) 的求法就变成了:


    eq?%5Cbegin%7Baligned%7D%20p%28X%29%26%20%3D%20%5Csum_Z%7Bp%28x%7Cz%29p%28z%29%7D%20%5C%5C%20%26%3D%5Cint%7Bp%28x%7Cz%29p%28z%29%7D%5Cspace%5Cmathrm%7Bd%7Dz%20%5Cend%7Baligned%7D
     

  • 然而,现实还是很骨感的。p(x|z) 这个分布通常是高维且包含复杂相互作用的,我们很难去求出这个似然。因此,直接通过积分来计算并最大化 p(x) 是不可能的,于是乎,我们就需要将这个问题简化、近似化,而我们简化问题的手段就是变分下界(Evidence Lower BOund,ELBO)

变分下界引入与推导

  • 那么 VAE 是怎么解决这个问题的呢?我们再看看原来的 p(X) 式子:


    eq?p%28X%29%3D%5Cint%7Bp%28x%7Cz%29p%28z%29%7D%5Cspace%5Cmathrm%7Bd%7Dz
     

  • 从训练的角度来说,我们需要最大化 p(x)。其中,p(z) 是我们找的一个简单分布,那自然是可知的,那么 p(x|z) 我们怎么求?p(x|z) 是已知潜在表示 z 求对应的 x,如果直接根据公式求 p(x) 的话我们需要列举所有的 z 并做积分,这肯定是不可能的。那这 z 应该从哪里来?好在我们可以用手上已有的数据去得到部分的 z 。具体而言,我们可以用已有的样本数据集 {x_1, …, x_n} 去得到基于已有样本的 z ,也即后验分布 p(z|x),从而我们可以根据这些部分 z ,去近似求取 p(x),或者从训练角度来说,去最大化 p(x)
  • 实际上,有关“为什么使用这些部分的 z 去最大化 p(x) 是有效的”这个问题,这里还有一种理解方式。我们可以说,对于 z~p(z) 的大部分采样,也就是大部分 z,对于 p(x) 的积分计算都没有贡献,也就是它们的 p(z|x) 都近乎为0,根本就跟 x 没什么关系。我们举个例子。如果定义 Z 是工具集合,目标 X 是职业集合,我自然可以说已知菜刀,厨师的概率会比较大,即 p(厨师|菜刀) 的值是很可观的。这意味着菜刀对于 p(厨师) 的积分计算贡献很大。究其本质原因,厨师本来就经常使用菜刀,即 p(菜刀|厨师) 是大的,这才使得菜刀对厨师分布的计算贡献大。此时,我使用菜刀以及其他厨具去近似计算厨师的分布,这才是有效的,因为他们对厨师的贡献占据了绝大部分。其余的例如什么螺丝刀、雨伞、梯子这类,p(厨师|螺丝刀/雨伞/梯子) 应该很小吧?这当然对最终的厨师分布积分计算没啥用,因此我们为了计算方便,去舍弃这些工具也是合理的,毕竟我们很难列举完世界上所有的工具。当然,这个假设是建立在工具 Z 自己的分布是个均匀分布,即所有先验 p(z) 是相同的,这里也为后续的 ELBO 计算埋下了伏笔。
  • 所以说,再次切换到原来的场景中,我们使用已有的样本数据集 {x_1, …, x_n} 去得到基于已有样本的 z ,这个过程本身就是在得到 p(z|x) 大的 z ,这些得来的 z 本身就对最终的 p(x) 贡献非常大,和 x 是更相关的,因此我们使用这些从后验分布中得到的 z 去进行训练是有效的、高效的。
  • 讲到现在,我们提到了 p(z|x) 和 p(x|z) ,我们怎么去通过神经网络去实现这些呢?欸!前者是根据 x 求 z,这不就是 Encoder 么?后者是根据 z 求 x,这不就是 Decoder 么?我们很自然就可以引入编解码器架构。首先看 p(z|x),我们肯定没法计算真正的后验分布,我们只能使用已有的有限的样本数据集 {x_1, …, x_n} 通过 Encoder 去得到 z,这建模出来的是一个近似后验分布 q,是近似代替真实后验分布 p(z|x),式子如下:


eq?q%28z%7Cx%29
 

  • 好了,如此一来我们就可以根据这个近似的分布 q ,采样对应的 z~q,去走 Decoder ,求取 E_{z~q}[ log p(x|z) ] 了。不过,我们的最终目的是通过训练最大化 p(x) ,那我们应该如何利用这两个式子来最大化 p(x) 呢?我们在这里使用 KL 散度来将这个近似后验分布同我们要求的联系起来。由 KL 散度公式,我们可以有下式 :


    eq?D%5Bq%28z%7Cx%29%7C%7Cp%28z%7Cx%29%5D%20%3D%20%5Cmathbb%7BE%7D_%7Bz%5Csim%20q%7D%5B%5Clog%7Bq%28z%7Cx%29%7D%20-%20%5Clog%7Bp%28z%7Cx%29%7D%5D
     

  • 使用贝叶斯公式转化右式的 p(z|x),式子变形如下:


    eq?%5Cbegin%7Baligned%7D%20D%5Bq%28z%7Cx%29%7C%7Cp%28z%7Cx%29%5D%20%26%3D%20%5Cmathbb%7BE%7D_%7Bz%5Csim%20q%7D%5B%5Clog%7Bq%28z%7Cx%29%7D%20-%20%5Clog%7Bp%28z%7Cx%29%7D%5D%20%5C%5C%20%26%3D%5Cmathbb%7BE%7D_%7Bz%5Csim%20q%7D%5B%5Clog%7Bq%28z%7Cx%29%7D%20-%20%5Clog%7B%5Cfrac%7Bp%28x%7Cz%29*p%28z%29%7D%7Bp%28x%29%7D%7D%5D%20%5C%5C%20%26%3D%5Cmathbb%7BE%7D_%7Bz%5Csim%20q%7D%5B%5Clog%7Bq%28z%7Cx%29%7D%20-%20%5Clog%7Bp%28x%7Cz%29-%5Clog%7Bp%28z%29%7D+%5Clog%7Bp%28x%29%7D%7D%5D%20%5C%5C%20%5Cend%7Baligned%7D
     

  • p(X) 是确定量,我们将其抽出,并进行移项:


    eq?%5Cbegin%7Baligned%7D%20D%5Bq%28z%7Cx%29%7C%7Cp%28z%7Cx%29%5D%20%26%3D%5Cmathbb%7BE%7D_%7Bz%5Csim%20q%7D%5B%5Clog%7Bq%28z%7Cx%29%7D%20-%20%5Clog%7Bp%28x%7Cz%29%7D-%5Clog%7Bp%28z%29%7D+%5Clog%7Bp%28x%29%7D%5D%20%5C%5C%20%26%3D%5Cmathbb%7BE%7D_%7Bz%5Csim%20q%7D%5B%5Clog%7Bq%28z%7Cx%29%7D%20-%20%5Clog%7Bp%28x%7Cz%29%7D-%5Clog%7Bp%28z%29%7D%5D%20+%20%5Clog%7Bp%28x%29%7D%20%5C%5C%20%5Cend%7Baligned%7D
     


    eq?%5Clog%7Bp%28x%29%7D%20-%20D%5Bq%28z%7Cx%29%7C%7Cp%28z%7Cx%29%5D%20%3D%20%5Cmathbb%7BE%7D_%7Bz%5Csim%20q%7D%5B-%5Clog%7Bq%28z%7Cx%29%7D%20+%20%5Clog%7Bp%28x%7Cz%29%7D%20+%5Clog%7Bp%28z%29%7D%5D%20%5C%5C%20%5Clog%7Bp%28x%29%7D%20-%20D%5Bq%28z%7Cx%29%7C%7Cp%28z%7Cx%29%5D%20%3D%20%5Cmathbb%7BE%7D_%7Bz%5Csim%20q%7D%5B%5Clog%7Bp%28x%7Cz%29%7D%5D%20-%20%5Cmathbb%7BE%7D_%7Bz%5Csim%20q%7D%5B%5Clog%7Bq%28z%7Cx%29%7D%20-%20%5Clog%7Bp%28z%29%7D%5D%20%5C%5C
     

  • 再使用 KL 散度公式进行重写,我们就得到了这个式子:


    eq?%5Clog%7Bp%28x%29%7D%20-%20D%5Bq%28z%7Cx%29%7C%7Cp%28z%7Cx%29%5D%20%3D%20%5Cmathbb%7BE%7D_%7Bz%5Csim%20q%7D%5B%5Clog%7Bp%28x%7Cz%29%7D%5D%20-%20D%5Bq%28z%7Cx%29%7C%7Cp%28z%29%5D
     

  • 由于 KL 散度非负,因此我们可以说:


    eq?%5Clog%7Bp%28x%29%7D%20%5Cge%20%5Cmathbb%7BE%7D_%7Bz%5Csim%20q%7D%5B%5Clog%7Bp%28x%7Cz%29%7D%5D%20-%20D%5Bq%28z%7Cx%29%7C%7Cp%28z%29%5D
     

  • 上面式子的 RHS(右式)很明显可以算是 log p(x) 的下界,我们一般称其为变分下界(Variational Lower Bound,ELBO)。实际上,我们的目标和 ELBO 的差距就是近似后验分布 q(z|x) 和真实后验分布 p(z|x) 的差距。至此,我们将 “使 p(x) 最大化” 这一问题转化为了将变分下界最大化

变分下界的理解

  • 既然目标是让变分下界最大化,那么我们就需要仔细研究一下这个变分下界。我们不难看出,变分下界主要由两部分组成:

    • z 在 q(z|x) 的分布下,x given z 的概率分布的期望值

    • z given x 的近似后验分布与 z 的真实分布(先验分布)的 KL 散度

  • 首先是第一项,要想最大化 ELBO,那我们自然是想让第一项尽可能的大,也就是 x given z 的概率分布期望值更大。这很明显就是由 z 到 x 重组的过程,也就是 AutoEncoder 中的 Decoder。模型想做的是尽可能准确地重组。

  • 其次是第二项,要想最大化 ELBO,我们自然需要让这项 KL 散度尽可能小,也就是 z 的近似后验分布 q(z|x) 尽可能接近于 z 的先验分布 p(z)!这一项我们可以理解为,模型想让 z 尽可能避免过拟合(坍缩成固定值),别让模型为了重建的质量而直接无视 p(z)。这样就可以保证 VAE 的最大特色,即编码是一个概率分布,而不是普通 AE 那样的点。

VAE 模型架构介绍

根据潜在空间确定模型架构

  • 理解了我们的核心公式和要做的事情后,我们就可以着手搭建模型了。首先我们需要做的是确定 z。VAE 是如何去描述潜在空间 z 的呢?它认为,z 根本没有一种合适的阐述方法,而是直接假定 z 的样本可以从简单的分布中抽取,即标准正态分布 N(0, I),其中 I 是单位矩阵。因为,任何 d 维度的分布都可以用一组 d 个服从正态分布的变量,通过足够复杂的函数进行映射从而生成。如此一来,无论整个编码空间是什么样子的,我们都可以用一个一个的小的正态分布的变量去进行叠加,从而对整个编码隐空间进行拟合。

    其中的原理可以参考[1606.05908] Tutorial on Variational Autoencoders (arxiv.org)这篇论文。此外,也有采用正态分布可以更方便 KL 散度计算的说法。

  • 那么怎么找到映射函数,并获取其输出,也就是正态分布的平均值和方差?这种复杂的任务自然是交给神经网络学习啦,我们可以使用两个神经网络分别输出平均值和标准差,如下:


    \mu = f_1(x) \\ \log \sigma^2 = f_2(x)
     

    • 其中 f_1 和 f_2 分别代表两个独立的神经网络

    • 选择拟合 log σ^2 是因为原本 σ^2 为非负,需要加激活函数,如果去拟合其 log 值就不用加激活函数了。

  • 这下我们就可以将我们的近似后验分布 q 描述为下面的公式:


    eq?q%28z%7Cx%29%20%3D%20%5Cmathcal%7BN%7D%28z%3B%5Cmu%2C%20%5Csigma%20%5E2%5Cmathbf%7BI%7D%29
     

    • 其中,μ 和 σ^2 就是通过两个不同的神经网络,根据样本学习到的平均值和方差。

    • I 为单位矩阵。

  • 好的,那模型貌似就很简单了。我们来看看整个模型:

    • 首先,样本进入 Encoder,Encoder 学习并输出潜在空间的平均值和标准差,得到潜在空间 Z,

    • 然后再从潜在空间中采样得到 z,并进入 Decoder,Decoder 根据采样进行重构,重新生成样本。

    • 根据我们的目标函数,只需要保证重构尽可能准确 + 潜在空间接近标准正态分布即可,即 ELBO 最大化。那么我们可以直接对 ELBO 进行取反作为我们的损失函数:


      eq?%5Cmathcal%7BL%7D%20%3D%20-%20%5Cmathbb%7BE%7D_%7Bz%5Csim%20q%7D%5B%5Clog%7Bp%28x%7Cz%29%7D%5D%20+%20D%5Bq%28z%7Cx%29%7C%7Cp%28z%29%5D
       

  • 根据上面的理论,我们可以画出我们的模型架构图:

    2b16db0d2d094befa9c53231e191e960.png

  • 好像看似很完美?那就开始训练吧!损失函数就是 ELBO 取反。根据我们的损失函数,我们需要对比 x 和 x',即原样本和生成样本。但是随即问题就出现在了我们的眼前:如何对比?我们来看看一些常规的想法:

    • KL 散度?KL 散度作为一种常见的比较两种分布相近程度的方法,在这里却失去了作用。其原因在于 KL 散度是根据两个概率分布的表达式来算它们的相似度的,然而我们只有一批从构造的分布 Z 采样重构而来的数据 {x_1', x_2' ,…, x_n'},还有一批从真实的分布采样而来的数据(也就是训练集){x_1, x_2, …, x_n},我们只知道样本本身,没有分布表达式,当然也就没有方法算KL散度。

    • 直接作比较?那既然我们有了生成的数据集和训练集,为什么不能直接算 D(某种距离函数) 这样的值直接进行比较呢?这样也有困难!其原因在于我们并不知道哪一个生成的样本对应着哪一个真实样本,也就是我们并不知道生成样本集和训练集的对应关系,x_1' 不一定对应着 x_1,自然就不能马马虎虎直接算 D(x_k', x_k)。

  • 坏了,这些常规的想法都不行!那我们应该怎么办?

对模型架构进行调整

  • 遇到问题我们就去解决问题。我们来看看同为生成模型,GAN(生成式对抗网络)是如何解决的:

    • GAN 主要由两部分:生成器判别器两部分组成。通过一个生成器网络生成样本,同时通过一个判别器网络对生成的样本进行判别。训练时,我们将真样本也给到判别器网络,让其进行训练判别能力。而生成器的训练目标就是能尽可能欺骗过判别器,让它识别不出来自己生成的样本。

    • 也就是说,GAN的生成过程是一个对抗性的过程,生成器和判别器相互竞争,最终生成器试图生成逼真的样本,判别器试图准确地区分真实和生成的样本。

      93e3a040865d4fab8d6dc3f0938403de.png
  • GAN 的思路很简单。既然比较有困难,那我直接把比较的方法也一并训练出来不就行了?这里 GAN 训练出来的比较的方法就是判别器

  • 那么 VAE 呢?VAE 则不是这样粗暴,而是采用了一种精妙的迂回方式。既然直接比较是找不到对应关系的,那我干脆就一对一进行训练,直接一个真实样本训练一个潜在空间,这样重构产生的样本自然就对应着它的老爸啦。修改后的模型示意图如下:

    afc22ec75fc24150b9704e001e9cc458.png

  • 如此改动后,我们就有了专属于每一个 x^{(i)} 的正态分布,从中采样并进行重构的自然就是对应的 Z^i,如此我们就可以直接进行比较。于是乎,我们的损失函数就可以进一步完善成下式:


    eq?%5Cmathcal%7BL%7D%28%5Ctheta%2C%20%5Cphi%3B%20x%5E%7B%28i%29%7D%29%20%3D%20-%20%5Cmathbb%7BE%7D_%7Bz%5Csim%20q_%5Cphi%28z%7Cx%5E%7B%28i%29%7D%29%7D%5B%5Clog%7Bp_%5Ctheta%28x%5E%7B%28i%29%7D%7Cz%29%7D%5D%20+%20D_%7BKL%7D%5Bq_%5Cphi%28z%7Cx%5E%7B%28i%29%7D%29%7C%7Cp%28z%29%5D
     

    • 其中,θ 和 φ 分别是 Decoder 和 Encoder 模型参数

    • 我们针对每一个样本都单独计算其独有的均值和标准差,构造属于其专有的潜在空间。

  • 我们也重新对我们的近似后验分布进行描述,由于在损失函数中,我们需要其对数形式,所以我们将对数形式添加上去,最终的公式如下:


    eq?%5Clog%20q%28z%7Cx%5E%7B%28i%29%7D%29%20%3D%20%5Clog%20%5Cmathcal%7BN%7D%28z%3B%5Cmu%5E%7B%28i%29%7D%2C%20%5Csigma%5E%7B2%28i%29%7D%5Cmathbf%7BI%7D%29
     

  • 这样,我们就得到了 VAE 的最终架构。实际上,VAE 最大特点也在这个改动之中,那就是它作为一个编解码器,它对样本的编码不再是和普通编解码器那样的一个“点”,而是一个概率分布,属于这个样本的概率分布。

  • 此外,有一个很有意思的地方在于损失函数的第二项。我们在之前的变分下界解析中曾经提到,这一项主要目的是为了防止潜在空间过拟合。当知晓了模型架构后,我们重新来看损失函数。第一项很自然的,就是重构项和对应的样本之间的差距,越小越好。然而,在整个模型中,潜在表示,也就是重构材料 z_k 是采样得到的,并不是像常规 AutoEncoder 那样由 Encoder 直接计算得到,因此这部分也就相当于噪声,它的随机性在干扰重构的过程。因此在训练过程中,为了更好重构,模型会尽可能让潜在空间的方差变为0,让潜在空间退化成潜在点,和目标样本直接一对一, 进而让 VAE 退化成普通的 AutoEncoder。缺少了变化,所谓的“生成式模型”可就名存实亡了。这可万万不能!此时,损失函数的第二项就起到了作用,它让潜在空间的后验分布逼近标准正态分布 N(0, I),从而避免了随机性消失,也就是方差变成0的情况,相当于对训练过程的正则化。因此,我们通常称损失函数中:


    eq?-%20%5Cmathbb%7BE%7D_%7Bz%5Csim%20q_%5Cphi%28z%7Cx%5E%7B%28i%29%7D%29%7D%5B%5Clog%7Bp_%5Ctheta%28x%5E%7B%28i%29%7D%7Cz%29%7D%5D
     

    这一项为重构项(Reconstruction Term),而另外一项:


    eq?D_%7BKL%7D%5Bq_%5Cphi%28z%7Cx%5E%7B%28i%29%7D%29%7C%7Cp%28z%29%5D
     

    这一项为正则化项(Regularization Term)

重参数技巧

  • 貌似万事大吉了?等等!这能训练吗?整个过程中,你可是从一个概率分布(潜在空间)中采样才得到潜在表示 z 的,而恰恰“采样”这个操作是不可导的,这也就导致在训练过程中无法进行反向传播,就无法训练了,怎么办呢?

  • 为了解决这个问题,VAE 使用了重参数技巧(reparameterization trick)。我们重新观察我们的潜在空间,也就是后验分布 q(z|x),利用正态分布标准化,我们可以得到下面的结论:


    z \sim \mathcal{N}(\mu, \sigma^2) \Rightarrow \frac{z-\mu}{\sigma} \sim \mathcal{N}(0, \mathbf{I})
     

  • 即,(z − μ) / σ 服从均值为 0,方差为 1 的标准正态分布。因此我们引入噪声项 ε,令 ε = (z − μ) / σ,从而将原本 从 N(μ, σ^2) 中采样得到 z 的操作转换成了 从 N(0, I) 中采样一个 ε,令 z = μ + ε*σ。如此一来,梯度计算可以通过 μ 和 σ 直接传递,而不再涉及对随机采样的梯度。

VAE 模型总结

  • 现在我们整体看一下整个 VAE 的模型结构,实际上它就是从普通的自编码器发展过来的变种。普通的 AutoEncoder,其 Encoder 生成的是有关样本的“信息”,也就是潜在表示,这样算出来的值是确定的。而 VAE 的 Encoder 却生成的是一个潜在空间,更具体地说是生成专属于当前样本的平均值和方差,这样算出来的“值”是不确定的。而从这样的潜在空间采样后再进行重构,这一过程本身就相当于“给潜在表示添加噪声”,相当于对 Encoder 的正则化,这样就使得 Decoder 能够对噪声具有一定的鲁棒性。

  • 从这个角度来看,生成方差的那个神经网络又何尝不可以理解为对噪声大小的调节器呢?方差越大,采样的结果就会越分散,这就变相增加了重构的难度;方差越小,采样的结果就越集中,就会降低重构的难度。引用变分自编码器(一):原来是这么一回事 - 科学空间|Scientific Spaces这篇文章中的内容来说,就是:

    当decoder还没有训练好时(重构误差远大于KL loss),就会适当降低噪声(KL loss增加),使得拟合起来容易一些(重构误差开始下降);反之,如果decoder训练得还不错时(重构误差小于KL loss),这时候噪声就会增加(KL loss减少),使得拟合更加困难了(重构误差又开始增加),这时候decoder就要想办法提高它的生成能力了。

    14ed54ba823b4b048e9b2a8d0ebe971f.png
  • 另外,如果我们更加深入去看 AE 和 VAE 的差别,你就会发现,普通的 AE 几乎对隐空间没有任何约束,它只是简单地将每个输入映射到一个固定的点(向量)在隐空间中,这些点之间没有必然的几何关系 - 相似的输入可能被映射到空间中很远的点,而不相似的输入可能被映射到很近的点。并且,隐空间是**高度不连续**的,充满了"空洞"和"空白区域"。这意味着当你从隐空间中随机采样一个点时,这个点极大概率不对应任何训练时见过的编码。由于解码器只"见过"训练时那些特定的编码点,它不知道如何处理这些陌生的点,结果就是最终 AE 会生成出无意义的、模糊的、或者像噪声一样的输出
  • 反观 VAE,VAE 的编码器不是输出一个单一的点,而是输出一个概率分布(原论文是一个高斯分布,由均值μ和方差σ描述)。损失函数中的正则项强制要求每个样本编码后的分布 q(z|x) 都向同一个先验分布 p(z) 看齐。这就让 VAE 的整个隐空间(注意,不是每个单独编码对应的隐空间,而是指的是整个编码隐空间)结构化、连续、有意义,所有数据点对应的隐分布都被“拉”向同一个中心,并且理论上语义上相似的样本,它们的隐分布会在隐空间中彼此靠近。并且,由于每个编码都是一个分布而不是一个点,这些分布之间会自然地重叠和融合,从而填满了普通AE中存在的“空洞”。隐空间从一个散乱的点集,变成了一个连续、平滑的流形。这样,VAE 就**学习到了整个局部区域**的映射关系,就可以进行可靠的生成了。

Logo

更多推荐