变分自编码器解析

概述

译自https://jaan.io/what-is-variational-autoencoder-vae-tutorial/

在讨论变分自动编码器时,为什么深度学习研究人员和概率机器学习人员会感到困惑? 什么是变体自动编码器? 为什么这个词会引起混乱?

这是因为神经网络和概率模型在基本概念和描述语言上存在差异。此教程的目标是弥合这一思想鸿沟,允许在这些领域之间进行更多的协作和讨论,并提供一致的实现方法。

变分自编码器用起来很酷,让我们能够设计复杂的数据生成模型,并将其应用于大型数据集。它可以生成虚构的名人面孔或者高分辨率的数字艺术品图像。这些模型在图像生成和强化学习中获得了非常好的效果。

下面本文将从神经网络和概率模型两个角度对其进行讲解。

神经网络角度

以神经网络语言描述的话,VAE包含编码器、解码器和损失函数三部分。编码器将数据压缩到隐空间\((z)\)中。 解码器根据隐状态\(z\)重建数据。

编码器是一个神经网络,它的输入是数据点\(x\),输出是隐状态\(z\),它的参数\(\theta\)包括权重和偏置。为了更具体地说明,假设\(x\)是一副\(28\times 28\)的手写数字图片,通常被重塑成784维的向量。编码器需要将728维的数据\(x\)编码到隐空间\(z\),而且\(z\)的维度要比784小很多。这通常被称为“瓶颈”,因为编码器必须学习将数据有效压缩到此低维空间的方法。假设编码器表示为\(q_{\theta}(z|x)\),我们注意到较低维的隐空间是随机的:编码器将参数输出到\(q_{\theta}(z|x)\),这是高斯概率密度,然后我们可以从该分布中采样以获得\(z\)的噪声值。

解码器也是一个神经网络,它的输入是隐状态\(z\),输出是数据的概率分布,它的参数\(\phi\)也包括权重和偏置,可以把解码器表示为\(p_{\phi}(x|z)\)。还是以上面例子讲解,假设每个像素取值是0或者1,一个像素的概率分布可以用伯努利分布表示。因此解码器输入\(z\)之后,输出784个伯努利参数,每个表示图中的一个像素是取0还是取1。原始784维图像\(x\)的信息是无法获取的,因为解码器只能看到压缩的隐状态\(z\)。这意味着存在信息丢失问题。

变分自编码器的损失函数是带正则项的负对数似然函数。因为所有数据点之间没有共享表示,因此每个数据点的损失\(l_i\)是独立的,总损失\(\mathcal{L}=\sum_{i=1}^N l_i\)是每个数据点损失之和。而数据点\(x_i\)的损失\(l_i\)可以表示为:

\[l_i(\theta,\phi)=-\mathbb{E}_{z \sim p_{\theta}(z|x_i)}[\log_{p_{\phi}}(x_i|z)] + KL(p_{\theta}(z|x_i)||p(z))
\]

第一项是重构损失,或者说是数据点\(x_i\)负对数似然的期望。第二项KL散度是正则项,它衡量了分布\(p\)和\(q\)的近似程度,也就是用\(q\)表示\(p\)时有多少信息丢失了。

在变分自编码器中,\(p(z)\)被指定为标准正态分布,也就是\(p(z)=\text{Normal}(0,1)\)。如果编码器输出的\(z\)不服从标准正态分布,将会在损失函数中对编码器施加惩罚。正则化用来保持每个手写数字的隐状态\(z\)充分多样但又具有意义。如果不使用的话,编码器可能简单地将每个数据点映射到欧几里德空间的不同区域,这会出现问题。比如有两个包含数字2的手写图片\(2_{a}\)和\(2_b\),它们可能会编码成非常不同的隐状态\(z_a\)和\(z_b\)。而我们希望在隐空间中相同数字的隐状态应该是彼此靠近的,因此需要用正则项进行约束。

概率模型角度

现在,让我们忘掉所有深度学习和神经网络知识,从概率模型的角度重新看变分自编码器。在最后,我们仍然会回到神经网络。

在概率模型框架下,变分自编码器中数据点\(x\)和隐变量\(z\)的联合概率表示为\(p(x,z)=p(x|z)p(z)\)。此时,对于每个数据点\(i\),生成过程可以表示如下:

  • 采样隐变量\(z_i \sim p(z)\)
  • 采样数据点\(x_i \sim p(x|z)\)

这可以用概率图模型表示;

这就是我们从概率模型角度讨论变分自编码器时的核心问题。隐状态\(z\)从先验分布\(p(z)\)中采样得到,然后数据点\(x\)从以\(z\)为条件的分布\(p(x|z)\)中产生。整个模型定义了数据和隐状态的联合分布\(p(x,z)=p(x|z)p(z)\),对于手写数字而言,\(p(x|z)\)就是伯努利分布。

现在,我们可以考虑如何根据给定的观测数据推断出隐变量,或者说计算后验概率\(p(z|x)\)。根据贝叶斯定理:

\[p(z|x)=\frac{p(x|z)p(z)}{p(x)}
\]

考虑分母\(p(x)\),它可以通过\(p(x)=\int p(x|z)p(z)dz\)计算。不幸的是,该积分需要指数时间来计算,因为需要对所有隐变量进行计算。 因此,我们需要近似该后验分布。

变分推断使用分布族\(q_{\lambda}(z|x)\)来近似后验分布,参数\(\lambda\)指示具体分布族。比如,如果\(q\)是高斯分布的话,\(\lambda\)就是每个数据点隐状态的均值和方差\(\lambda_{x_i}=(\mu_{x_i},\sigma_{x_i}^2)\)。

那么怎么知道用分布\(q(z|x)\)近似真实的后分布\(p(z|x)\)到底好不好呢?我们可以用KL散度来衡量:

\[KL\left(q_{\lambda}(z|x)||p(z|x)\right) = \\ \mathbb{E}_q[\log q_{\lambda}(z|x)] - \mathbb{E}_q[\log p(x,z)] + \log p(x)
\]

我们的目标是找到使得KL散度最小的变分参数\(\lambda\)。最优的后验分布就可以表示为:

\[q_{\lambda^*}(z|x)=\arg\min_{\lambda}KL\left(q_{\lambda}(z|x)||p(z|x)\right)
\]

但是这依然无法进行计算,因为仍然会涉及到\(p(x)\),我们还需要继续改进。引入下面这个函数:

\[ELBO(\lambda)= \mathbb{E}_q[\log p(x,z)] - \mathbb{E}_q[\log q_{\lambda}(z|x)]
\]

我们可以将ELBO与上面的KL散度计算公式结合,可以得到:

\[\log p(x)= ELBO(\lambda) + KL\left(q_{\lambda}(z|x)||p(z|x)\right)
\]

由于KL散度始终是大于等于0的,这意味着最小化KL散度等价于最大化ELBO。ELBO(Evidence Lower BOund)让我们能够对后验分布进行近似推断,可以从最小化KL散度中解脱出来,转而最大化ELBO。而后者在计算上是比较方便的。

在变分自编码器模型中,每个数据点的隐状态\(z\)是独立的,因此ELBO可以被分解成所有数据点对应项之和。这使得我们可以用随机梯度下降来更新共享参数\(\lambda\)。每个数据点的ELBO表示如下:

\[ELBO_i(\lambda)=\mathbb{E}q_{\lambda}(z|x_i)[\log p(x_i|z)] - KL(q_{\lambda}(z|x_i)||p(z))
\]

现在可以再用神经网络来进行描述了。我们使用一个推断网络(或编码器)近似后验\(q_{\theta}(z|x,\lambda)\),该推断网络输入数据\(x\)然而输出参数\(\lambda\)。再使用一个生成网络(或解码器)参数化\(p(x|z)\),该生成网络输入隐状态和参数,输出数据分布\(p_{\phi}(x|z)\)。\(\theta\)和\(\phi\)是推断网络和生成网络的参数。此时我们可以使用这两个网络来重写ELBO:

\[ELBO_i(\theta,\phi)=\mathbb{E}q_{\theta}(z|x_i)[\log p_{\phi}(x_i|z)] - KL(q_{\theta}(z|x_i)||p(z))
\]

可以看到,\(ELBO_i(\theta,\phi)\)和我们之前从神经网络角度提到的损失函数就差一个符号,即\(ELBO_i(\theta,\phi)=-l_i(\theta,\phi)\)。我们仍然可以将KL散度看作正则项,将期望看作重构损失。但是概率模型清楚解释了这些项的意义,即最小化近似后验分布\(q_{\lambda}(z|x)\)和模型后验分布\(p(z|x)\)之间的KL散度。

模型参数呢?我们忽略了这一点,但这很重要。术语“变分推断”通常是指相对于参数\(\lambda\)最大化ELBO。我们还可以相对于模型参数\(\phi\)最大化ELBO。这项技术称为变分EM(期望最大化),因为我们正在相对于模型参数最大化数据的期望对数似然。

这就是全部了,我们遵循了变分推断的方法,定义了:

  • 概率模型\(p\)表示隐变量和数据的分布
  • 隐状态的变分分布族\(q\),用于近似后验分布

然后我们利用变分推断算法学习变分参数(在ELBO上用梯度上升学习\(\lambda\)),利用变分EM算法学习模型参数(在ELBO上用梯度上升学习\(\phi\))。

实验

现在可以模型进行一些实验了,两种方式衡量实验进度:从先验分布或后验分布采样。为了更好地解释学习到的潜在空间,我们可以可视化隐变量的后验分布\(q_{\lambda}(z|x)\)。

可以参考作者给出的代码:https://github.com/altosaar/variational-autoencoder。

Mean-field推断和amortized推断

这个问题对我来说非常令人困惑,对于来自深度学习背景的人来说,它可能会更加令人困惑。在深度学习中,我们考虑输入和输出,编码器和解码器以及损失函数。在学习概率建模时,这可能导致模糊,不精确的概念。

让我们讨论Mean-field推断和amortized推断的不同之处。这是我们在进行近似推断以估计隐变量的后验分布时所面临的选择。这可能涉及到各种问题:我们是否有大量数据?我们有大量计算资源吗?每个数据点的隐变量是局部独立的,还是全局共享的?

Mean-field变分推断是指在没有共享参数的情况下对\(N\)个数据点进行分布推断:

\[q(z)=\prod_i^N q(z_i;\lambda_i)
\]

这意味着每个数据点都有自由参数\(\lambda_i\)(例如对于高斯隐变量,\(\lambda_i =(\mu_i,\sigma_i)\))。对于新数据点,我们需要针对其mean-field参数\(\lambda_i\)最大化ELBO。

amortized推断是指“摊销”数据点之间的推断成本。一种方法是在数据点之间共享(摊销)变分参数\(\lambda\)。例如,在变分自动编码器中,推断网络的参数\(\theta\),这些全局参数在所有数据点之间共享。如果我们看到一个新的数据点并想看一下它的近似后验\(q(z_i)\),我们可以再次运行变分推断(最大化ELBO直到收敛),或者直接使用共享参数。 与Mean-field变分推断相比,这可能是一个优势。

哪一个更灵活呢?Mean-field变分推断严格来说更具表达性,因为它没有共享参数。每个数据点独立的参数\(\lambda_i\)可以确保近似后验最准确。但另一方面,通过在数据点之间共享参数可以限制分布族的容量或表示能力(例如,使用在数据之间共享权重和偏差的神经网络)。

重参数化技巧

实现变分自编码器的最后一件事是如何对随机变量的参数求导数。如果给定从分布\(q_{\theta}(z|x)\)中得出的\(z\),并且我们想要对\(\theta\)取\(z\)函数的导数呢?此时采样不可导,进而导致模型无法反向传播。

对于某些分布,可以以巧妙的方式重新设置样本的参数,也就是重参数化。例如,在均值\(\mu\)和标准偏差\(\sigma\)的正态分布变量中,我们可以像这样从中采样:

\[z = \mu + \sigma \odot \epsilon
\]

其中\(\epsilon \sim Normal(0,1)\)。首先从从均值为0,标准差为1的高斯分布中采样,再放缩平移得到\(z\)。这样从\(\epsilon\)到\(z\)只涉及了线性操作(平移缩放),采样操作在神经网络计算图之外。

这张图表示了重参数化的形式,其中圆是随机节点,菱形是确定性节点。

由于水平有限,文中难免出现部分错误,还望交流指出!

原文地址:https://www.cnblogs.com/weilonghu/p/12567793.html

时间: 2024-07-30 13:13:47

变分自编码器解析的相关文章

变分自编码器(Variational Autoencoder, VAE)通俗教程

最佳阅读体验请前往原文地址:变分自编码器(Variational Autoencoder, VAE)通俗教程—— 作者:邓范鑫 1. 神秘变量与数据集 现在有一个数据集DX(dataset, 也可以叫datapoints),每个数据也称为数据点. X是一个实际的样本集合,我们假定这个样本受某种神秘力量操控,但是我们也无从知道这些神秘力量是什么?那么我们假定这股神秘力量有n个,起名字叫power1,power2,…,powern吧,他们的大小分别是z1,z2,…,zn,称之为神秘变量表示成一个向量

变分自编码器:原来是这么一回事

链接:https://kexue.fm/archives/5253 分布变换 通常我们会拿VAE跟GAN比较,的确,它们两个的目标基本是一致的——希望构建一个从隐变量Z生成目标数据X的模型,但是实现上有所不同.更准确地讲,它们是假设了Z服从某些常见的分布(比如正态分布或均匀分布),然后希望训练一个模型X=g(Z),这个模型能够将原来的概率分布映射到训练集的概率分布,也就是说,它们的目的都是进行分布之间的变换. 生成模型的难题就是判断生成分布与真实分布的相似度,因为我们只知道两者的采样结果,不知道

Variational Auto-encoder(VAE)变分自编码器-Pytorch

import os import torch import torch.nn as nn import torch.nn.functional as F import torchvision from torchvision import transforms from torchvision.utils import save_image # 配置GPU或CPU设置 # Device configuration device = torch.device('cuda' if torch.cud

【Learning Notes】变分自编码(Variational Auto-Encoder,VAE)

近年,随着有监督学习的低枝果实被采摘的所剩无几,无监督学习成为了研究热点.VAE(Variational Auto-Encoder,变分自编码器)[1,2] 和 GAN(Generative Adversarial Networks) 等模型,受到越来越多的关注. 笔者最近也在学习 VAE 的知识(从深度学习角度).首先,作为工程师,我想要正确的实现 VAE 算法,以及了解 VAE 能够帮助我们解决什么实际问题:作为人工智能从业者,我同时希望在一定程度上了解背后的原理. 作为学习笔记,本文按照由

变分自编码

一 变分自编码(Variational Auto-Encoder) 变分自编码不再是学习样本的个体,而是学习样本的规律,这样训练出来的自编码不单具有重构样本的功能,还具有仿照样本的功能. 变分自编码,其实就是在编码过程中改变了样本的分布("变分"可以理解为改变分布).前面所说的"学习样本的规律",具体指的就是样本的分布,假设我们知道样本的分布函数,就可以从这个函数中随便的取一个样本,然后进行网络解码层向前传导,这样就可以生成一个新的样本. 为了得到这个样本的分布函数

变分自动编码器

变分自动编码器 自编码器 中间层的编码维度要远远小于输出数据,整个模型训练目标为最小化重建输入数据误差 标准自编码器面临的问题在于 自编玛器将输入数据转为隐空间中的表达式不是连续的,使得解码器对于存在于类别之间的区域无法进行解码,因此提出了变分自编码器 变分自编码器 变分自编码器的隐空间设计为连续的分布以便进行随机采样和插值,编码器输出两个n维向量,分别为均值向量u以及标准差向量sigma:随后通过对u和sigam作为均值和方差采样得到随机变量x,n次采样后形成n维采样后结果作为编码输出,送入后

(转)【重磅】无监督学习生成式对抗网络突破,OpenAI 5大项目落地

[重磅]无监督学习生成式对抗网络突破,OpenAI 5大项目落地 [新智元导读]"生成对抗网络是切片面包发明以来最令人激动的事情!"LeCun前不久在Quroa答问时毫不加掩饰对生成对抗网络的喜爱,他认为这是深度学习近期最值得期待.也最有可能取得突破的领域.生成对抗学习是无监督学习的一种,该理论由 Ian Goodfellow 提出,此人现在 OpenAI 工作.作为业内公认进行前沿基础理论研究的机构,OpenAI 不久前在博客中总结了他们的5大项目成果,结合丰富实例介绍了生成对抗网络

GAN的资料

https://blog.csdn.net/heyc861221/article/details/80128351 优势 GANs是一种以半监督方式训练分类器的方法,可以参考我们的NIPS paper和相应代码.在你没有很多带标签的训练集的时候,你可以不做任何修改的直接使用我们的代码,通常这是因为你没有太多标记样本.我最近也成功地使用这份代码与谷歌大脑部门在深度学习的隐私方面合写了一篇论文.GANs可以比完全明显的信念网络(NADE,PixelRNN,WaveNet等)更快的产生样本,因为它不需

Auto-encoder 在异常检测中的应用

1 Auto-encoder 目的是提取特征.  Auto-encoder能恢复样本训练过程,就保证了隐含层提取的特征是样本的重要,本质的特征,否则不能恢复样本. 2 用样本学习好Auto-encoder, 将时间序列样本,输入训练好的auto-encoder, 如果输出与输入残差值(平方误差和等)小表示没有异常发生,否则发生异常. 3 隐含层提取的特征很难表达,变分自编码器(Variational autoencoder,VAE):编码数据的分布 是一个描述隐含层特征的特殊自动编码器 4 RN