基于Pytorch的自编码(AutoEncoder)学习

欢迎学习交流!
邮箱: z…@1…6.com
网站: https://zephyrhours.github.io/

前言

笔者在学习深度学习过程中,首先针对AutoEncoder进行了简单的学习,虽然网上有很多相关资料,但是绝大多部分写的很粗,尤其是包含代码和详细介绍的少之又少。不过笔者发现一篇博文写的非常不错,非常适合新手学习和了解自编码,博客后面会附生原文链接,感兴趣的朋友可以看一下!

一、什么是自编码(What is AutoEnconder)?

自编码器( Autoencoder) 最原始的概念很简单,简单来说就是将一组数据输入神经网络中,然后经过神经网络训练后,得到的输出数据输入数据一模一样。整个自编码器( Autoencoder) 可以拆解成 编码器 (Encoder)解码器(Decoder) 两个神经网络。编码器 吃进的原始数据 在经过神经网络后,原始数据就会被压缩成一个维度较小的向量Z,这部分就是编码的整个过程;然后将向量Z输入解码器中,将向量Z还原成原始数据大小。虽然听起来很容易,但是具体的实施过程确是相对有点复杂,需要具有一定的数学功底,具体过程可以通过下面的这个图来简单说明。
请添加图片描述

1. Encoder

为了方便初学者了解,下面笔者以上图为例子,进行简单的说明。其实整个编码的过程就是负责将原始数据X进行输入,然后根据网络模型对其进行压缩,将原始高维度的数据X压缩成低维度数据C,而这些低维度数据(也就是上面图中的C)通常习惯上被称为隐层空间数据 (latent vector),原始数据经过非线性隐含层(Hidden layer)的激活函数操作后,原始数据就会被转换到一个低维度空间,这个空间被认为是高级特征空间。这里有点类似PCA对高维度数据压缩的感觉,可以理解为编码就是将原始数据转换到特征空间。但是不同之处在于Enconder是非线性的降维变换,这点不同于PCA变换。

2. Decoder

解码就是将原始隐含层数据转换回原始数据空间,是一个将低维度数据像高维度数据转换的过程,跟PCA变换的后一段,利用特征向量与特征值对数据进行投影重构的过程。但是不同之处在于PCA变化改变了高维度数据的初始维度,而经过自编码后得到的数据是与原始数据的维度是相同的。

对于衡量自编码的工作状态就需要用到损失函数来对其进行评估,具体这里不再赘述。下面直接放上具体的自编码代码和具体实验结果,给初学者参考。

二、autoEnconder 源码

下面是基于MNIST数据编写的一个简单自编码(autoEnconder)代码,初学者可以配置好相应环境后,直接拿去使用。有点需要提的是,强烈建议windows 用户使用anaconda来安装,因为这个anaconda除了内置了一些必要的库环境外,还可以根据用户需求进行环境虚拟,这样就可以根据不同的项目需求单独设置相应环境,免去了重新安装、各种bug的烦恼。编辑器建议使用Pycharm,笔者认为这是一个非常优秀的编辑器,当然还有许多不错的编辑器,用户根据自己的需求自行挑选就可以。笔者使用的开发环境具体如下:

版本要求:

  • Python 3.7
  • Pytorch 1.8.1

具体代码:

# Author: Zephyr Hou
# Time: 2021-08-16

import os
import torch
import torchvision
from torch import nn
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision.datasets import MNIST
from torchvision.utils import save_image

if not os.path.exists('./mlp_img'):
    os.mkdir('./mlp_img')


# Parameter Setting
num_epochs = 100
batch_size = 128
learning_rate = 1e-3


def to_img(x):
    x = 0.5 * (x + 1)
    x = x.clamp(0, 1)
    x = x.view(x.size(0), 1, 28, 28)
    return x


img_transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize([0.5], [0.5])
])

# Mnist digits dataset
train_data = torchvision.datasets.MNIST(
    root='./data/mnist/',
    train=True,
    transform=torchvision.transforms.ToTensor(),  # converts a PIL.Image or numpy.ndarry to torch.FloatTensor(C x H x W)
    download=True,
)


dataLoader = DataLoader(train_data, batch_size=batch_size, shuffle=True)


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


model = autoEncoder().cuda()    # autoEncoder model
loss_func = nn.MSELoss()        # loss function
optimizer = torch.optim.Adam(
    model.parameters(), lr=learning_rate, weight_decay=1e-5)

for epoch in range(num_epochs):
    for data in dataLoader:
        img, _ = data
        img = img.view(img.size(0), -1)
        img = Variable(img).cuda()
        # ===================forward=====================
        output = model(img)
        loss = loss_func(output, img)
        # ===================backward====================
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    # ===================log========================
    print('epoch [{}/{}], loss:{:.4f}'.format(epoch + 1, num_epochs, loss.item()))
    if epoch % 10 == 0:
        pic = to_img(output.cpu().data)
        save_image(pic, './mlp_img/image_{}.png'.format(epoch))

        pic1 = to_img(img.data)
        save_image(pic1, './mlp_img/Ori_image_{}.png'.format(epoch))

三、编码效果对比

下面我们来看一下具体的效果,如下图所示,第一行的三张图是从MNIST数据中随机筛选的三组数据,第二行三张图是利用上述自编码分别学习1次,10次和20次后的效果展示。从下面数据可以看出,经过的训练次数越多,最后生成的图像与真实的图像越相似。这里单纯从效果来看,对于二维图像自编码有点类似滤波操作的效果,但是本质上是完全不同的,这点要加以区分。

请添加图片描述

请添加图片描述
参考文献:

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
PyTorch是一种深度学习框架,用于构建和训练神经网络模型。自编码器AutoEncoder)是一种可以进行无监督学习的神经网络模型,可以用PyTorch实现。在PyTorch中,可以使用torch.nn模块来构建自编码器模型。 一个完整的自编码器主要由两部分组成:编码器(Encoder)和解码器(Decoder)。编码器负责将输入数据进行压缩和特征提取,而解码器负责将编码后的特征重新构建为原始输入数据。 以下是一个简化的PyTorch自编码器模型的代码示例: ``` python class AutoEncoder(torch.nn.Module): def __init__(self): super(AutoEncoder, self).__init__() self.encoder = torch.nn.Sequential( torch.nn.Linear(input_size, hidden_size), # 编码器的输入层 torch.nn.ReLU(), # 编码器的激活函数 torch.nn.Linear(hidden_size, latent_size) # 编码器的输出层 ) self.decoder = torch.nn.Sequential( torch.nn.Linear(latent_size, hidden_size), # 解码器的输入层 torch.nn.ReLU(), # 解码器的激活函数 torch.nn.Linear(hidden_size, input_size) # 解码器的输出层 ) def forward(self, input): encoded = self.encoder(input) # 编码器的前向传播 decoded = self.decoder(encoded) # 解码器的前向传播 return decoded ``` 在这个示例中,编码器和解码器都是由全连接层(Linear)构成的。编码器的输入层将输入数据压缩为较低维度的特征(latent_size),解码器则将这些特征重新还原为原始的输入数据。 需要注意的是,上述的代码示例是一个简化的自编码器模型,实际应用中可能会有更多的层和复杂的结构。具体的自编码器模型的设计和参数设置可以根据具体的任务和数据集来进行调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独不懂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值