AE自编码器代码练习注释

 

AEmain函数

import torch
from torch.utils.data import DataLoader #自定义自己读取数据的方法,集成类,封装到dataloader
from torchvision import transforms, datasets
#transforms 常用的图片变换,裁剪旋转
#datasets 构建计算机视觉模型,加载数据的函数以及常用的数据集接口
from ae import AE
from torch import nn, optim
#optim优化器,优化算法封装成的包,把优化的参数以及使用到的学习率传入函数中
#反向传播前利用优化器对参数梯度进行清零,反向传播结束后利用优化器对参数更新
#对神经网络参数的操作可以直接在优化器上进行

import matplotlib.pyplot as plt
#可视化工具,绘图

plt.style.use("ggplot")
#设置plt风格

def main(epoch_num):
    # 下载mnist数据集
    mnist_train = datasets.MNIST('mnist', train=True, transform=transforms.Compose([
        transforms.ToTensor()]), download=True)
    '''   
   ‘root’
    True, 下载训练集 trainin.pt; 如果是False,下载测试集 test.pt; 默认是True
    transforms.Compose()类。这个类的主要作用是串联多个图片变换的操作。
    transform:一系列作用在PIL图片上的转换操作,返回一个转换后的版本
    transforms.ToTensor()将PIL Image或numpy.ndarray转换为tensor,并归一化到[0,1]之间
    download:是否下载到 root指定的位置,如果指定的root位置已经存在该数据集,则不再下载
    '''

    mnist_test = datasets.MNIST('mnist', train=False, transform=transforms.Compose([transforms.ToTensor()]), download=True)

    #查看每一个batch图片的规模
    x, label = iter(mnist_train).__next__()
    # 取出第一批(batch)训练所用的数据集
    print(' img : ', x.shape)
    # img :  torch.Size([32, 1, 28, 28]), 每次迭代获取32张图片,每张图大小为(1,28,28)

    # 准备工作 : 搭建计算流程
    device = torch.device('cuda')
    #torch.device代表将torch.Tensor分配到的设备的对象
    #cuda设备类型,gpu,设备序号没有就是当前设备

    model = AE().to(device)
    # 生成AE模型,并转移到GPU上去
    print('The structure of our model is shown below: \n')
    print(model)
    loss_function = nn.MSELoss()
    '''
    生成损失函数,度量预测值和真实值的差异,损失函数越小,模型鲁棒性越好
    前向传播输出预测值,损失函数计算出预测值和真实值之间的差异值,就是损失值
    得到损失值,模型通过反向传播更新参数,降低真实值和预测值之间的损失
    MSELoss均方损失函数就是均方差
    '''

    optimizer = optim.Adam(model.parameters(), lr=1e-3)  # 生成优化器,需要优化的是model的参数,学习率为0.001
    '''
    optimizer优化器对象保存当前的状态,并能根据计算得到的梯度更新参数
    model.base.parameters()将使用1e-3的学习率
    optim有SGD、adam、adagrad等优化器,参数传进去并进行优化
    '''

    # 开始迭代
    loss_epoch = []
    for epoch in range(epoch_num):
        # 每一代都要遍历所有的批次
        for batch_index, (x, _) in enumerate(mnist_train):
            # [b, 1, 28, 28]
            x = x.to(device)
            # 前向传播
            x_hat = model(x)  # 模型的输出,在这里会自动调用model中的forward函数
            loss = loss_function(x_hat, x)  # 计算损失值,即目标函数
            # 后向传播
            optimizer.zero_grad()  # 梯度清零,否则上一步的梯度仍会存在
            loss.backward()  # 后向传播计算梯度,这些梯度会保存在model.parameters里面
            optimizer.step()  # 更新梯度,这一步与上一步主要是根据model.parameters联系起来了

        loss_epoch.append(loss.item())
        if epoch % (epoch_num // 10) == 0:
            print('Epoch [{}/{}] : '.format(epoch, epoch_num), 'loss = ', loss.item())  # loss是Tensor类型
            # x, _ = iter(mnist_test).__next__()   # 在测试集中取出一部分数据
            # with torch.no_grad():
            #     x_hat = model(x)

    return loss_epoch

if __name__ == '__main__':
	epoch_num = 100
	loss_epoch = main(epoch_num=epoch_num)
	# 绘制迭代结果
	plt.plot(loss_epoch)
	plt.xlabel('epoch')
	plt.ylabel('loss')
	plt.show()

ae.py

from torch import nn


class AE(nn.Module):

    def __init__(self):
        # 调用父类方法初始化模块的state,后面的是类的构造方法
        super(AE, self).__init__()

        # 编码器 : [b, 784] => [b, 20]
        self.encoder = nn.Sequential(
            #可以允许整个容器视为单个模块,多个模块封装成一个模块,定义自己的网络层
            nn.Linear(784, 256),
            nn.ReLU(),
            nn.Linear(256, 20),
            nn.ReLU()
            #输入784神经元,输出到隐藏层256个神经元
            #激活函数relu
            #输入256个神经元,输出到输出层20个神经元
        )

        # 解码器 : [b, 20] => [b, 784]
        self.decoder = nn.Sequential(
            nn.Linear(20, 256),
            nn.ReLU(),
            nn.Linear(256, 784),
            nn.Sigmoid()
            # 图片数值取值为[0,1],不宜用ReLU
        )

    def forward(self, x):
        """
        向前传播部分, 在model_name(inputs)时自动调用
        :param x: the input of our training model
        :return: the result of our training model
        """
        batch_size = x.shape[0]   # 每一批含有的样本的个数
        # flatten
        # tensor.view()方法可以调整tensor的形状,但必须保证调整前后元素总数一致。view不会修改自身的数据,
        # 返回的新tensor与原tensor共享内存,即更改一个,另一个也随之改变。
        x = x.view(batch_size, 784)  # 一行代表一个样本

        # encoder
        x = self.encoder(x)

        # decoder
        x = self.decoder(x)

        # reshape
        x = x.view(batch_size, 1, 28, 28)
        return x

参考文献:

Python实战——VAE的理论详解及Pytorch实现_vae模型 pytorch_三只佩奇不结义的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值