深度学习实战(五):使用自动编码器生成图像

举报
AiCharm 发表于 2023/05/14 14:53:30 2023/05/14
【摘要】 1. 项目简介  如果我们不需要所有这些标记的数据来训练我们的模型。我的意思是标记和分类数据需要太多的工作。不幸的是,大多数现有的模型,从支持向量机到卷积神经网络,都不能在没有它们的情况下进行训练。  除了一小部分的算法可以。这就是所谓的无监督学习(Unsupervised Learning)。无监督学习通过自己的方式从未标记的数据中推断出一个函数。最著名的无监督算法是K-Means,它被...

1. 项目简介

  如果我们不需要所有这些标记的数据来训练我们的模型。我的意思是标记和分类数据需要太多的工作。不幸的是,大多数现有的模型,从支持向量机到卷积神经网络,都不能在没有它们的情况下进行训练。

  除了一小部分的算法可以。这就是所谓的无监督学习(Unsupervised Learning)。无监督学习通过自己的方式从未标记的数据中推断出一个函数。最著名的无监督算法是K-Means,它被广泛用于将数据聚类,而PCA则是降维的首选方案。K-Means和PCA可能是有史以来最好的两种机器学习算法。而让它们更出色的是它们的简单性。如果你掌握了它们,你就会觉得:“为什么我没有早点想到呢?”

2. 自动编码器Autoencoders

  为了更好地理解自动编码器,我将提供一些代码以及解释。我们将使用 Pytorch 来构建和训练我们的模型。

import torch
from torch import nn, optim
from torch.autograd import Variable
from torch.nn import functional as F

  自动编码器是简单的神经网络,其输出就是其输入。就这么简单。它们的目标是学习如何重构输入数据。但它是如何帮助的呢?诀窍在于它们的结构。网络的第一部分是我们所说的编码器。它接收输入,并将其编码在一个低维的潜在空间中。第二部分(解码器)接收该矢量并对其进行解码,以产生原始输入。
image.png

  中间的向量(粉红色块)是我们想要的,因为它是输入的压缩表示。此外,我们可以应用它们来重现相同但有点不同甚至更好的数据。这方面的例子:

  1. 数据去噪,给他们提供一个有噪声的图像,并训练他们输出相同的图像,但没有噪声。
  2. 训练数据的增强
  3. 异常检测,在一个单一的类别上训练它们,使每一个异常点都有一个大的重建误差。

然而,自动编码器面临着与大多数神经网络相同的几个问题。它们倾向于过度拟合,并且受到梯度消失问题的影响。那么有什么解决办法吗?

3. 变分自动编码器 (VAE)

  VAE是一个相当好的、优雅的努力。它基本上增加了随机性,但不完全是。

  让我们进一步解释一下。变异自动编码器被训练来学习模拟输入数据的概率分布,而不是映射输入和输出的函数。然后,它从这个分布中取样,并将其送入解码器以生成新的输入数据样本。但是,等一下。当我听到概率分布时,我只想到了一件事。贝叶斯。是的,贝叶斯法则再一次成为主要原则。顺便说一句,我无意夸大其词,但贝叶斯公式是有史以来唯一最好的方程式。而且我不是在开玩笑。它无处不在。如果你不知道是什么,请查一查。回到变分自动编码器。我想下面的图片会解释清楚了。
image.png

  你有了它。一个随机的神经网络。在我们建立一个自己的生成新图像的例子之前,我们应该再讨论一些细节。

  VAE的一个关键方面是损失函数。最常见的是,它由两部分组成。重建损失衡量重建的数据与原始数据的不同程度(例如二进制交叉熵)。KL-散度 试图使这个过程正规化,并使重建的数据尽可能地多样化。

def loss_function(recon_x, x, mu, logvar) -> Variable:
    BCE = F.binary_cross_entropy(recon_x, x.view(-1, 784))
    KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
    KLD /= BATCH_SIZE * 784

    return BCE + KLD

  另一个重要方面是如何训练模型。困难的出现是因为变量是注定的,而是随机的,而梯度下降通常不以这种方式工作。
  为了解决这个问题,我们使用参数化归一化。潜在向量(z)将等于我们分布的学习平均数(μ)加上学习标准差(σ)乘以(ε),其中ε遵循正态分布。我们对样本进行重新参数化,使随机性与参数无关。

def reparameterize(self, mu: Variable, logvar: Variable) -> Variable:

        #mu :  mean matrix
        #logvar :  variance matrix
        if self.training:
            std = logvar.mul(0.5).exp_()  # type: Variable
            eps = Variable(std.data.new(std.size()).normal_())
            return eps.mul(std).add_(mu)
        else:
            return mu

4. 使用自动编码器生成图像

  在我们的例子中,我们将尝试使用VAE来生成新的图像。我们将使用MNIST数据集,重建的图像将是手写的数字。正如我已经告诉你的,我使用Pytorch作为一个框架,除了熟悉之外,没有什么特别的原因。首先,我们应该定义我们的层。

def __init__(self):
        super(VAE, self).__init__()

        # ENCODER
        self.fc1 = nn.Linear(784, 400)
        self.relu = nn.ReLU()
        self.fc21 = nn.Linear(400, 20)  # mu layer
        self.fc22 = nn.Linear(400, 20)  # logvariance layer

        # DECODER
        self.fc3 = nn.Linear(20, 400)
        self.fc4 = nn.Linear(400, 784)
        self.sigmoid = nn.Sigmoid()

  正如你所看到的,我们将使用一个非常简单的网络,只有密集层(在pytorch的情况下为线性)。下一步是建立运行编码器和解码器的函数。

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

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

def forward(self, x: Variable) -> (Variable, Variable, Variable):
    mu, logvar = self.encode(x.view(-1, 784))
    z = self.reparameterize(mu, logvar)
    return self.decode(z), mu, logvar

  最后我们可以训练我们的模型并看到我们生成的图像。

optimizer = optim.Adam(model.parameters(), lr=1e-3)

def train(epoch):
    model.train()
    train_loss = 0

    for batch_idx, (data, _) in enumerate(train_loader):
        data = Variable(data)
        optimizer.zero_grad()
        recon_batch, mu, logvar = model(data)
        loss = loss_function(recon_batch, data, mu, logvar)
        loss.backward()
        train_loss += loss.data[0]
        optimizer.step()


def test(epoch):
    model.eval()
    test_loss = 0

    for i, (data, _) in enumerate(test_loader):
        data = Variable(data, volatile=True)
        recon_batch, mu, logvar = model(data)
        test_loss += loss_function(recon_batch, data, mu, logvar).data[0]

for epoch in range(1, EPOCHS + 1):
    train(epoch)
    test(epoch)

  当训练完成后,我们执行测试功能来检查模型的工作情况。事实上,它做得很好,构建的图像与原始图像几乎完全一样,我相信没有人能够在不了解整个故事的情况下把它们分开。

  下图第一行是原始照片,第二行是制作的照片。
image.png

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。