生成对抗网络及其pytorch实现应用

1.GAN主要又生成器和鉴别器组成。

2.其流程主要有以下:

        初始化生成器和鉴别器

        重复:

                固定生成器,升级鉴别器

                固定鉴别器,升级生成器

链接:https://pan.baidu.com/s/1ZbANCQ58p42lzmcpc2r2-A?pwd=ttmf 
提取码:ttmf

此处我们也来实现一个经典的二次元头像生成器,上面是数据集。

我们使用深度卷积神经网络来作为鉴别器,使用反卷积神经网络作为生成器,DCGAN。

补充一下:

  1. 迭代次数(Iteration):迭代次数指的是模型在训练过程中参数更新的次数。在每次迭代中,模型会通过反向传播算法计算梯度并更新参数,这样模型就逐渐优化和学习。一次迭代通常是指模型使用一个 mini-batch(小批量)数据进行前向传播、计算损失、反向传播和参数更新的过程。

  2. Epoch:Epoch 是指整个数据集通过神经网络的前向传播和反向传播的总次数。当我们将整个数据集通过模型训练一轮(将数据集中的每个样本都经过一次前向传播和反向传播)时,就称为完成了一个 epoch。在实际训练中,一个 epoch 包含多个迭代过程。

举个例子,假设数据集有 1000 个样本,如果我们将 mini-batch 大小设置为 100,那么在完成一个 epoch 时,模型会执行 10 次迭代(1000个样本 / 100个样本 = 10 次迭代)。

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
from torchvision import datasets,transforms,models
import matplotlib.pyplot as plt
import os


# 图片预处理与图像加载
data_transform = transforms.Compose([
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
    ])


trainset = datasets.ImageFolder('faces', data_transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=5, shuffle=True, num_workers=0)


def imshow(inputs, picname):
    plt.ion()
    inputs = inputs / 2 + 0.5
    inputs = inputs.numpy().transpose((1, 2, 0))
    plt.imshow(inputs)
    plt.pause(0.01)
    plt.savefig(picname + ".jpg")
    plt.close()

# 从名为trainloader的数据加载器中获取下一个批次的数据,并将其中的第一个元素赋值给变量inputs。
# 通常这种代码用在深度学习的场景中,用于迭代数据加载器以获取训练数据的批次。
inputs,_ = next(iter(trainloader))
imshow(torchvision.utils.make_grid(inputs), "RealDataSample")

# 定义一个鉴别器
class D(nn.Module):
    def __init__(self,nc,ndf):
        super(D, self).__init__()
        # nc代表输入图片的通道数(例如,RGB图像的通道数为3)。
        # ndf代表模型中特征的数量,在这里用作卷积层中的特征维度倍增系数。
        # 例如,在第一层卷积之后,特征图的通道数为ndf,第二层卷积后的特征图通道数为ndf*2,依此类推
        self.layer1 = nn.Sequential(nn.Conv2d(nc, ndf, kernel_size=4, stride=2, padding=1),
                                    nn.BatchNorm2d(ndf), nn.LeakyReLU(0.2, inplace=True))

        self.layer2 = nn.Sequential(nn.Conv2d(ndf, ndf * 2, kernel_size=4, stride=2, padding=1),
                                    nn.BatchNorm2d(ndf*2), nn.LeakyReLU(0.2, inplace=True))

        self.layer3 = nn.Sequential(nn.Conv2d(ndf * 2, ndf * 4, kernel_size=4, stride=2, padding=1),
                                    nn.BatchNorm2d(ndf * 4), nn.LeakyReLU(0.2, inplace=True))

        self.layer4 = nn.Sequential(nn.Conv2d(ndf * 4, ndf * 8, kernel_size=4, stride=2, padding=1),
                                    nn.BatchNorm2d(ndf * 8), nn.LeakyReLU(0.2, inplace=True))

        self.fc = nn.Sequential(nn.Linear(256*6*6, 1), nn.Sigmoid())

    def forward(self,x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        out = out.view(-1, 256*6*6)
        out = self.fc(out)
        return out


class G(nn.Module):
    def __init__(self, nc, ngf, nz, feature_size):
        super(G, self).__init__()
        self.prj = nn.Linear(feature_size, nz*6*6)
        self.layer1 = nn.Sequential(nn.ConvTranspose2d(nz, ngf * 4, kernel_size=4, stride=2, padding=1),
                                    nn.BatchNorm2d(ngf*4), nn.ReLU())
        self.layer2 = nn.Sequential(nn.ConvTranspose2d(ngf * 4, ngf * 2, kernel_size=4, stride=2, padding=1),
                                    nn.BatchNorm2d(ngf * 2), nn.ReLU())
        self.layer3 = nn.Sequential(nn.ConvTranspose2d(ngf * 2, ngf, kernel_size=4, stride=2, padding=1),
                                    nn.BatchNorm2d(ngf), nn.ReLU())
        self.layer4 = nn.Sequential(nn.ConvTranspose2d(ngf, nc, kernel_size=4, stride=2, padding=1),
                                    nn.Tanh())

    def forward(self,x):
        out = self.prj(x)
        out = out.view(-1, 1024, 6, 6)
        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        return out


# d = D(3, 32):创建了一个判别器对象d,将输入图像的通道数设为3(通常表示RGB图像),
# ndf参数设为32,用于定义模型中特征的数量。
# 这意味着判别器的第一层卷积输出的特征图通道数为32,之后逐层增加。
# g = G(3, 128, 1024, 100):创建了一个生成器对象g,将输入图像的通道数设为3(通常表示RGB图像),
# ngf参数设为128作为模型中特征的数量,nz设为1024表示噪声向量的维度,
# feature_size设为100表示生成器前向传播时的特征参数大小。
d = D(3, 32)
g = G(3, 128, 1024, 100)


criterion = nn.BCELoss()
d_optimizer = torch.optim.Adam(d.parameters(), lr=3e-4)
g_optimizer = torch.optim.Adam(g.parameters(), lr=3e-4)


def train(d, g, criterion, d_optimizer, g_optimizer,epochs=1, show_every=1000, print_every=10):
    iter_count = 0
    for epoch in range(epochs):
            for inputs,_ in trainloader:
                # 训练判别器(D):
                # 计算真实图像通过判别器后的输出。将真实标签设为1,计算判别器对真实图像的损失d_loss_real。
                # 计算生成图像通过判别器后的输出。将生成标签设为0,计算判别器对生成图像的损失d_loss_fake。
                # 将两者的损失相加得到总的判别器损失d_loss。
                # 对判别器的参数进行梯度清零、反向传播、更新参数过程。
                # 训练生成器(G):
                # 重新生成一组噪声数据fake_inputs。
                # 将生成的假图像通过判别器,得到输出。
                # 将生成标签设为1,计算生成器的损失g_loss。
                # 对生成器的参数进行梯度清零、反向传播、更新参数过程


                real_inputs = inputs
                # 重新生成噪声数据 fake_inputs
                fake_inputs = g(torch.randn(5,100))

                real_labels = torch.ones(real_inputs.size(0), 1)
                fake_labels = torch.zeros(5, 1)

                # 将 real_inputs 输入到判别器 d 中,得到判别器对真实数据的输出 real_outputs。
                real_outputs = d(real_inputs)
                d_loss_real = criterion(real_outputs, real_labels)
                real_scores = real_outputs

                fake_outputs = d(fake_inputs)
                d_loss_fake = criterion(fake_outputs, fake_labels)
                fake_score = fake_outputs

                d_loss = d_loss_real + d_loss_fake

                d_optimizer.zero_grad()
                d_loss.backward()
                d_optimizer.step()

                fake_inputs = g(torch.randn(5, 100))
                outputs = d(fake_inputs)

                real_labels = torch.ones(outputs.size(0), 1)
                g_loss = criterion(outputs, real_labels)

                g_optimizer.zero_grad()
                g_loss.backward()
                g_optimizer.step()


                if iter_count % show_every == 0:
                    print('Epoch: {},Iter: {},D: {:.4}, G: {:.4}'.format(
                        epoch, iter_count, d_loss.item(), g_loss.item()))

                    picname = "Epoch_" + str(epoch) + "Iter_" + str(iter_count)
                    imshow(torchvision.utils.make_grid(fake_inputs.data),picname)

                if iter_count % print_every == 0:
                    print('Epoch: {},Iter: {},D: {:.4}, G: {:.4}'.format(
                        epoch, iter_count, d_loss.item(), g_loss.item()))

                iter_count += 1

            print("Finished")


train(d, g, criterion, d_optimizer, g_optimizer, epochs=300)



  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值