第G1周:生成对抗网络(GAN)入门

一、理论基础

1.什么是GAN

GAN(生成对抗网络)是一种神经网络架构,它的设计灵感来自于博弈论的思想。这种网络由两个关键组件组成:生成器(Generator)和判别器(Discriminator)。生成器的任务是从随机噪声中生成与真实数据相似的合成样本,而判别器则负责辨别给定的样本是真实数据还是生成器产生的人工样本。这两个组件通过反复对抗性的训练相互影响和提升。

在训练过程中,生成器努力生成越来越逼真的样本,而判别器则不断提高辨别真实与生成样本的能力。这种博弈过程推动着两者的不断进步,直到最终生成器生成的样本足够逼真,使得判别器无法有效地区分真实和生成的样本。这就达到了一个状态,即生成器能够以惊人的逼真度产生伪造的真实样本。

GAN的应用广泛,包括图像生成、风格转换、图像编辑等领域,其独特的博弈训练方法使其在生成高质量数据方面表现出色。

2.什么是生成器

在生成对抗网络(GANs)中,生成器(G)是一个关键组件,其任务是利用随机噪声(通常表示为z)作为输入,并通过不断的学习和拟合过程生成一个与真实样本在尺寸和分布上相似的伪造样本G(z)。生成器本质上是一种生成式方法的模型,它通过学习数据的分布和分布参数来生成新的样本。

从数学的角度来看,生成式方法首先对数据的显式或隐含变量进行分布假设,然后通过将真实数据输入模型并训练变量和参数,最终得到一个学习后的近似分布。这个学习后的分布可以被用来生成新的数据。与传统的数学方法不同,生成器使用机器学习的方法,通过不断学习真实数据并修正模型,最终得到一个可以执行样本生成任务的学习后模型,这一过程可能相对较为直观。

生成器通过借助现有数据生成新数据,例如从随机产生的一组数字向量(称为潜在空间 latent space)中生成图像、音频等数据。在构建生成器时,首先需要明确生成的目标,然后将生成的结果传递给判别器网络进行进一步处理。这协同的过程在训练中推动生成器生成越来越逼真的样本。

3.什么是判别器

在生成对抗网络(GANs)中,判别器(D)是另一个关键的组件,其任务是对于输入的样本x输出一个介于[0,1]之间的概率数值D(x)。这个样本x可能是来自原始数据集中的真实样本,也可能是由生成器G生成的人工样本G(z)。通常的约定是,概率值D(x)越接近于1,表示此样本为真实样本的可能性越大;反之,概率值越小,则代表此样本为伪造样本的可能性越大。判别器因此是一个二分类的神经网络分类器,其目标是区分输入样本的真伪,而非判定样本的原始类别。这表明GAN是一个无监督学习过程,没有使用样本的类别信息。

判别器的任务是尝试区分接收到的数据是真实数据还是由生成网络生成的数据。它根据预定义的类别对输入进行分类,通常在GAN中是进行二分类。判别器的输出结果是一个介于0和1之间的数字,用来表示当前输入被认为是真实数据的可能性。当判别结果为1时,判别器认为输入来自真实数据;反之,如果判别结果接近0,则判别器将其视为生成数据。判别器的目标是不断优化以在这个对抗性的过程中更准确地区分真实和生成的样本。

4.原理

生成对抗网络(GAN)是博弈论和机器学习相结合的创新性产物,由Ian Goodfellow于2014年提出。这一算法的问世引起了广泛的研究热潮,表明人们对这种算法的认可和热切的研究兴趣。

研究者最初尝试通过计算机来实现自动生成数据的功能。早期的生成算法通常采用均方误差作为损失函数来衡量生成图片和真实图片之间的差距。然而,研究者发现,有时两张生成图片的均方误差相同,但它们的视觉效果却迥然不同。鉴于这种不足,Ian Goodfellow提出了生成对抗网络。

GAN的核心思想是由两个模型组成:生成模型(G)和判别模型(D)。生成模型首先接收随机噪声z作为输入,生成一张初级图片。然后,训练一代判别模型(D)进行二分类操作,将生成的图片判别为0,真实图片判别为1。为了欺骗一代判别器,生成模型开始优化。随着一代生成模型的进步,它成功欺骗判别模型1D,然后判别模型也会优化更新,升级为2D。这样的迭代过程不断进行,生成模型和判别模型相互对抗、相互优化,生成越来越逼真的样本,形成了一个动态的博弈过程。

GAN的原理在于通过这种对抗性训练,生成器学习生成逼真的数据,而判别器学习更好地区分真实和生成的数据。这种博弈过程使得GAN在生成高质量、逼真的数据方面取得了显著的成功。

二、代码实现

1.定义超参数

import os
import argparse
import numpy as np
import torch
import torch.nn as nn
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.utils import save_image
import torchvision.transforms as transforms
 
# 创建文件夹
os.makedirs('./output/images/', exist_ok=True)
os.makedirs('./output/', exist_ok=True)
os.makedirs('./data/MNIST/', exist_ok=True)
 
# 超参数配置
n_epochs = 50
batch_size = 64
lr = 0.0002
b1 = 0.5
b2 = 0.999
n_cpu = 2
latent_dim = 100
img_size = 28
channels = 1
sample_interval = 500
 
# 图像的尺寸:(1, 28, 28),和图像的像素面积:(784)
img_shape = (channels, img_size, img_size)
img_area = np.prod(img_shape)
 
# 设置cuda:(cuda:0)
cuda = True if torch.cuda.is_available() else False
print(cuda)
 

实现一个基本的GAN,主要负责设置超参数、创建文件夹、定义模型结构、加载数据以及设置训练过程中的一些参数。

  1. 创建文件夹:

    • os.makedirs('./output/images/', exist_ok=True): 创建用于保存生成图片的文件夹。
    • os.makedirs('./output/', exist_ok=True): 创建用于保存模型训练过程中的输出的文件夹。
    • os.makedirs('./data/MNIST/', exist_ok=True): 创建用于保存MNIST数据集的文件夹。
  2. 超参数配置:

    • n_epochs: 训练的总轮次。
    • batch_size: 每个批次中的样本数。
    • lr: 学习率。
    • b1, b2: Adam优化器的超参数。
    • n_cpu: 数据加载时使用的CPU数。
    • latent_dim: 生成器的输入噪声向量的维度。
    • img_size: 生成图片的尺寸。
    • channels: 输入图像的通道数。
    • sample_interval: 控制在训练过程中每隔多少个批次输出生成的样本。
  3. 图像的尺寸和像素面积:

    • img_shape: 图像的形状,这里是(1, 28, 28),表示灰度图像,尺寸为28x28。
    • img_area: 图像的像素面积,即宽度乘以高度。
  4. 设置cuda:

    • cuda = True if torch.cuda.is_available() else False: 判断是否可用GPU加速,如果可用则将cuda设置为True。这将影响后续模型的设备选择。

2.配置数据集

## mnist数据集下载
mnist = datasets.MNIST(root='./data/', 
                       train=True, 
                       download=True,
                       transform=transforms.Compose([transforms.Resize(img_size), transforms.ToTensor(), transforms.Normalize([0.5], [0.5])]))
# 配置数据到加载器
dataloader = DataLoader(mnist, batch_size=batch_size, shuffle=True)

3.定义鉴别器

'''
定义判别器 Discriminator
将图片28x28展开成784,然后通过多层感知器,
中间经过斜率设置为0.2的LeakyReLU激活函数,
最后接sigmoid激活函数得到一个0到1之间的概率进行二分类
'''
class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.model = nn.Sequential(
                     nn.Linear(img_area, 512),
                     nn.LeakyReLU(0.2, inplace=True),
                     nn.Linear(512, 256),
                     nn.LeakyReLU(0.2, inplace=True),
                     nn.Linear(256, 1),
                     nn.Sigmoid())
    
    def forward(self, img):
        img_flat = img.view(img.size(0), -1)  # 鉴别器输入是一个被view展开的(784)的一维图像:(64, 784)
        validity = self.model(img_flat)       # 通过鉴别器网络
        return validity                       # 鉴别器返回的是一个[0, 1]间的概率
 

定义判别器(Discriminator)模型,判别器是GAN中的一个关键组件,负责对输入的样本进行分类,判断它是真实样本还是生成器生成的伪造样本。

其结构如下:

  1. 输入层:将28x28的图像展开成784个像素的一维向量。
  2. 隐层1:包含512个神经元,通过LeakyReLU激活函数进行非线性变换。
  3. 隐层2:包含256个神经元,同样使用LeakyReLU激活函数。
  4. 输出层:包含1个神经元,经过Sigmoid激活函数得到一个在[0,1]范围内的概率值,用于进行二分类(真实或伪造)。

在前向传播(forward)过程中,输入图像首先通过view操作展平成一维向量,然后通过判别器模型进行前向计算,得到输出值(validity),表示输入样本为真实样本的概率。

在生成对抗网络(GAN)中,判别器是负责对输入样本进行分类的关键组件,其主要作用是区分真实数据和生成器生成的伪造数据。通过学习和不断提高对真实和伪造样本的分类准确性,判别器引导生成器生成更逼真的样本,形成一个动态的博弈过程。判别器的存在推动了整个系统的学习和优化,促使生成器生成更接近真实数据分布的高质量样本。因此,判别器在GAN中扮演着“警察”的角色,对生成器的输出进行评估,推动生成器生成更为逼真的数据。这种博弈性的学习过程使得GAN在生成高质量样本方面取得了显著的成功。

4.定义生成器

 
'''
定义生成器 Generator
输入一个100维的0~1之间的高斯分布,
然后通过第一层线性变换将其映射到256维,
然后通过LeakyReLU激活函数,
接着进行一个线性变换,
再经过一个LeakyReLU激活函数,
然后经过陷先变换将其变成784维,
最后经过Tanh激活函数,
是希望生成的假的图片数据分布,能够再-1~1之间。
'''
class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        # 模型中间块
        def block(in_feat, out_feat, normalize=True):
            layers = [nn.Linear(in_feat, out_feat)]
            if normalize:
                layers.append(nn.BatchNorm1d(out_feat, 0.8))
            layers.append(nn.LeakyReLU(0.2, inplace=True))
            return layers
        # prod():返回给定轴上的数组元素的乘积:1*28*28=784
        self.model = nn.Sequential(
                     *block(latent_dim, 128, normalize=False),
                     *block(128, 256),
                     *block(256, 512),
                     *block(512, 1024),
                     nn.Linear(1024, img_area),
                     nn.Tanh())
    
    # view():相当于numpy中的reshape,重新定义矩阵的形状:这里是reshape(64, 1,28, 28)
    def forward(self, z):                          # 输入的是(64, 100)的噪声数据
        imgs = self.model(z)                       # 噪声数据通过生成器模型
        imgs = imgs.view(imgs.size(0), *img_shape)  # reshape成(64, 1,28, 28)
        return imgs                                # 输出为64张大小为(1, 28, 28)的图像
 

定义了生成器(Generator)模型,生成器是GAN中另一个关键组件,其任务是通过输入的随机噪声生成逼真的样本,以欺骗判别器。

生成器的结构如下:

输入层:接收一个100维的、取值范围在[0,1]之间的高斯分布的随机噪声。
隐层1:包含128个神经元的线性变换,不使用批量归一化(normalize=False),并经过LeakyReLU激活函数。
隐层2:包含256个神经元的线性变换,使用批量归一化,并经过LeakyReLU激活函数。
隐层3:包含512个神经元的线性变换,使用批量归一化,并经过LeakyReLU激活函数。
隐层4:包含1024个神经元的线性变换,使用批量归一化,并经过LeakyReLU激活函数。
输出层:通过线性变换将1024维的输出映射到图像的784维,然后通过Tanh激活函数,将输出限制在[-1,1]的范围内。
在前向传播(forward)过程中,输入的随机噪声通过生成器模型,最终生成一张大小为(1, 28, 28)的逼真图像。这个过程中,批量归一化有助于加速训练收敛,LeakyReLU激活函数引入了非线性,Tanh激活函数将输出范围固定在[-1,1]内,符合常见的图像像素值范围。

生成器的目标是学会从随机噪声中生成与真实数据相似的图像,以愚弄判别器,从而形成生成对抗网络中的博弈过程。

5.模型的训练与保存

# 创建生成器、判别器对象
generator = Generator()
discriminator = Discriminator()
# 定义loss的度量方式(二分类的交叉熵)
criterion = torch.nn.BCELoss()
# 定义又换函数,学习率为0.0003
# betas: 用于计算梯度以及梯度平方的运行平均值的系数
optimizer_G = torch.optim.Adam(generator.parameters(), lr=lr, betas=(b1, b2))
optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=lr, betas=(b1, b2))
# 若有显卡,在cuda模式中运行
if torch.cuda.is_available():
    generator = generator.cuda()
    discriminator = discriminator.cuda()
    criterion = criterion.cuda()
 
 
# 进行多个epoch的训练
for epoch in range(n_epochs):
    for i, (imgs, _) in enumerate(dataloader):
        ''' 训练判别器 Train Discriminator '''
        # 分为两部分:1、真的图像判别为真;2、假的图像判别为假
        imgs = imgs.view(imgs.size(0), -1)
        real_img = Variable(imgs).cuda()
        real_label = Variable(torch.ones(imgs.size(0), 1)).cuda()
        fake_label = Variable(torch.zeros(imgs.size(0), 1)).cuda()
        # 计算真实图片的损失
        real_out = discriminator(real_img)
        loss_real_D = criterion(real_out, real_label)
        real_scores = real_out
        # 计算假的图片的损失
        # detach(): 从当前计算图中分离下来避免梯度传到G,因为G不用更新
        z = Variable(torch.randn(imgs.size(0), latent_dim)).cuda()
        fake_img = generator(z).detach()
        fake_out = discriminator(fake_img)
        loss_fake_D = criterion(fake_out, fake_label)
        fake_scores = fake_out
        # 损失函数和优化
        loss_D = loss_real_D + loss_fake_D
        optimizer_D.zero_grad()
        loss_D.backward()
        optimizer_D.step()
        
        ''' 训练生成器 Train Generator '''
        # 原理:目的是希望生成的假的图片被判别器判断为真的图片,
        # 在此过程中,将判别器固定,将假的图片传入判别器的结果与真实的label对应,
        # 反向传播更新的参数是生成网络里面的参数,
        # 这样可以通过更新生成网络里面的参数,来训练网络,使得生成的图片让判别器以为是真的, 这样就达到了对抗的目的
        z = Variable(torch.randn(imgs.size(0), latent_dim)).cuda()
        fake_img = generator(z)
        output = discriminator(fake_img)
        # 损失函数和优化
        loss_G = criterion(output, real_label)
        optimizer_G.zero_grad()
        loss_G.backward()
        optimizer_G.step()
        
        ''' 打印训练过程中的日志 '''
        # item():取出单元素张量的元素值并返回该值,保持原元素类型不变
        if (i + 1) % 300 == 0:
            print("[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f] [D real: %f] [D fake: %f]"
            % (epoch, n_epochs, i, len(dataloader), loss_D.item(), loss_G.item(), real_scores.data.mean(), fake_scores.data.mean()))
        # 保存训练过程中的图像
        batches_done = epoch * len(dataloader) + i
        if batches_done % sample_interval == 0:
            save_image(fake_img.data[:25], "./output/images/%d.png" % batches_done, nrow=5, normalize=True)
# 保存模型
torch.save(generator.state_dict(), './output/generator.pth')
torch.save(discriminator.state_dict(), './output/discriminator.pth')

三、结果展示

[Epoch 0/50] [Batch 299/938] [D loss: 1.062955] [G loss: 0.904519] [D real: 0.565589] [D fake: 0.370396]
[Epoch 0/50] [Batch 599/938] [D loss: 0.962778] [G loss: 1.388392] [D real: 0.740921] [D fake: 0.476253]
[Epoch 0/50] [Batch 899/938] [D loss: 1.157217] [G loss: 0.925423] [D real: 0.426990] [D fake: 0.159059]
[Epoch 1/50] [Batch 299/938] [D loss: 0.926703] [G loss: 1.032149] [D real: 0.591346] [D fake: 0.280134]
[Epoch 1/50] [Batch 599/938] [D loss: 0.969020] [G loss: 1.608932] [D real: 0.796820] [D fake: 0.508097]
[Epoch 1/50] [Batch 899/938] [D loss: 1.055912] [G loss: 0.997927] [D real: 0.569173] [D fake: 0.299630]
[Epoch 2/50] [Batch 299/938] [D loss: 0.792568] [G loss: 1.304700] [D real: 0.637448] [D fake: 0.211832]
[Epoch 2/50] [Batch 599/938] [D loss: 0.802352] [G loss: 1.578910] [D real: 0.721856] [D fake: 0.328017]
[Epoch 2/50] [Batch 899/938] [D loss: 0.824679] [G loss: 1.094702] [D real: 0.610786] [D fake: 0.151364]
[Epoch 3/50] [Batch 299/938] [D loss: 0.942010] [G loss: 2.572878] [D real: 0.857348] [D fake: 0.514068]
[Epoch 3/50] [Batch 599/938] [D loss: 0.834547] [G loss: 1.283262] [D real: 0.629549] [D fake: 0.215891]
[Epoch 3/50] [Batch 899/938] [D loss: 1.420294] [G loss: 0.657411] [D real: 0.353584] [D fake: 0.097988]
[Epoch 4/50] [Batch 299/938] [D loss: 0.751580] [G loss: 2.135909] [D real: 0.814683] [D fake: 0.370327]
[Epoch 4/50] [Batch 599/938] [D loss: 0.937634] [G loss: 1.849720] [D real: 0.808991] [D fake: 0.457426]
[Epoch 4/50] [Batch 899/938] [D loss: 0.817051] [G loss: 1.892973] [D real: 0.749581] [D fake: 0.351872]
[Epoch 5/50] [Batch 299/938] [D loss: 1.443673] [G loss: 2.338635] [D real: 0.803128] [D fake: 0.661811]
[Epoch 5/50] [Batch 599/938] [D loss: 0.652590] [G loss: 2.060009] [D real: 0.767464] [D fake: 0.242118]
[Epoch 5/50] [Batch 899/938] [D loss: 1.428830] [G loss: 1.432412] [D real: 0.410900] [D fake: 0.037912]
[Epoch 6/50] [Batch 299/938] [D loss: 0.759507] [G loss: 1.941889] [D real: 0.858148] [D fake: 0.408682]
[Epoch 6/50] [Batch 599/938] [D loss: 1.337436] [G loss: 1.029973] [D real: 0.446741] [D fake: 0.111939]
[Epoch 6/50] [Batch 899/938] [D loss: 0.870214] [G loss: 1.490566] [D real: 0.724359] [D fake: 0.327510]
[Epoch 7/50] [Batch 299/938] [D loss: 1.122367] [G loss: 0.827073] [D real: 0.507671] [D fake: 0.130975]
[Epoch 7/50] [Batch 599/938] [D loss: 0.692919] [G loss: 1.806647] [D real: 0.783640] [D fake: 0.297796]
[Epoch 7/50] [Batch 899/938] [D loss: 0.789551] [G loss: 1.864350] [D real: 0.746999] [D fake: 0.305150]
[Epoch 8/50] [Batch 299/938] [D loss: 0.733965] [G loss: 1.515813] [D real: 0.693676] [D fake: 0.212955]
[Epoch 8/50] [Batch 599/938] [D loss: 0.791131] [G loss: 1.415176] [D real: 0.720173] [D fake: 0.288257]
[Epoch 8/50] [Batch 899/938] [D loss: 1.041299] [G loss: 1.707542] [D real: 0.789294] [D fake: 0.477999]
[Epoch 9/50] [Batch 299/938] [D loss: 0.767330] [G loss: 1.714275] [D real: 0.662479] [D fake: 0.181842]
[Epoch 9/50] [Batch 599/938] [D loss: 0.751823] [G loss: 1.618091] [D real: 0.743732] [D fake: 0.317823]
[Epoch 9/50] [Batch 899/938] [D loss: 1.005928] [G loss: 0.934031] [D real: 0.567297] [D fake: 0.169746]
[Epoch 10/50] [Batch 299/938] [D loss: 0.840555] [G loss: 1.309746] [D real: 0.641146] [D fake: 0.192289]
[Epoch 10/50] [Batch 599/938] [D loss: 0.955076] [G loss: 1.478955] [D real: 0.722971] [D fake: 0.389301]
[Epoch 10/50] [Batch 899/938] [D loss: 1.099679] [G loss: 2.458704] [D real: 0.801575] [D fake: 0.528984]
[Epoch 11/50] [Batch 299/938] [D loss: 1.134981] [G loss: 2.152138] [D real: 0.827615] [D fake: 0.561016]
[Epoch 11/50] [Batch 599/938] [D loss: 1.110051] [G loss: 2.186940] [D real: 0.785736] [D fake: 0.522965]
[Epoch 11/50] [Batch 899/938] [D loss: 0.967798] [G loss: 1.143636] [D real: 0.612437] [D fake: 0.289298]
[Epoch 12/50] [Batch 299/938] [D loss: 0.987672] [G loss: 1.053961] [D real: 0.668040] [D fake: 0.350569]
[Epoch 12/50] [Batch 599/938] [D loss: 0.994264] [G loss: 1.329461] [D real: 0.663970] [D fake: 0.359072]
[Epoch 12/50] [Batch 899/938] [D loss: 1.010527] [G loss: 2.234476] [D real: 0.801662] [D fake: 0.489242]
[Epoch 13/50] [Batch 299/938] [D loss: 1.018733] [G loss: 1.054845] [D real: 0.584695] [D fake: 0.272875]
[Epoch 13/50] [Batch 599/938] [D loss: 0.897803] [G loss: 1.070929] [D real: 0.634907] [D fake: 0.260495]
[Epoch 13/50] [Batch 899/938] [D loss: 0.928602] [G loss: 0.980382] [D real: 0.585267] [D fake: 0.202608]
[Epoch 14/50] [Batch 299/938] [D loss: 1.041200] [G loss: 1.371832] [D real: 0.738872] [D fake: 0.444859]
[Epoch 14/50] [Batch 599/938] [D loss: 1.189782] [G loss: 0.427081] [D real: 0.449587] [D fake: 0.168180]
[Epoch 14/50] [Batch 899/938] [D loss: 0.854989] [G loss: 1.091617] [D real: 0.632299] [D fake: 0.224815]
[Epoch 15/50] [Batch 299/938] [D loss: 0.944193] [G loss: 1.155721] [D real: 0.620216] [D fake: 0.269962]
[Epoch 15/50] [Batch 599/938] [D loss: 0.998389] [G loss: 0.904146] [D real: 0.556171] [D fake: 0.204791]
[Epoch 15/50] [Batch 899/938] [D loss: 1.008590] [G loss: 0.914938] [D real: 0.582012] [D fake: 0.268009]
[Epoch 16/50] [Batch 299/938] [D loss: 0.911417] [G loss: 1.359278] [D real: 0.682099] [D fake: 0.344080]
[Epoch 16/50] [Batch 599/938] [D loss: 1.012941] [G loss: 1.778577] [D real: 0.793160] [D fake: 0.508073]
[Epoch 16/50] [Batch 899/938] [D loss: 0.975888] [G loss: 1.202470] [D real: 0.637166] [D fake: 0.316471]
[Epoch 17/50] [Batch 299/938] [D loss: 0.943770] [G loss: 1.741435] [D real: 0.633970] [D fake: 0.306987]
[Epoch 17/50] [Batch 599/938] [D loss: 0.833549] [G loss: 1.772633] [D real: 0.649062] [D fake: 0.204961]
[Epoch 17/50] [Batch 899/938] [D loss: 1.010297] [G loss: 1.863605] [D real: 0.810268] [D fake: 0.501031]
[Epoch 18/50] [Batch 299/938] [D loss: 0.914496] [G loss: 1.749049] [D real: 0.765166] [D fake: 0.389558]
[Epoch 18/50] [Batch 599/938] [D loss: 0.996462] [G loss: 1.039770] [D real: 0.590974] [D fake: 0.247277]
[Epoch 18/50] [Batch 899/938] [D loss: 0.964202] [G loss: 1.767048] [D real: 0.656000] [D fake: 0.320717]
[Epoch 19/50] [Batch 299/938] [D loss: 0.843251] [G loss: 1.236855] [D real: 0.646118] [D fake: 0.237653]
[Epoch 19/50] [Batch 599/938] [D loss: 0.976936] [G loss: 1.396986] [D real: 0.697293] [D fake: 0.374340]
[Epoch 19/50] [Batch 899/938] [D loss: 0.870332] [G loss: 1.709515] [D real: 0.721556] [D fake: 0.352539]
[Epoch 20/50] [Batch 299/938] [D loss: 0.969142] [G loss: 1.302671] [D real: 0.735120] [D fake: 0.404214]
[Epoch 20/50] [Batch 599/938] [D loss: 0.989958] [G loss: 1.944960] [D real: 0.758919] [D fake: 0.440808]
[Epoch 20/50] [Batch 899/938] [D loss: 0.935569] [G loss: 1.534396] [D real: 0.669523] [D fake: 0.338873]
[Epoch 21/50] [Batch 299/938] [D loss: 1.035034] [G loss: 0.908412] [D real: 0.628880] [D fake: 0.322658]
[Epoch 21/50] [Batch 599/938] [D loss: 1.101136] [G loss: 1.216910] [D real: 0.607380] [D fake: 0.340446]
[Epoch 21/50] [Batch 899/938] [D loss: 1.177686] [G loss: 2.213221] [D real: 0.807462] [D fake: 0.525449]
[Epoch 22/50] [Batch 299/938] [D loss: 0.870708] [G loss: 1.437802] [D real: 0.694793] [D fake: 0.323918]
[Epoch 22/50] [Batch 599/938] [D loss: 1.106889] [G loss: 1.012407] [D real: 0.486944] [D fake: 0.195053]
[Epoch 22/50] [Batch 899/938] [D loss: 1.000133] [G loss: 1.045473] [D real: 0.572080] [D fake: 0.245656]
[Epoch 23/50] [Batch 299/938] [D loss: 0.888755] [G loss: 1.096570] [D real: 0.602487] [D fake: 0.193794]
[Epoch 23/50] [Batch 599/938] [D loss: 1.047959] [G loss: 1.100965] [D real: 0.615336] [D fake: 0.304345]
[Epoch 23/50] [Batch 899/938] [D loss: 1.079803] [G loss: 1.284658] [D real: 0.568702] [D fake: 0.205231]
[Epoch 24/50] [Batch 299/938] [D loss: 0.972733] [G loss: 1.969384] [D real: 0.758505] [D fake: 0.436408]
[Epoch 24/50] [Batch 599/938] [D loss: 0.921657] [G loss: 1.064871] [D real: 0.654241] [D fake: 0.272639]
[Epoch 24/50] [Batch 899/938] [D loss: 0.968343] [G loss: 0.903804] [D real: 0.675703] [D fake: 0.329859]
[Epoch 25/50] [Batch 299/938] [D loss: 1.145077] [G loss: 0.843309] [D real: 0.497391] [D fake: 0.227816]
[Epoch 25/50] [Batch 599/938] [D loss: 1.075655] [G loss: 1.029029] [D real: 0.613387] [D fake: 0.312752]
[Epoch 25/50] [Batch 899/938] [D loss: 1.010697] [G loss: 1.490351] [D real: 0.669022] [D fake: 0.376234]
[Epoch 26/50] [Batch 299/938] [D loss: 0.983672] [G loss: 1.413204] [D real: 0.666687] [D fake: 0.336629]
[Epoch 26/50] [Batch 599/938] [D loss: 1.047531] [G loss: 0.843206] [D real: 0.574479] [D fake: 0.267796]
[Epoch 26/50] [Batch 899/938] [D loss: 1.062833] [G loss: 1.039606] [D real: 0.498748] [D fake: 0.150498]
[Epoch 27/50] [Batch 299/938] [D loss: 1.072042] [G loss: 1.565302] [D real: 0.706010] [D fake: 0.394275]
[Epoch 27/50] [Batch 599/938] [D loss: 0.824592] [G loss: 1.582908] [D real: 0.766955] [D fake: 0.363206]
[Epoch 27/50] [Batch 899/938] [D loss: 0.968758] [G loss: 1.291694] [D real: 0.583086] [D fake: 0.165570]
[Epoch 28/50] [Batch 299/938] [D loss: 1.238154] [G loss: 2.020324] [D real: 0.847639] [D fake: 0.584372]
[Epoch 28/50] [Batch 599/938] [D loss: 0.998096] [G loss: 1.243028] [D real: 0.642028] [D fake: 0.345103]
[Epoch 28/50] [Batch 899/938] [D loss: 0.962889] [G loss: 1.364775] [D real: 0.723890] [D fake: 0.383930]
[Epoch 29/50] [Batch 299/938] [D loss: 0.824154] [G loss: 2.135429] [D real: 0.744123] [D fake: 0.340545]
[Epoch 29/50] [Batch 599/938] [D loss: 0.953269] [G loss: 1.026226] [D real: 0.597327] [D fake: 0.248981]
[Epoch 29/50] [Batch 899/938] [D loss: 0.875270] [G loss: 1.951008] [D real: 0.776749] [D fake: 0.390874]
[Epoch 30/50] [Batch 299/938] [D loss: 0.912583] [G loss: 1.812899] [D real: 0.719492] [D fake: 0.363508]
[Epoch 30/50] [Batch 599/938] [D loss: 0.826313] [G loss: 1.293154] [D real: 0.674231] [D fake: 0.252548]
[Epoch 30/50] [Batch 899/938] [D loss: 0.955207] [G loss: 2.284338] [D real: 0.842908] [D fake: 0.496630]
[Epoch 31/50] [Batch 299/938] [D loss: 1.105594] [G loss: 1.499079] [D real: 0.728621] [D fake: 0.473395]
[Epoch 31/50] [Batch 599/938] [D loss: 0.918280] [G loss: 1.294344] [D real: 0.610279] [D fake: 0.215408]
[Epoch 31/50] [Batch 899/938] [D loss: 0.904938] [G loss: 1.202110] [D real: 0.718352] [D fake: 0.336531]
[Epoch 32/50] [Batch 299/938] [D loss: 0.887325] [G loss: 1.869841] [D real: 0.752809] [D fake: 0.360330]
[Epoch 32/50] [Batch 599/938] [D loss: 0.862946] [G loss: 1.423999] [D real: 0.733013] [D fake: 0.337863]
[Epoch 32/50] [Batch 899/938] [D loss: 0.881429] [G loss: 1.764507] [D real: 0.684698] [D fake: 0.265486]
[Epoch 33/50] [Batch 299/938] [D loss: 0.847196] [G loss: 1.533767] [D real: 0.748652] [D fake: 0.338352]
[Epoch 33/50] [Batch 599/938] [D loss: 0.890364] [G loss: 1.191150] [D real: 0.665347] [D fake: 0.243825]
[Epoch 33/50] [Batch 899/938] [D loss: 0.872981] [G loss: 1.362405] [D real: 0.691033] [D fake: 0.305003]
[Epoch 34/50] [Batch 299/938] [D loss: 0.985218] [G loss: 1.281500] [D real: 0.548885] [D fake: 0.140615]
[Epoch 34/50] [Batch 599/938] [D loss: 0.793171] [G loss: 1.109184] [D real: 0.680612] [D fake: 0.226118]
[Epoch 34/50] [Batch 899/938] [D loss: 0.954198] [G loss: 1.143580] [D real: 0.628429] [D fake: 0.287817]
[Epoch 35/50] [Batch 299/938] [D loss: 0.916259] [G loss: 1.428971] [D real: 0.658356] [D fake: 0.276234]
[Epoch 35/50] [Batch 599/938] [D loss: 0.948558] [G loss: 1.223554] [D real: 0.638418] [D fake: 0.281471]
[Epoch 35/50] [Batch 899/938] [D loss: 0.857785] [G loss: 1.932398] [D real: 0.746985] [D fake: 0.349830]
[Epoch 36/50] [Batch 299/938] [D loss: 1.091316] [G loss: 1.919538] [D real: 0.765110] [D fake: 0.455750]
[Epoch 36/50] [Batch 599/938] [D loss: 1.047269] [G loss: 1.158984] [D real: 0.587491] [D fake: 0.180821]
[Epoch 36/50] [Batch 899/938] [D loss: 0.888727] [G loss: 0.967270] [D real: 0.621429] [D fake: 0.236691]
[Epoch 37/50] [Batch 299/938] [D loss: 0.866641] [G loss: 1.702019] [D real: 0.756511] [D fake: 0.359900]
[Epoch 37/50] [Batch 599/938] [D loss: 0.911748] [G loss: 1.353123] [D real: 0.710482] [D fake: 0.309445]
[Epoch 37/50] [Batch 899/938] [D loss: 0.870284] [G loss: 1.274699] [D real: 0.631317] [D fake: 0.194104]
[Epoch 38/50] [Batch 299/938] [D loss: 0.842599] [G loss: 1.659850] [D real: 0.717162] [D fake: 0.306773]
[Epoch 38/50] [Batch 599/938] [D loss: 0.837747] [G loss: 1.053589] [D real: 0.642340] [D fake: 0.196331]
[Epoch 38/50] [Batch 899/938] [D loss: 0.869350] [G loss: 1.841435] [D real: 0.800417] [D fake: 0.415925]
[Epoch 39/50] [Batch 299/938] [D loss: 0.880686] [G loss: 1.209579] [D real: 0.690959] [D fake: 0.283914]
[Epoch 39/50] [Batch 599/938] [D loss: 0.877852] [G loss: 0.830870] [D real: 0.658372] [D fake: 0.268402]
[Epoch 39/50] [Batch 899/938] [D loss: 0.978142] [G loss: 2.271859] [D real: 0.803293] [D fake: 0.444690]
[Epoch 40/50] [Batch 299/938] [D loss: 0.771765] [G loss: 2.259018] [D real: 0.829622] [D fake: 0.361728]
[Epoch 40/50] [Batch 599/938] [D loss: 0.892520] [G loss: 1.763451] [D real: 0.672333] [D fake: 0.228710]
[Epoch 40/50] [Batch 899/938] [D loss: 0.802244] [G loss: 1.445543] [D real: 0.699383] [D fake: 0.250980]
[Epoch 41/50] [Batch 299/938] [D loss: 1.341725] [G loss: 0.782063] [D real: 0.408866] [D fake: 0.125863]
[Epoch 41/50] [Batch 599/938] [D loss: 0.785944] [G loss: 1.853362] [D real: 0.761955] [D fake: 0.312440]
[Epoch 41/50] [Batch 899/938] [D loss: 0.951069] [G loss: 1.208025] [D real: 0.652018] [D fake: 0.284539]
[Epoch 42/50] [Batch 299/938] [D loss: 0.774799] [G loss: 1.747546] [D real: 0.821659] [D fake: 0.361410]
[Epoch 42/50] [Batch 599/938] [D loss: 1.001426] [G loss: 1.745122] [D real: 0.804986] [D fake: 0.457982]
[Epoch 42/50] [Batch 899/938] [D loss: 0.890022] [G loss: 1.853921] [D real: 0.685620] [D fake: 0.218101]
[Epoch 43/50] [Batch 299/938] [D loss: 0.974726] [G loss: 1.995896] [D real: 0.728058] [D fake: 0.367714]
[Epoch 43/50] [Batch 599/938] [D loss: 0.990968] [G loss: 1.358955] [D real: 0.625547] [D fake: 0.273775]
[Epoch 43/50] [Batch 899/938] [D loss: 0.973941] [G loss: 1.210741] [D real: 0.608805] [D fake: 0.205208]
[Epoch 44/50] [Batch 299/938] [D loss: 0.906846] [G loss: 1.619644] [D real: 0.645157] [D fake: 0.254954]
[Epoch 44/50] [Batch 599/938] [D loss: 0.883303] [G loss: 2.114267] [D real: 0.794034] [D fake: 0.379586]
[Epoch 44/50] [Batch 899/938] [D loss: 1.050809] [G loss: 0.902721] [D real: 0.591037] [D fake: 0.266058]
[Epoch 45/50] [Batch 299/938] [D loss: 0.815616] [G loss: 1.365411] [D real: 0.713596] [D fake: 0.273942]
[Epoch 45/50] [Batch 599/938] [D loss: 1.011158] [G loss: 1.113275] [D real: 0.561966] [D fake: 0.168626]
[Epoch 45/50] [Batch 899/938] [D loss: 0.847521] [G loss: 1.222216] [D real: 0.664941] [D fake: 0.235488]
[Epoch 46/50] [Batch 299/938] [D loss: 0.940070] [G loss: 1.607019] [D real: 0.788724] [D fake: 0.398294]
[Epoch 46/50] [Batch 599/938] [D loss: 0.992476] [G loss: 1.555995] [D real: 0.694556] [D fake: 0.364282]
[Epoch 46/50] [Batch 899/938] [D loss: 0.922023] [G loss: 1.982483] [D real: 0.807779] [D fake: 0.441375]
[Epoch 47/50] [Batch 299/938] [D loss: 0.826111] [G loss: 1.947735] [D real: 0.874026] [D fake: 0.419001]
[Epoch 47/50] [Batch 599/938] [D loss: 0.814420] [G loss: 2.030638] [D real: 0.789359] [D fake: 0.354669]
[Epoch 47/50] [Batch 899/938] [D loss: 0.769126] [G loss: 0.983590] [D real: 0.665294] [D fake: 0.182470]
[Epoch 48/50] [Batch 299/938] [D loss: 1.002635] [G loss: 1.455177] [D real: 0.657658] [D fake: 0.323212]
[Epoch 48/50] [Batch 599/938] [D loss: 0.978162] [G loss: 1.609365] [D real: 0.630500] [D fake: 0.252250]
[Epoch 48/50] [Batch 899/938] [D loss: 0.945259] [G loss: 1.568523] [D real: 0.664012] [D fake: 0.267772]
[Epoch 49/50] [Batch 299/938] [D loss: 0.760730] [G loss: 1.163772] [D real: 0.683584] [D fake: 0.211297]
[Epoch 49/50] [Batch 599/938] [D loss: 0.906713] [G loss: 1.578192] [D real: 0.805951] [D fake: 0.423694]
[Epoch 49/50] [Batch 899/938] [D loss: 0.856342] [G loss: 1.611097] [D real: 0.647225] [D fake: 0.214937]

请添加图片描述

500
1000
请添加图片描述

请添加图片描述

  • 20
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值