首页 > 其他分享 >VAE--就是AutoEncoder的编码输出服从正态分布

VAE--就是AutoEncoder的编码输出服从正态分布

时间:2023-06-02 23:06:55浏览次数:45  
标签:编码器 AutoEncoder nn -- self VAE 生成 我们 图片

花式解释AutoEncoder与VAE

什么是自动编码器

自动编码器(AutoEncoder)最开始作为一种数据的压缩方法,其特点有:

1)跟数据相关程度很高,这意味着自动编码器只能压缩与训练数据相似的数据,这个其实比较显然,因为使用神经网络提取的特征一般是高度相关于原始的训练集,使用人脸训练出来的自动编码器在压缩自然界动物的图片是表现就会比较差,因为它只学习到了人脸的特征,而没有能够学习到自然界图片的特征;

2)压缩后数据是有损的,这是因为在降维的过程中不可避免的要丢失掉信息;

到了2012年,人们发现在卷积网络中使用自动编码器做逐层预训练可以训练更加深层的网络,但是很快人们发现良好的初始化策略要比费劲的逐层预训练有效地多,2014年出现的Batch Normalization技术也是的更深的网络能够被被有效训练,到了15年底,通过残差(ResNet)我们基本可以训练任意深度的神经网络。

所以现在自动编码器主要应用有两个方面,第一是数据去噪,第二是进行可视化降维。然而自动编码器还有着一个功能就是生成数据。

我们之前讲过GAN,它与GAN相比有着一些好处,同时也有着一些缺点。我们先来讲讲其跟GAN相比有着哪些优点。

第一点,我们使用GAN来生成图片有个很不好的缺点就是我们生成图片使用的随机高斯噪声,这意味着我们并不能生成任意我们指定类型的图片,也就是说我们没办法决定使用哪种随机噪声能够产生我们想要的图片,除非我们能够把初始分布全部试一遍。但是使用自动编码器我们就能够通过输出图片的编码过程得到这种类型图片的编码之后的分布,相当于我们是知道每种图片对应的噪声分布,我们就能够通过选择特定的噪声来生成我们想要生成的图片。

第二点,这既是生成网络的优点同时又有着一定的局限性,这就是生成网络通过对抗过程来区分“真”的图片和“假”的图片,然而这样得到的图片只是尽可能像真的,但是这并不能保证图片的内容是我们想要的,换句话说,有可能生成网络尽可能的去生成一些背景图案使得其尽可能真,但是里面没有实际的物体。

自动编码器的结构

首先我们给出自动编码器的一般结构

VAE--就是AutoEncoder的编码输出服从正态分布_2d

从上面的图中,我们能够看到两个部分,第一个部分是编码器(Encoder),第二个部分是解码器(Decoder),编码器和解码器都可以是任意的模型,通常我们使用神经网络模型作为编码器和解码器。输入的数据经过神经网络降维到一个编码(code),接着又通过另外一个神经网络去解码得到一个与输入原数据一模一样的生成数据,然后通过去比较这两个数据,最小化他们之间的差异来训练这个网络中编码器和解码器的参数。当这个过程训练完之后,我们可以拿出这个解码器,随机传入一个编码(code),希望通过解码器能够生成一个和原数据差不多的数据,上面这种图这个例子就是希望能够生成一张差不多的图片。

VAE--就是AutoEncoder的编码输出服从正态分布_编码器_02

这件事情能不能实现呢?其实是可以的,下面我们会用PyTorch来简单的实现一个自动编码器。

首先我们构建一个简单的多层感知器来实现一下。

class autoencoder(nn.Module):
    def __init__(self):
        super(autoencoder, self).__init__()
        self.encoder = nn.Sequential(
            nn.Linear(28*28, 128),
            nn.ReLU(True),
            nn.Linear(128, 64),
            nn.ReLU(True),
            nn.Linear(64, 12),
            nn.ReLU(True),
            nn.Linear(12, 3)
        )
        self.decoder = nn.Sequential(
            nn.Linear(3, 12),
            nn.ReLU(True),
            nn.Linear(12, 64),
            nn.ReLU(True),
            nn.Linear(64, 128),
            nn.ReLU(True),
            nn.Linear(128, 28*28),
            nn.Tanh()
        )

    def forward(self, x):
        x = self.encoder(x)
        x = self.decoder(x)
        return x

这里我们定义了一个简单的4层网络作为编码器,中间使用ReLU激活函数,最后输出的维度是3维的,定义的解码器,输入三维的编码,输出一个28x28的图像数据,特别要注意最后使用的激活函数是Tanh,这个激活函数能够将最后的输出转换到-1 ~1之间,这是因为我们输入的图片已经变换到了-1~1之间了,这里的输出必须和其对应。

训练过程也比较简单,我们使用最小均方误差来作为损失函数,比较生成的图片与原始图片的每个像素点的差异。

同时我们也可以将多层感知器换成卷积神经网络,这样对图片的特征提取有着更好的效果。

class autoencoder(nn.Module):
    def __init__(self):
        super(autoencoder, self).__init__()
        self.encoder = nn.Sequential(
            nn.Conv2d(1, 16, 3, stride=3, padding=1),  # b, 16, 10, 10
            nn.ReLU(True),
            nn.MaxPool2d(2, stride=2),  # b, 16, 5, 5
            nn.Conv2d(16, 8, 3, stride=2, padding=1),  # b, 8, 3, 3
            nn.ReLU(True),
            nn.MaxPool2d(2, stride=1)  # b, 8, 2, 2
        )
        self.decoder = nn.Sequential(
            nn.ConvTranspose2d(8, 16, 3, stride=2),  # b, 16, 5, 5
            nn.ReLU(True),
            nn.ConvTranspose2d(16, 8, 5, stride=3, padding=1),  # b, 8, 15, 15
            nn.ReLU(True),
            nn.ConvTranspose2d(8, 1, 2, stride=2, padding=1),  # b, 1, 28, 28
            nn.Tanh()
        )

    def forward(self, x):
        x = self.encoder(x)
        x = self.decoder(x)
        return x

这里使用了nn.ConvTranspose2d(),这可以看作是卷积的反操作,可以在某种意义上看作是反卷积。

我们使用卷积网络得到的最后生成的图片效果会更好,具体的图片效果我就不再这里放了,可以在我们的github上看到图片的展示。

变分自动编码器(Variational Autoencoder)

变分编码器是自动编码器的升级版本,其结构跟自动编码器是类似的,也由编码器和解码器构成。

回忆一下我们在自动编码器中所做的事,我们需要输入一张图片,然后将一张图片编码之后得到一个隐含向量,这比我们随机取一个随机噪声更好,因为这包含着原图片的信息,然后我们隐含向量解码得到与原图片对应的照片。

但是这样我们其实并不能任意生成图片,因为我们没有办法自己去构造隐藏向量,我们需要通过一张图片输入编码我们才知道得到的隐含向量是什么,这时我们就可以通过变分自动编码器来解决这个问题。

其实原理特别简单,只需要在编码过程给它增加一些限制,迫使其生成的隐含向量能够粗略的遵循一个标准正态分布,这就是其与一般的自动编码器最大的不同。

这样我们生成一张新图片就很简单了,我们只需要给它一个标准正态分布的随机隐含向量,这样通过解码器就能够生成我们想要的图片,而不需要给它一张原始图片先编码。

在实际情况中,我们需要在模型的准确率上与隐含向量服从标准正态分布之间做一个权衡,所谓模型的准确率就是指解码器生成的图片与原图片的相似程度。我们可以让网络自己来做这个决定,非常简单,我们只需要将这两者都做一个loss,然后在将他们求和作为总的loss,这样网络就能够自己选择如何才能够使得这个总的loss下降。另外我们要衡量两种分布的相似程度,如何看过之前一片GAN的数学推导,你就知道会有一个东西叫KL divergence来衡量两种分布的相似程度,这里我们就是用KL divergence来表示隐含向量与标准正态分布之间差异的loss,另外一个loss仍然使用生成图片与原图片的均方误差来表示。

我们可以给出KL divergence 的公式

VAE--就是AutoEncoder的编码输出服从正态分布_数据_03


这里变分编码器使用了一个技巧“重新参数化”来解决KL divergence的计算问题。

VAE--就是AutoEncoder的编码输出服从正态分布_2d_04

这时不再是每次产生一个隐含向量,而是生成两个向量,一个表示均值,一个表示标准差,然后通过这两个统计量来合成隐含向量,这也非常简单,用一个标准正态分布先乘上标准差再加上均值就行了,这里我们默认编码之后的隐含向量是服从一个正态分布的。这个时候我们是想让均值尽可能接近0,标准差尽可能接近1。而论文里面有详细的推导如何得到这个loss的计算公式,有兴趣的同学可以去看看推导

下面是PyTorch的实现

reconstruction_function = nn.BCELoss(size_average=False)  # mse loss

def loss_function(recon_x, x, mu, logvar):
    """
    recon_x: generating images
    x: origin images
    mu: latent mean
    logvar: latent log variance
    """
    BCE = reconstruction_function(recon_x, x)
    # loss = 0.5 * sum(1 + log(sigma^2) - mu^2 - sigma^2)
    KLD_element = mu.pow(2).add_(logvar.exp()).mul_(-1).add_(1).add_(logvar)
    KLD = torch.sum(KLD_element).mul_(-0.5)
    # KL divergence
    return BCE + KLD

另外变分编码器除了可以让我们随机生成隐含变量,还能够提高网络的泛化能力。

最后是VAE的代码实现

class VAE(nn.Module):
    def __init__(self):
        super(VAE, self).__init__()

        self.fc1 = nn.Linear(784, 400)
        self.fc21 = nn.Linear(400, 20)
        self.fc22 = nn.Linear(400, 20)
        self.fc3 = nn.Linear(20, 400)
        self.fc4 = nn.Linear(400, 784)

    def encode(self, x):
        h1 = F.relu(self.fc1(x))
        return self.fc21(h1), self.fc22(h1)

    def reparametrize(self, mu, logvar):
        std = logvar.mul(0.5).exp_()
        if torch.cuda.is_available():
            eps = torch.cuda.FloatTensor(std.size()).normal_()
        else:
            eps = torch.FloatTensor(std.size()).normal_()
        eps = Variable(eps)
        return eps.mul(std).add_(mu)

    def decode(self, z):
        h3 = F.relu(self.fc3(z))
        return F.sigmoid(self.fc4(h3))

    def forward(self, x):
        mu, logvar = self.encode(x)
        z = self.reparametrize(mu, logvar

标签:编码器,AutoEncoder,nn,--,self,VAE,生成,我们,图片
From: https://blog.51cto.com/u_11908275/6405436

相关文章

  • tflearn tensorflow LSTM predict sin function
    from__future__importdivision,print_function,absolute_importimporttflearnimportnumpyasnpimportmathimportmatplotlibmatplotlib.use('Agg')importmatplotlib.pyplotaspltimporttensorflowastfstep_radians=0.001steps_of_histor......
  • python扫描proxy并获取可用代理ip列表
    mac或linux下可以work的代码如下:#coding=utf-8importrequestsimportrefrombs4importBeautifulSoupasbsimportQueueimportthreadingimportrandomimportreheaders_useragents=[]headers_referers=[]headers_referers.append('http://www.google.com/?q......
  • DGA GAN——GAN在安全中的应用
    DGA的模型:https://github.com/Yuren-Zhong/DeepDGACNN、LSTM、双向LSTM论文可以看https://openreview.net/pdf?id=BJLmN8xRWDGAGAN的论文:https://arxiv.org/pdf/1610.01969.pdf 国内的一些实验demohttp://www.itboth.com/d/fuE77fIBNvAn使用的是LSTM,但是效果不是很好有时间自......
  • cylance做的机器学习相关材料汇总
    https://www.cylance.com/en_us/products/our-products/protect----threatzero.html产品介绍关键!!!! https://www.blackhat.com/docs/us-16/materials/us-16-Wolff-Applied-Machine-Learning-For-Data-Exfil-And-Other-Fun-Topics.pdf实验室做的东西 https://www.slideshare.net/......
  • 非监督异常点检测算法总结——没有想到矩阵分解和编码解码器也是一种思路
    非监督异常点检测算法总结 一、基于密度1) d(p,o):两点p和o之间的距离;2)k-distance:第k距离 对于点p的第k距离dk(p)定义如下:p的第k距离,也就是距离p第k远的点的距离,如图。  3)k-distanceneighborhoodofp:第k距离邻域 点p的第k距离邻域Nk(p),就是p的第k距离即以内的所有点,包括......
  • GAN的原理入门
    GAN的基本原理其实非常简单,这里以生成图片为例进行说明。假设我们有两个网络,G(Generator)和D(Discriminator)。正如它的名字所暗示的那样,它们的功能分别是:G是一个生成图片的网络,它接收一个随机的噪声z,通过这个噪声生成图片(如正态分布,auto-encoder是中间输出是一般也是),记做G(z)。D是一个......
  • Use trained sklearn model with pyspark
    Usetrainedsklearnmodelwithpyspark frompysparkimportSparkContextimportnumpyasnpfromsklearnimportensembledefbatch(xs):yieldlist(xs)N=1000train_x=np.random.randn(N,10)train_y=np.random.binomial(1,0.5,N)model=ensemb......
  • 查 101.201.62.30 IP信誉方法
    查101.201.62.30IP信誉方法https://www.virustotal.com/#/ip-address/101.201.62.30https://talosintelligence.com/reputation_center/lookup?search=101.201.62.30https://x.threatbook.cn/ip/101.201.62.30......
  • 数据不够怎么训练深度学习模型?不妨试试迁移学习 ——重用神经网络的结构2
    数据不够怎么训练深度学习模型?不妨试试迁移学习本质就是这个图!pretrainedmodel就是你截取的部分神经网络模型(迁移学习),而nanonet就是你自己加入的网络层。随着深度学习技术在机器翻译、策略游戏和自动驾驶等领域的广泛应用和流行,阻碍该技术进一步推广的一个普遍性难题也日渐凸显:训......
  • 1、Ansible安装及Ansible各模块作用、使用方法
    Ansible功能1、批量执行远程命令,可以对远程的多台主机同时进行命令的执行2、批量安装和配置软件服务,可以对远程的多台主机进行自动化的方式配置和管理各种服务3、编排高级的企业级复杂的IT架构任务,Ansible的Playbook和role可以轻松实现大型的IT复杂架构4、提供自动化运维......