开发 | 深度学习自动编码器还能用于数据生成？这篇文章告诉你答案

AI 科技评论按：本文作者廖星宇，原载于作者知乎专栏，经授权发布。

什么是自动编码器

• 跟数据相关程度很高，这意味着自动编码器只能压缩与训练数据相似的数据，这个其实比较显然，因为使用神经网络提取的特征一般是高度相关于原始的训练集，使用人脸训练出来的自动编码器在压缩自然界动物的图片是表现就会比较差，因为它只学习到了人脸的特征，而没有能够学习到自然界图片的特征；
• 压缩后数据是有损的，这是因为在降维的过程中不可避免的要丢失掉信息；

自动编码器的结构

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

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

http://t.cn/RK5gxpM

变分自动编码器(Variational Auto Encoder)

https://arxiv.org/pdf/1606.05908.pdf

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

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) return self.decode(z), mu, logvar

VAE的结果比普通的自动编码器要好很多，下面是结果：

VAE的缺点也很明显，他是直接计算生成图片和原始图片的均方误差而不是像GAN那样去对抗来学习，这就使得生成的图片会有点模糊。现在已经有一些工作是将VAE和GAN结合起来，使用VAE的结构，但是使用对抗网络来进行训练，具体可以参考一下这篇论文：

https://arxiv.org/pdf/1512.09300.pdf

http://t.cn/RK5gxpM

http://t.cn/RtoJRAa

0 条评论

相关文章

1.4K7

5798

1110

991

物体计数--Learning To Count Objects in Images

Learning To Count Objects in Images NIPS 2010 http://www.robots.ox.ac.uk/~v...

2529

1432

832

983

4124