Pytorch袖珍手册之八

2021-08-24  本文已影响0人  深思海数_willschang
pytorch pocket reference
原书下载地址:
我用阿里云盘分享了「OReilly.PyTorch.Pocket.R...odels.149209000X.pdf」,你可以不限速下载🚀
复制这段内容打开「阿里云盘」App 即可获取
链接:https://www.aliyundrive.com/s/NZvnGbTYr6C

第四章 基于已有网络设计进行神经网络应用开发

这一章主要通过三个例子来表现Pytorch在神经网络开发应用的便捷性及高效性。

GAN,基于Fashion MNIST数据生成图片

深度学习另一个应用场景就是生成学习(generative learning),主要通过模型来生成数据,如图片,音乐,文本和时间系列数据等。

在本章节的例子中,我们通过构建一个GAN模型生成如Fashion-MNIST里的图片数据。

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import torch
import torch.nn as nn
from torch import optim
from torch.utils.data import DataLoader
from torchvision import datasets,transforms
from torchvision.utils import make_grid


CODING_SIZE = 100
BATCH_SIZE = 32
IMAGE_SIZE = 64

device = 'cuda' if torch.cuda.is_available() else 'cpu'

# 定义transforms
transform = transforms.Compose(
    [
        transforms.Resize(IMAGE_SIZE),
        transforms.ToTensor()
    ]
)

dataset = datasets.FashionMNIST(
    './data',
    train=True,
    download=True,
    transform=transform
)

dataloader = DataLoader(
        dataset,
        batch_size=BATCH_SIZE,
        shuffle=True,
        num_workers=0 # 在windows下无法用多进程
    )


# 数据可视化,查看数据情况
data_batch, labels_batch = next(iter(dataloader))
# batch_size 32, 4*8
grid_img = make_grid(data_batch, nrow=8)
plt.figure(figsize=(10,10))
plt.imshow(grid_img.permute(1, 2, 0))
Fashion MNIST
# 生成器模型构建
class Generator(nn.Module):
    def __init__(self, coding_sz):
        super(Generator, self).__init__()
        self.net = nn.Sequential(
            # 反卷积操作
            nn.ConvTranspose2d(coding_sz, 1024, 1, 1),
            nn.BatchNorm2d(1024),
            nn.ReLU(),
            nn.ConvTranspose2d(1024, 512, 4, 2, 1),
            nn.BatchNorm2d(512),
            nn.ReLU(),
            nn.ConvTranspose2d(512, 256, 4, 2, 1),
            
            nn.BatchNorm2d(256),
            nn.ReLU(),
            nn.ConvTranspose2d(256, 128, 4, 2, 1),
            nn.BatchNorm2d(128),
            nn.ReLU(),
            nn.ConvTranspose2d(128, 1, 4, 2, 1),
            nn.Tanh()       
        )
        
    def forwar(self, input):
        return self.net(input)
    
netG = Generator(CODING_SIZE).to(device)


# 判别器模型构建
class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.net = nn.Sequential(
            nn.Conv2d(1, 128, 4, 2, 1),
            nn.LeakyReLU(0.2),
            nn.Conv2d(128, 256, 4, 2, 1),
            nn.BatchNorm2d(256),
            nn.LeakyReLU(0.2),
            nn.Conv2d(256, 512, 4, 2, 1),
            nn.BatchNorm2d(512),
            nn.LeakyReLU(0.2),
            nn.Conv2d(512, 1024, 4, 2, 1),
            nn.BatchNorm2d(1024),
            nn.LeakyReLU(0.2),
            nn.Conv2d(1024, 1, 4, 1, 0),
            nn.Sigmoid()
        )
        
    def forward(self, input):
        return self.net(input)
    
netD = Discriminator().to(device)

# DCGAN paper found that it helps to initialize the weights 
def weights_init(m):
    classname = m.__class__.__name__
    if classname.find('Conv') != -1:
        nn.init.normal_(m.weight.data, 0.0, 0.02)
    elif classname.find('BatchNorm') != -1:
        nn.init.normal_(m.weight.data, 1.0, 0.02)
        nn.init.constant_(m.bias.data, 0)
        

netG.apply(weights_init)
netD.apply(weights_init)
“”“
Generator(
  (net): Sequential(
    (0): ConvTranspose2d(100, 1024, kernel_size=(1, 1), stride=(1, 1))
    (1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (2): ReLU()
    (3): ConvTranspose2d(1024, 512, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))
    (4): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (5): ReLU()
    (6): ConvTranspose2d(512, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))
    (7): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (8): ReLU()
    (9): ConvTranspose2d(256, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))
    (10): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (11): ReLU()
    (12): ConvTranspose2d(128, 1, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))
    (13): Tanh()
  )
)
============================================================================================
Discriminator(
  (net): Sequential(
    (0): Conv2d(1, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))
    (1): LeakyReLU(negative_slope=0.2)
    (2): Conv2d(128, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))
    (3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (4): LeakyReLU(negative_slope=0.2)
    (5): Conv2d(256, 512, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))
    (6): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (7): LeakyReLU(negative_slope=0.2)
    (8): Conv2d(512, 1024, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))
    (9): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (10): LeakyReLU(negative_slope=0.2)
    (11): Conv2d(1024, 1, kernel_size=(4, 4), stride=(1, 1))
    (12): Sigmoid()
  )
)
”“”
# 训练模型
"""
In each epoch, we will first train the discriminator with a real batch of data, 
then use the generator to create a fake batch, and then train the discriminator with the generated fake batch of data. 
Lastly, we will train the generator NN to produce better fakes.
"""
# 定义损失函数及优化器
criterion = nn.BCELoss()
optimizerG = optim.Adam(netG.parameters(), lr=0.0002, betas=(0.5, 0.999))
optimizerD = optim.Adam(netD.parameters(), lr=0.0001, betas=(0.5, 0.999))

# 定义真假数据标签值
real_labels = torch.full((BATCH_SIZE,), 1., dtype=torch.float, device=device)
fake_labels = torch.full((BATCH_SIZE,), 0., dtype=torch.float, device=device)


G_losses = []
D_losses = []
D_real = []
D_fake = []
N_EPOCHS = 5

z = torch.randn((BATCH_SIZE, 100)).view(-1, 100, 1, 1).to(device)
test_out_images = []

for epoch in range(N_EPOCHS):
    print(f'Epoch: {epoch}')
    for i, batch in enumerate(dataloader):
        if (i%200==0):
            print(f'batch: {i} of {len(dataloader)}')
    
        # 训练判别器,基于真数据
        netD.zero_grad()
        real_images = batch[0].to(device) *2. - 1.
        output = netD(real_images).view(-1) 
        errD_real = criterion(output, real_labels)
        D_x = output.mean().item()

        # 训练判别器,基于假数据
        noise = torch.randn((BATCH_SIZE, CODING_SIZE))
        noise = noise.view(-1,100,1,1).to(device)
        fake_images = netG(noise)
        output = netD(fake_images).view(-1) 
        errD_fake = criterion(output, fake_labels)
        D_G_z1 = output.mean().item()
        errD = errD_real + errD_fake
        errD.backward(retain_graph=True) 
        optimizerD.step()

        # 训练生成器,产生更逼真数据
        netG.zero_grad()
        output = netD(fake_images).view(-1) 
        errG = criterion(output, real_labels)
        errG.backward() 
        D_G_z2 = output.mean().item()
        optimizerG.step()

        # 保存中间变量值,用于后续画图
        G_losses.append(errG.item())
        D_losses.append(errD.item())

        D_real.append(D_x)
        D_fake.append(D_G_z2)

    test_images = netG(z).to('cpu').detach() 
    test_out_images.append(test_images)
        
         
grid_img = make_grid((test_out_images[0]+1.)/2., nrow=8)
plt.imshow(grid_img.permute(1, 2, 0)) 
image.png
plt.figure(figsize=(10,5))
plt.title("Generator and Discriminator Loss During Training")
plt.plot(G_losses,label="G")
plt.plot(D_losses,label="D")
plt.xlabel("iterations")
plt.ylabel("Loss")
plt.legend()
plt.show()
image.png
plt.figure(figsize=(10,5))
plt.title("Discriminator Results")
plt.plot(D_real,label="D(real)")
plt.plot(D_fake,label="D(fake)")
plt.xlabel("iterations")
plt.ylabel("Percentage Real")
plt.legend()
plt.show()
image.png
grid_img = make_grid((test_out_images[4]+1.)/2., nrow=8)
plt.imshow(grid_img.permute(1, 2, 0))
image.png
上一篇下一篇

猜你喜欢

热点阅读