与变分自编码器(Variational Auto-Encoder)的决一死战

前言

关于VAE,其实我在第一次自学李宏毅老师的课程时就已经写过一篇文章,之后在学校的Machine Learning2课程中也将原始paper-Auto-Encoding Variational Bayes 作为我的期末报告的对象。最近因为毕业论文又需要用到VAE,因此打算在这里对VAE再做一次复习与总结。

回归原文

0.问题

现在我们有一批数据{x1,x2,…,xn}, 采样自某随机变量x。我们希望构建一个模型来探究x的生成过程。首先作者假设这个生成过程分为2步,其中涉及某个隐变量z。即
1)某个随机变量z从某个z的先验分布pθ (z)得到。
2)然后根据得到的z,从条件概率分布pθ(x|z)采样得到x的值。
在这里插入图片描述
但显然这个思路过于理想化,整个过程的大部分信息,比如后验概率pθ(z|x),隐变量z的值,均是隐藏的,因此我们无法单单依靠这个建模思路来求解模型参数。

当然,作者也提到了可以对整个过程,比如后验概率或者边际概率做一些简化性的假设来帮助模型的求解。但是作者并没有这么做,而是希望通过设计一个更一般性的算法来求解这个问题,下面我们就来看一看作者究竟是怎么做的。

1.基本思路

既然我无法直接对真实的后验概率pθ(z|x) (绝大多数情况下非常复杂)进行操作,那么我们就引入另一个分布qφ(z|x)来近似真实的后验概率。这里其实就使用了变分推断的思想。

整个模型的基本框架可以用原文中的这张图来进行说明。
在这里插入图片描述
其中实线代表生成式模型部分,即pθ(z)pθ(x|z),虚线则代表使用qφ(z|x)来变分近似未知的真实后验概率分布。其中的模型参数φ会在后续与θ一起进行优化。

2.如何定义pθ(z|x) 与 qφ(z|x)的近似程度?

既然我们需要一个近似的分布来代替真实的后验分布,那么我们必然需要一个度量手段来度量这两个分布之间的相似程度。这里我们使用KL散度,常用于度量两个分布之间的相似程度。
如qφ(z|x) 与 p(z|x)的KL散度定义如下。
在这里插入图片描述

3.使用qφ(z|x)代替pθ(z|x)进行目标函数推导

现在我们回到我们的目标—极大化边际似然函数p(x)(取log)。
通过引入qφ(z|x),我们可以将其表达为如下形式。(下图取自原文)
在这里插入图片描述
即我们可以将边际似然转化为两个部分,上式右边第一部分就是我上面提到的引入的变分近似分布qφ(z|x)与真实的后验概率分布pθ(z|x)的KL散度。第二部分被称为变分下限(the varitional lower bound)。根据KL散度的定义,我们有KL散度恒大于0的结论,因此可以得到如下这个重要的关系式。
在这里插入图片描述
这也是我们为什么将该部分称为变分下限的原因,所以我们就可以通过优化我们的变分下限来间接地优化我们的目标似然函数。那么我们现在就将注意力放在如何优化我们的变分下限函数L上。

事实上,它可以进一步被拆分成两个部分。如下
在这里插入图片描述
我们先来看后面红色的一项,这一项非常好理解,本质上就是希望模型能基于q分布(encoder)产生的隐变量z,最大概率得通过p分布 (decoder)还原得到x

然后来看蓝色这一部分,这部分代表的是我们引入的变分近似分布qφ(z|x)与隐变量z的分布之间的负KL散度,为了让最终结果最大化,这项KL散度要尽可能地小,即我们希望让q分布和隐变量z的分布尽可能靠近。本质上这一项可以看作是正则项,如果没有这一项的约束,单纯地优化红色部分,那么模型会倾向于消除所有的噪声,过分地保证训练集中的输入与输出的高度一致,这不是我们想要的,我们希望地是模型更加具有创造性。

哦对了,说了这么多好像还没有说我们是如何从最初的对数似然函数推导到我们的变分下限函数的。以下是简单的推导过程。
在这里插入图片描述
最后一行的前两项就是我们的L(θ,φ;x )。

4.如何优化新的目标函数L(θ,φ;x )?

在前一部分,我们已经得到了我们的新目标函数,即变分下限函数L(θ,φ;x )。这里我们需要优化的参数有两个,即θ,φ。但是其中φ的求解存在一些问题。如果我们想直接利用梯度来优化φ是不行的。因为参数φ决定了隐变量的分布以及之后的采样结果,但是注意,采样这个过程是不可导的,因此梯度的反向传播也会因此受阻。

因此为了使得采样过后,参数φ能够依然留在表达式中,使得我们依旧能够对参数
φ求梯度,这里作者使用了一个小trick,叫做重参数法(the reparameterization trick)。即我们再引入一个辅助变量ε,其遵循某个已知的独立分布p,比如标准正态分布。然后让其参与到z的产生过程。具体来说,我们可以将其表达为下图中黄色的表达式。
在这里插入图片描述
这里解释一下整个逻辑,首先我们的采样过程由辅助变量ε来完成,然后参数φ负责建立从采样结果ε到我们需要的采样结果z的映射关系。这样一来即使我们利用蒙特卡罗方法用采样均值替代期望后,参数φ依然留在表达式中,这样一来我们就可以使用对其求梯度来进行正常优化了。
在这里插入图片描述
利用这个方法作者就成功构建了SGVB estimator来近似我们的变分下限目标函数L(θ,φ;x ),使其依旧对参数θ,φ可微。我们来看一下其具体的表达式,如下。
在这里插入图片描述
说白了,就是用蒙特卡罗估计(L个样本的采样平均)代替原来的期望。前一项KL divergence是有表达式的,因此不需要做近似。

事实上,在原文中变分下限函数L(θ,φ;x )有两种表达式,因此SGVB estimator自然也有对应的两种,这里我列举了第二种(B), 也是因为与我上文列出的变分下限表达式保持一致。

Anyway, 现在我们已经提出了对目标参数θ,φ可微的目标函数表达式,接下来我们可以来引出完整的算法了,也是这篇文章的核心算法—AEVB algorithm
直接copy原文:)
在这里插入图片描述
其实核心就是得到SGVB estimator,之前的步骤包括初始化参数,分割minibatch,辅助变量的采样,后面的步骤就是使用梯度更新参数。这些更多是实践层面的东西,这里就不再展开了。

5.重要的应用VAE

这篇文章提出了一个一般性的算法,用于求解包含隐变量的有向概率图模型。其中非常重要的一个应用就是VAE。

在上述的生成式概率图模型中,我们引入了一个变分近似qφ (z|x),用于近似表示未知的后验概率pθ(z|x)。这个部分可以被看作是一个编码(encoding)的过程,即将原始输入x转化为对应隐变量z的分布参数。在VAE中,我们使用一个神经网络来拟合这个过程。但是光这样还是不够的,因为我们对pθ(z|x)是完全未知的,因此能够使用的近似分布qφ (z|x)的形式存在太多不同的可能了。所以作者在这里做了一个假设,真实的后验概率为高斯分布。下面是原文中的相关描述。
在这里插入图片描述
从而我们神经网络的构建方向也清晰了: 使用一个多层感知机,输出为高斯分布的均值和方差,当然在高维情况下,为均值和方差向量。
在这里插入图片描述
然后就是借助上文中提到的reparameterization技巧借助辅助变量ε进行z的采样。
偷个懒,直接拷贝原文的描述:)
在这里插入图片描述
完成z的采样之后,接下来就来到了解码过程了(decoding),即通过隐变量z来还原x。同样的,这个解码器(decoder)也使用神经网络来拟合。在原文中,作者针对输出数据的不同分布,一种是伯努利分布,一种是高斯分布,提出了两种对应的解码器结构。
在这里插入图片描述
理论部分差不多就是这样了,接下来在最后一部分,用pytorch写一个简单的VAE。

6.Pytorch实现一个简单的VAE结构

import torch
import torch.nn as nn
import torch.nn.function

#basic VAE
class simple_vae(nn.Module):
    def __init__(self,org_size,input_size,hid_dim,lat_dim):
        super(VAE,self).__init__()
        self.org_size=org_size # the original size of x
        self.input_size=input_size # the reshaped size of x
        self.hid_dim=hid_dim # hidden layer dimension
        self.lat_dim=lat_dim # latent variable dimension
        self.encoder=nn.Sequential(nn.Linear(input_size,hid_dim),
                                   nn.ReLU())
        # mu vector
        self.mu=nn.Linear(hid_dim,lat_dim)
        # log_var vector : make sure var is always positive
        self.log_var=nn.Linear(hid_dim,lat_dim) 
        
        self.decoder=nn.Sequential(nn.Linear(lat_dim,hid_dim),
                                   nn.ReLU(),
                                   nn.Linear(hid_dim,input_size))
       
    def encode(self,x):
        x=x.view(x.size(0),self.input_size) # reshape to (batch_size,input_size)
        hid_out=self.encoder(x)
        return self.mu(hid_out),self.log_var(hid_out)
    
    def reparameterize(self,mu,log_var):
        # calculate std
        std=torch.exp(log_var/2)
        # produce random auxiliary variable eps with the same size of mu (or std)
        eps=torch.randn_like(mu) 
        return mu+eps*std
    
    def decode(self,z):
        out=self.decoder(z)
        return F.sigmoid(out)
    
    def forward(self,x):
        mu,log_var=self.encode(x)
        z=self.reparameterize(mu,log_var)
        output=self.decode(z)
        
        return output 

这里只是一个示例代码,单纯是为了博客完整性而写的,我并没有在实际数据集上做任何实验。如果你想直接使用的话还需要注意以下问题:

1上面示例中我的output是没有最终还原到原始数据尺寸的。
2.最终解码时我使用sigmoid激活函数将其输出分布压缩到0-1之间,但是在实际使用中还是需要依据你的数据分布来进行修改。
3.这样简单的结构一般在实际使用中很难有好的效果。

以上就是这篇文章的全部内容了,谢谢大家的阅读。

参考文章:
1.Auto-Encoding Variational Bayes
2.《Auto-Encoding Variational Bayes》论文阅读
3.变分自编码器(一):原来是这么一回事

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
变分自编码器Variational Autoencoders,VAE)是一种生成模型,结合了自编码器变分推断的概念。 VAE的目标是学习输入数据的潜在表示,并通过该表示生成新的样本。与传统的自编码器不同,VAE引入了概率分布的概念,并通过变分推断来学习数据的分布。 以下是VAE的主要组成部分和工作流程: 1. 编码器(Encoder):编码器将输入数据映射到潜在空间中的潜在变量(latent variable),也称为编码(encoding)。编码器的目标是学习数据的分布,并产生潜在变量的均值和方差。 2. 解码器(Decoder):解码器接收潜在变量作为输入,并将其映射回原始数据空间中,以重构输入数据。解码器的目标是学习生成数据的分布,并尽可能准确地重构输入数据。 3. 潜在变量采样(Latent Variable Sampling):在训练过程中,从编码器中获得的均值和方差用于参数化一个概率分布,然后从该分布中采样潜在变量。这个采样过程使得VAE能够生成多样化的样本。 4. 损失函数(Loss Function):VAE使用重构损失和KL散度损失来训练模型。重构损失衡量重构样本与原始样本之间的差异,KL散度损失衡量潜在变量的分布与预定义的先验分布之间的差异。通过最小化这两个损失函数,VAE能够学习到数据的潜在表示。 VAE的训练过程可以概括为以下几个步骤: 1. 输入数据经过编码器,获得潜在变量的均值和方差。 2. 根据潜在变量的均值和方差,从潜在空间中采样一些潜在变量。 3. 采样的潜在变量输入解码器,生成重构样本。 4. 计算重构损失和KL散度损失,并将它们相加得到总体损失。 5. 使用反向传播算法更新编码器和解码器的参数。 6. 重复步骤1-5,直到达到预定的训练迭代次数或达到训练目标。 VAE通过学习数据的潜在表示,能够生成新的样本,并且具有较好的样本多样性和连续性。它在图像生成、特征提取和数据压缩等领域具有广泛的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值