文章主题:生成模型, VAE, 变分推理
写在前面
🌟自学生成模型大热🔥,探索DALLE、novel AI和chatGPT等前沿技术,这些创新模型无疑是今年的焦点。GANs、VAEs、流模型及扩散模型等各具特色,都是生成领域的重要知识点。📚想要深入浅出地掌握它们?别急,我会以简洁的语言带你入门。GANs是生成对抗网络,VAEs则是维数压缩的典范,流模型则如流动的代码,揭示数据内在结构;而扩散模型以其扩散过程解释生成机制,独特且实用。理论部分,GAN通过对抗训练提升生成质量,VAEs用概率建模来理解数据分布。流模型像数据的血液,帮助我们追踪信息流动,而扩散模型则是预测和生成的利器。如果你是新手,欢迎提出任何疑问,我会尽我所能帮你澄清疑惑。记住,错误是学习的一部分,欢迎大家批评指正!🎓#生成模型入门# #技术探索# #理论解析
引言
🌟VAEs虽名声不若GAN,却以其坚实的理论基础和独特的可解释性魅力,在AI领域独树一帜。💡作为早期的生成模型之一,DALLE的诞生就源于对VAE深度理解的洞察,这使得它在数据生成与分析中展现出强大的潜力。📊尽管它们不像GAN那样耀眼夺目,但VAEs的实用性不容忽视,尤其是在需要透明度和解析性的时候。📚如果你对AI的深层探索感兴趣,不妨深入了解VAEs,它们或许会成为你的新发现之旅。🌐
🎨💻VAE的力量:不同于传统神经网络,它以创新的方式编码图像,将像素转化为`(n维向量)`, 不仅为生成带来飞跃,还融入了贝叶斯思维的魔法。通过模拟概率分布,让每张图片拥有一个独特的`随机生成源`。这个过程不仅增强了模型的多样性,还能确保生成的新图与原图神似,展现卓越的生成和泛化能力。🌍✨
接下来的内容将以深度解析的方式展开,首先,章节一将带领您穿越时空,重温Autoencoder(AE)的核心原理,这是理解VAE不可或缺的基石。在第二篇章中,我们将揭示AE的局限性,探讨为何它无法生成新颖数据,并在此基础上引出VAE——一个巧妙的正则化变体,它的存在为数据处理带来了革命性的改变。最后,对于那些对VAE数学细节感兴趣的读者,章节三将提供严谨的推导和解析,让您能从更抽象的角度理解这一模型的工作机制。然而,这部分并非必要,即使略过,也不会影响您对VAE整体概念的把握。让我们一起探索这个深度学习领域的瑰宝,用代码和实例来揭示其背后的智慧与价值。记得跟随我们的步伐,每一步都充满惊喜与洞察。📚💻
一、自动编码器(Autoencoder,AE)
🎨📊AI入门指南:理解VAE背后的秘密🔍首先,让我们揭开VAE(Variational Autoencoder)神秘的面纱,它并非简单易懂的新星,而是深度学习世界中的变形高手!💡AE,即Autoencoder,是无监督学习领域里的明星,它的操作就像魔术师手中的变形棒:将高维数据压缩成低维宇宙,再用智慧重构回原貌。`(潜在空间 -> 特征压缩 -> 数据重建)`AE的核心由两部分网络组成,它们像是协同工作的双子星座,共同编织数据的梦境。`(编码器(编码) -> 潜在层(隐藏) -> 解码器(解密))`VAE,作为AE的进化版,引入了概率的概念,通过优化一个近似真实分布来学习数据的内在结构。`(用变分原理捕捉不确定性,让模型更聪明)`想要深入探索这个奇妙的世界,不妨跟随VAE的脚步,一起在数据的维度中游刃有余。`=^_^=`SEO提示:无监督学习、Autoencoder、VAE、深度学习、变形高手、概率优化、数据内在结构
Encoder:将原始的高维数据映射到低维特征空间,这个特征维度一般比原始数据维度要小,这样就起到降维的目的,这个低维特征也往往被称为中间隐含特征(latent representation);鉴于Encoder的作用,理论上,我们可以将它用来对图像等高维数据做降维使用,或是当预训练模型的权重。Decoder:基于压缩后的低维特征来重建原始数据;因为它是用于生成的,理论上,我们应该是可以将它拿来作为生成器,生成图像等数据。🌟当训练AE模型时,我们的目标是让它生成的数据尽可能接近原始数据,这就需要巧妙地运用损失函数。一个常用且直观的选择是均方误差(MSE)🌟——它测量预测值与实际值之间的差距,确保重建的品质高且精准。
LAE=||x−d(e(x))||2L_{AE}=|| x – d(e(x)) ||^2
PS:以上,就是AE的简单介绍。但在写这些的时候,忍不住去想一些有的没的:大数据时代,信息的巨量增长,也给人们带来的储存,表达上的不方便,人们需要一种降维算法方便储存或是表达。以图像为例,一张 512×512512 \times512 的单通道图像,有差不多25w个数值,太多了,一个很简单直接的想法就是,我们将这个 512×512512 \times512 的图像矩阵,变成 1×(512∗512)1 \times (512*512) 的维度,后面接一个 ()(512∗512)×64(512*512)\times 64 的转换矩阵,那图像就变成了 1×641\times 64 的一个向量了!如果我们有一个海量图像库,我们现在只需要存储一下这个低维向量和转换矩阵即可,大大减少了内存占用,但是突然发现这个转换矩阵它不是方阵,他不可逆!我们不能通过简单求逆的方式得到一个 64×(512∗512)64 \times (512*512) 的矩阵将低维向量还原回去。。。。不过现在的神经网络很牛,既然数学上求解不出来,那就交给神经网络去学习,希望它能把这两个矩阵的近似解搞出来,那也是可以的,事实证明,神经网络确实能搞出来,就是太容易过拟合了。。。以上,只是个人角度理解的AE,hh
AE缺陷
虽然AE的Encoder和Decoder看起来很靠谱。。。都有各自的用途。但是,在实际的应用中,人们发现AE很容易过拟合,我们的神经网络很可能过于强大,以致于它根本没必要学会样本含有的语义信息,只是无脑的知道训练集中某个编码进来,那他的输出就是这样的,它的loss能非常接近于0,但是对训练集外的样本,做成编码传到decoder之后,网络只能干瞪眼,没有泛化能力,也就失去了生成能力。
说的详细点,对于encoder的输出,首先,我们自然是希望Encoder得到的隐特征是尽可能多的保留原始信息,最好仍有原来的语义信息,但是实际得到的特征,不一定有这性质,就像下图一样,我们希望两个8,两个9能比较靠近,但显然,下图中它们没做到。
又或者,像下面的图一样,看似每一类都聚合的很不错,但是左侧的大豁口暗示着这模型过拟合严重。我们希望得到的聚类图应该是样本能尽量散布全图,整体轮廓比较“圆润”,然后边界也比较清晰。但像下图这样,就不太“圆润”,若取豁口处的点作为样本输出decoder中,模型输出的图大概率是啥都不像,这就意味着decoder没有它应有的生成能力。
再换个角度,上面讲到AE是把一个样本映射成一个n维向量,这个向量我们可以将它看作是某个高维空间上的一个坐标点,也就是说我们把一个样本映射到了一个点上。限于AE的泛化能力,encoder得到的向量所含的语义信息不太强,导致这个点周围的样本点,并不一定和我们的输入样本很相关,所以我们在这个隐空间中随机采样时,将采样得到的点输入decoder中,它生成的样本也就不太满意了。就如下图所示。
无意义的隐空间使我们采样到的点不能生成有效的内容。虽然也有相应的模型与技术针对AE的缺陷进行了改进,但这些不是本文的重点,接下来看一下VAE是怎么解决以上的缺陷的。
二、VAE介绍
首先,我们给出一些符号的定义,假设已知的数据集为X={x(i)}i=1N\mathbf{X}=\{x^{(i)}\}_{i=1}^N,在VAE中,除了已知的数据外还存在一个隐变量,记为zz,它服从先验分布 p(z)p(\mathbf{z}),假设是标准正态分布 。基于这些符号,我们可以把VAE中的encoder写作 p(z|x)p(z|x) ,decoder写作 p(x|z)p(x|z) 。
AE和VAE的比较鉴于前面讨论过的AE过拟合严重这一问题,很自然的想法就是我们增加正则化手段以增加模型的泛化性,VAE从某个角度来看就是AE的正则化版本。既然最初的AE将一个样本映射成一个点很容易使得没在训练集里出现的点都失去意义,太容易过拟合了,那我们就引入贝叶斯理论的一些思想:将训练集的每一个样本映射成一个专属的分布,从这个分布上取到的点,都有概率和原样本比较相似,且越容易被采样到的点越像原样本,从而增强模型的泛化能力。
那按这个思路,我们会想到这么一个问题。我们怎么让神经网络去学一个分布。这里VAE假设encoder学出来的分布 p(z|x)p(z|x) 是正态分布,而要想确定一个正太分布,我们只需要知道两个统计量就好了,也就是它的均值和方差。因此,我们要学这个分布,只需要让神经网络学均值和方差即可,再具体点说,如果学的是一元高斯分布,我们就在encoder后面加一个二维的全连接层,输出的二维向量分别表示均值、方差,如果是二元高斯分布,那就是后面接一个4维的全连接层,以此类推。VAE的具体流程如下。
从图中可以看到,每一个样本,得到的正太分布都是不一样的,这也和前面的论述对上了。
从图中,我们可以知道训练的目标,仍然是减少 X^\hat{X} 和 XX 之间的误差,但不同于AE,VAE中间多了个采样的过程,这实际上也是增加噪声的过程,加大了模型的训练难度,从而起到了正则化的作用。但是,仔细想一下,这样的操作还是不够的,因为增加噪声主要靠的是方差,但若是模型投机取巧,把方差训练成了0,那这个采样的过程不就毫无作用了,起不到增加噪声,完成正则化的目的了。
因此,VAE在训练的时候,还要求中间的正态分布都向标准正态分布靠拢,这样也就防止了方差变成0。
我们希望encoder学出来的分布p(z|x)p(z|x)是服从标准正态分布的原因,直觉上可以这么理解,在训练中,我们不能让方差退化成接近0,如果方差几乎为0,那意味着我们这个分布几乎退化成了一个点,那就和AE没区别了,还是过拟合。但也不是说方差可以很大,这会使得数据差异太大,显然也不太合理,会过度增加模型的训练难度。方差上有限制,均值也同样有,我们希望每个样本的均值都比较接近,也就是每一个样本得到的高斯分布之间要紧凑,太分散的话,同样会出现离散的点,生成的图像四不像;紧凑一点,有的点可能属于多个分布,那这个点就是每个样本都像一点,那也符合预期,下面这个图可以很好的概括~。
三个圆圈挨得近,说明均值比较靠近,圆圈半径比较大,说明方差要稍微大一点理论上来看,如果所有的 p(z|x)p(z|x) 都可以近似的看作是标准正态分布,那么根据定义:
p(z)=∫p(z|x)p(x)dx=∫N(0,I)p(x)dx=N(0,I)∫p(x)dx=N(0,I)p(\mathbf{z})=\int{p(z|x)p(x)}dx=\int N(0,I)p(x)dx=N(0,I)\int p(x)dx=N(0,I)
这时候,我们就会发现,前面假设Z的先验分布是标准正态分布就用上了,我们可以放心的从标准正太分布上采样,并得到我们想要的结果了。
在实际使用中,我们就可以这么使用VAE生成数据:
1.从先验分布p(z)p(\mathbf{z})中采样一个z(i)\mathbf{z}^{(i)};
2.根据decoder的p(x|z)p(x|z),用z(i)\mathbf{z}^{(i)}生成x(i)\mathbf{x}^{(i)}。
解决了这个问题后,还有一个问题就是怎么优化。AE的loss只能使得decoder的输出尽可能地拟合原始输出,但是如何让encoder的输出p(z|x)p(z|x)满足正态分布呢,我们知道,KL散度是可以判断两个分布是否相似的一个标准,所以新加的正则化项就是encoder拟合的分布与高斯分布之间的 Kulback-Leibler 散度。
最终VAE的loss可以写成如下这种形式:
LVAE=||x−d(e(x))||2+KL[N(μx,σx2),N(0,1)]L_{VAE}=|| x – d(e(x)) ||^2+KL[N(\mu_x,\sigma^2_x),N(0,1)]
VAE代码实现及重采样技术
这里给出一个非常简单的VAE代码实现,请结合注释使用。encoder和decoder就是简单的全连接+relu,增加一些非线性性。
看forward函数了解模型的前向流程,首先,图像经过encoder,得到均值和方差,然后用chunk函数,将它切分开来,这里的方差求的是logvar,因为var是大于0的一个数,而我们的全连接输出是整个实数域,所以加一个log将值域从全体实数域转到正数。
reparameterize函数是一个重采样函数,也是模型的一个重点,前面讲到得到均值和方差后,我们就确定了一个高斯分布,但如果直接在这个分布上随机采样一个点传到decoder中,采样这一过程并不可导,会导致梯度断裂,模型无法更新,所以我们需要一个合理的采样方式,让梯度正常传递才行。这里采用的做法就是利用标准高斯分布经过缩放,可以变成任何高斯分布的特点,从标准高斯分布中随机生成一个点,再利用均值和方差进行变换,这样就把均值方差用上了,让梯度连接了起来,从而可以正常更新参数。
每次训练的时候,我们都会在一个分布上采样一个点,那假设我们训练100个epoch,就意味着我们在输入对应的分布上采样了一百次,采样的每个点,我们都希望他和原图相似,且采样概率大的点,因此更容易被采到,一般会更像,采样概率小的点,可能就是有一点像。
三、数学推导
预备知识
一些需要用到的公式:
KL散度,也叫相对熵,其公式为
KL(p||q)=H(p,q)−H(p)KL(p||q) = H(p,q)-H(p)
=−∫p(x)logq(x)dx−∫−p(x)logp(x)dx=-\int p(x)logq(x)dx-\int -p(x)logp(x)dx
=−∫p(x)(logq(x)−log(p(x)))dx=-\int p(x)(\log q(x)-\log(p(x)))dx
=−∫p(x)logq(x)p(x)dx=-\int p(x)\log \frac{q(x)}{p(x)}dx
以上, H(p,q)H(p,q) 表示p和q的交叉熵, H(p)H(p) 表示p的熵。实际上,可以将上式改写为期望的形式,借鉴
∫f(x)p(x)dx=Ep(x)(f(x))\int f(x)p(x)dx=E_{p(x)}(f(x))
所以,下面这三条公式很重要,会在后面用到。
H(p)=Ep(x)(log1p(x))=−Ep(x)(logp(x))H(p)=E_{p(x)}(\log \frac{1}{p(x)})=-E_{p(x)}(\log {p(x)})
H(p,q)=Ep(x)(log1q(x))=−Ep(x)(logq(x))H(p,q)=E_{p(x)}(\log \frac{1}{q(x)})=-E_{p(x)}(\log {q(x)}) (1)
∫p(x)log1q(x)dx=Ep(x)(log1q(x))\int p(x)log{\frac{1}{q(x)}}dx=E_{p(x)}(\log \frac{1}{q(x)})
推导
我们沿用前面的符号定义,decoder自然地由 p(x|z)p(x|z) 定义,它描述了给定隐变量后的decoder生成的变量的分布,而encoder由 p(z|x)p(z|x) 定义,它描述了给定样本后,隐变量的分布。
在前面我们提到过KL散度,为了让中间的分布逼近标准正态分布,我们采用了它。而实际上,我们采用这种方法就默认了我们使用了一种变分推断技术(变分推断 (Variational Inference,VI) 作为一种近似复杂分布的技术,它的想法是设置一个参数化的分布族(例如高斯族,其参数是均值和协方差)并在这个族中寻找我们的目标分布的最佳近似值。族中最好的元素是最小化loss时(大多数情况下是近似值和目标之间的 KL 散度)的那个元素,并且是通过梯度下降找到的。)
试想一下我们不用神经网络,那从理论上看我们是否可以直接得到p(z|x)p(z|x)呢,根据贝叶斯公式,后验 p(z|x) p(z|x) 可以与先验 p(z) p(z) 、似然 p(x|z)p(x|z) 建立联系,即
p(z|x)=p(x|z)p(z)∫p(x|u)p(u)dup(z|x)=\frac{p(x|z)p(z)}{\int p(x|u)p(u)du}
此时我们会遇到一个棘手的问题,也就是分母处的积分!可能会很难求,甚至没有具体的解析解,如果p(z|x)p(z|x)能直接求出来,也就没神经网络什么事了,直接上精确的解析解了。
所以,这里我们试图用变分推断的技术寻找一个高斯分布 q(z|x)q(z|x) 来近似 p(z|x)p(z|x),其均值和协方差由两个函数 g(.)g(.) 和 h(.)h(.) 定义。因此我们可以表示,
q(z|x)≡N(g(x),h(x))q(z|x) \equiv N(g(x),h(x))
由此,我们通过这种方式定义了一组用于变分推断的候选者,现在需要找到最佳的函数 gg 和 hh,以最小化近似值和目标 p(z|x) p(z|x) 之间的误差。换句话说,我们正在寻找最优的 g* 和 h* 使得
(g∗,h∗)=argmin(g,h)∈G×HKL(q(z|x),p(z|x))(g*,h*)=\mathop{argmin}\limits_{(g,h) \in G \times H}KL(q(z|x),p(z|x))
=argmin(g,h)∈G×HH(q(z|x),p(z|x))−H(q(z|x))=\mathop{argmin}\limits_{(g,h) \in G \times H}H(q(z|x),p(z|x))-H(q(z|x))
=argmin(g,h)∈G×H(−Eq(z|x)(logp(x|z)p(z)p(x))−(−Eq(z|x)(logq(z|x))))=\mathop{argmin}\limits_{(g,h) \in G \times H} \left( -E_{ q(z|x)}(\log\frac{p(x|z)p(z)}{p(x)} \right) – \left( -E_{q(z|x)}(\log q(z|x))) \right)
=argmin(g,h)∈G×H(−Eq(z|x)(logp(x|z))−Eq(z|x)(logp(z))+Eq(z|x)(logp(x))+Eq(z|x)(logq(z|x)))=\mathop{argmin}\limits_{(g,h) \in G \times H}\left( -E_{q(z|x)}(\log p(x|z)) -E_{q(z|x)}(\log p(z)) + E_{q(z|x)}(\log p(x)) + E_{q(z|x)}(\log q(z|x))\right)
此处进行移项,整理,根据预备知识的公式(1),则
上式=argmin(g,h)∈G×H(−Eq(z|x)(logp(x|z))+(H(q(z|x),p(z))−H(q(z|x)))+logp(x)∫q(z|x)dz)=\mathop{argmin}\limits_{(g,h) \in G \times H}\left( -E_{q(z|x)}(\log p(x|z)) + (H(q(z|x),p(z)) -H(q(z|x))) +\log p(x)\int q(z|x)dz \right)
最后一项的积分为1,中间两项可写成KL散度的形式,则
上式=argmin(g,h)∈G×H(−Eq(z|x)(logp(x|z))+KL(q(z|x),p(z))+logp(x))=\mathop{argmin}\limits_{(g,h) \in G \times H}\left( -E_{q(z|x)}(\log p(x|z))+KL(q(z|x),p(z)) + \log p(x)\right) (2)
上式中,要找最优的参数和样本x出现的概率无关,所以最后一项可以不看,所以,我们能得到
(g*,h*)=\mathop{argmax}\limits_{(g,h) \in G \times H}\left( E_{q(z|x)}(\log p(x|z))-KL(q(z|x),p(z))\right)
在很多教程中,还会再假设p(x|z) 同样是高斯分布,也就是decoder的分布,其均值由 z 变量的确定性函数 f 定义,协方差矩阵的形式为常数 c 乘以单位矩阵 I 。假设函数 f 属于表示为 F 的函数族。因此,我们有
0″>p(x|z)\equiv N(f(z),cI), f\in F, c>0
由此,上式我们就可以改写做,
=\mathop{argmax}\limits_{(g,h) \in G \times H}\left( E_{q(z|x)}(-\frac{||x-f(z)||^2}{2c})-KL(q(z|x),p(x))\right)
在上式中,我们可以观察到存在权衡,即当近似后验 p(z|x) 时——最大化“观察”的可能性(最大化对数似然,第一项)和保持接近先验分布(对于第二项, q(z|x) 和 p(z) 之间的 KL 散度最小化)。这种权衡对于贝叶斯推理问题来说是很自然的,它表达了我们对数据的信心和对先验的信心之间需要找到的平衡。具体地说,x 和 f(z) 之间的重构误差以及 q(z|x) 和 p(z) 之间的 KL 散度给出的正则化项存在一个权衡,常数 c 决定了两项之间的平衡。 c 越高,我们假设模型中的“probabilistic decoder”围绕 f(z) 的方差越大,因此我们越倾向于正则化项而不是重建项(如果 c 较低,则相反)。
某种意义上,VAE 跟 GAN 一样,内部其实是包含了一个对抗的过程,只不过它们两者是混合起来,共同进化的。
最后一个问题,我们在上面得到了优化函数,但是在大多数教程中,它还会继续写下去。针对第一项,可以使用MSE函数或者二分交叉熵函数去优化,对于第二项,看到很多代码中会看到下面式子的影子
\frac{1}{2}(-\log \sigma ^2 +\sigma^2+\mu^2-1)
它是 KL(q(z|x),p(x)) 的具体结果,至于怎么计算的,因为牵扯到线性代数等知识,比较繁琐,笔者没能力自己推导,具体参考这篇和这篇文章~只是想了解的,知道上式代表的是啥我想也就够了~
另外,在学VAE的概念的时候,一定会看到ELBO这个单词,实际上它就是我们的公式(2)这里出来,从另一个角度进行的理解,由公式(2),去掉argmax这个符号,我们可以得到
KL(q(z|x),p(z|x))=-E_{q(z|x)}(\log p(x|z))+KL(q(z|x),p(z)) + \log p(x)
将其移个项,可以得到,
\log p(x)-KL(q(z|x),p(z|x))=E_{q(z|x)}(\log p(x|z))-KL(q(z|x),p(z))
由于KL散度的非负性,所以有下述不等式:
\log p(x) \geq E_{q(z|x)}(\log p(x|z))- KL(q(z|x),p(z))
不等号右边的式子就是ELBO,它规定了x出现的概率下界,所以我们的优化过程,也可以被理解成是在不断提高ELBO的下界,使得x出现的概率更高。
参考资料
2.https://towardsdatascience.com/understanding-variational-autoencoders-vaes-f70510919f73
3.变分自编码器(Variational AutoEncoder, VAE),直观理解、数学推导与两年前的应用
4.PaperWeekly:变分自编码器VAE:原来是这么一回事 | 附开源代码
5.KL散度(Kullback-Leibler Divergence)介绍及详细公式推导
AI时代,拥有个人微信机器人AI助手!AI时代不落人后!
免费ChatGPT问答,办公、写作、生活好得力助手!
搜索微信号aigc666aigc999或上边扫码,即可拥有个人AI助手!