第G9周:ACGAN理论与实战

  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊

由于ACGAN的原理在上一篇文章中已经很详细的解释过了,这次我们直接上代码

一、代码解读

import argparse
import os
import numpy as np

import torchvision.transforms as transforms
from torchvision.utils import save_image

from torch.utils.data import DataLoader
from torchvision import datasets
from torch.autograd import Variable

import torch.nn as nn
import torch
import sys
sys.argv = ['run.py']

os.makedirs("images1", exist_ok=True)

parser = argparse.ArgumentParser()
parser.add_argument("--n_epochs", type=int, default=100, help="训练的总轮数")
parser.add_argument("--batch_size", type=int, default=128, help="每个批次的大小")
parser.add_argument("--lr", type=float, default=0.0002, help="Adam优化器的学习率")
parser.add_argument("--b1", type=float, default=0.5, help="Adam优化器的一阶动量衰减")
parser.add_argument("--b2", type=float, default=0.999, help="Adam优化器的二阶动量衰减")
parser.add_argument("--n_cpu", type=int, default=8, help="用于批次生成的CPU线程数")
parser.add_argument("--latent_dim", type=int, default=100, help="潜在空间的维度")
parser.add_argument("--n_classes", type=int, default=10, help="数据集的类别数")
parser.add_argument("--img_size", type=int, default=32, help="每个图像的尺寸")
parser.add_argument("--channels", type=int, default=1, help="图像通道数")
parser.add_argument("--sample_interval", type=int, default=200, help="图像采样间隔")
opt = parser.parse_args()
print(opt)

cuda = True if torch.cuda.is_available() else False

这段代码是一个Python脚本的示例,它使用了argparse库来解析命令行参数,并设置了与图像生成相关的各种参数。代码的主要部分包括参数解析、检查GPU支持、以及创建一个目录来存储生成的图像。

  1. 导入必要的库和模块
    • argparse:用于解析命令行参数。
    • os:用于操作系统相关的功能,如创建目录。
    • numpy:用于数学计算。
    • torchvision.transforms:用于图像预处理。
    • torchvision.utils:用于保存图像。
    • torch.utils.data:用于数据加载。
    • torchvision.datasets:用于加载数据集。
    • torch.autograd:用于自动求导。
    • torch.nn:用于定义神经网络。
    • torch:用于深度学习。
    • sys:用于访问系统相关的参数和函数。
  2. 创建用于存储生成图像的目录
    • os.makedirs("images1", exist_ok=True):如果目录"images1"不存在,则创建它。如果目录已经存在,则不会引发错误。
  3. 解析命令行参数
    • 使用argparse.ArgumentParser创建一个参数解析器。
    • 添加多个参数,包括训练的总轮数、每个批次的大小、Adam优化器的学习率、一阶和二阶动量衰减、用于批次生成的CPU线程数、潜在空间的维度、数据集的类别数、每个图像的尺寸、图像通道数和图像采样间隔。
    • 使用parser.parse_args()解析命令行参数,并将解析后的参数存储在opt变量中。
    • 打印解析后的参数。
  4. 检查是否支持GPU加速
    • cuda = True if torch.cuda.is_available() else False:检查是否有可用的GPU,并设置cuda变量为TrueFalse
      这段代码为后续的深度学习模型训练和图像生成准备环境,包括设置参数和检查GPU支持。在实际应用中,这段代码可能需要根据具体任务和数据集进行调整。
def weights_init_normal(m):
    classname = m.__class__.__name__
    if classname.find("Conv") != -1:
        torch.nn.init.normal_(m.weight.data, 0.0, 0.02)
    elif classname.find("BatchNorm2d") != -1:
        torch.nn.init.normal_(m.weight.data, 1.0, 0.02)
        torch.nn.init.constant_(m.bias.data, 0.0)

# 生成器网络类
class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()

        # 为类别标签创建嵌入层
        self.label_emb = nn.Embedding(opt.n_classes, opt.latent_dim)

        # 计算上采样前的初始大小
        self.init_size = opt.img_size // 4  # Initial size before upsampling

        # 第一层线性层
        self.l1 = nn.Sequential(nn.Linear(opt.latent_dim, 128 * self.init_size ** 2))

        # 卷积层块
        self.conv_blocks = nn.Sequential(
            nn.BatchNorm2d(128),
            nn.Upsample(scale_factor=2),
            nn.Conv2d(128, 128, 3, stride=1, padding=1),
            nn.BatchNorm2d(128, 0.8),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Upsample(scale_factor=2),
            nn.Conv2d(128, 64, 3, stride=1, padding=1),
            nn.BatchNorm2d(64, 0.8),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Conv2d(64, opt.channels, 3, stride=1, padding=1),
            nn.Tanh(),
        )

    def forward(self, noise, labels):
        # 将标签嵌入到噪声中
        gen_input = torch.mul(self.label_emb(labels), noise)

        # 通过第一层线性层
        out = self.l1(gen_input)

        # 重新整形为合适的形状
        out = out.view(out.shape[0], 128, self.init_size, self.init_size)

        # 通过卷积层块生成图像
        img = self.conv_blocks(out)
        return img

这段代码定义了一个生成器网络类Generator,它是用于生成图像的深度学习模型。生成器网络是生成对抗网络(GAN)的一部分,它学习如何从随机噪声生成真实的图像。代码中定义了网络的结构和前向传播过程。

  1. 权重初始化函数
    • weights_init_normal(m):这是一个自定义的权重初始化函数,用于在生成器网络中初始化各种层的权重。
    • classname = m.__class__.__name__:获取当前层的类名。
    • if classname.find("Conv") != -1::如果层是卷积层,则进行相应的权重初始化。
    • elif classname.find("BatchNorm2d") != -1::如果层是批量归一化层,则进行相应的权重和偏置初始化。
    • torch.nn.init.normal_(m.weight.data, 0.0, 0.02):对权重进行正态分布初始化。
    • torch.nn.init.constant_(m.bias.data, 0.0):对偏置进行常数初始化。
  2. 生成器网络类
    • class Generator(nn.Module):定义了一个名为Generator的类,它继承自nn.Module,这是所有PyTorch神经网络类的基础。
    • def __init__(self):这是生成器网络的构造函数。
    • super(Generator, self).__init__():调用父类的构造函数,初始化网络的基本结构。
    • self.label_emb = nn.Embedding(opt.n_classes, opt.latent_dim):创建一个嵌入层,用于将类别标签嵌入到潜在空间中。
    • self.init_size = opt.img_size // 4:计算上采样前的初始大小,通常为输入图像尺寸的四分之一。
    • self.l1 = nn.Sequential(...):定义了一个包含线性层和重排层的序列,用于将潜在空间向量转换为适合后续卷积层的形状。
    • self.conv_blocks = nn.Sequential(...):定义了一个包含多个卷积层、批量归一化层和Leaky ReLU激活函数的序列,用于生成最终的图像。
  3. 前向传播过程
    • def forward(self, noise, labels):定义了生成器的前向传播函数。
    • gen_input = torch.mul(self.label_emb(labels), noise):将标签嵌入到噪声中,生成用于后续处理的输入。
    • out = self.l1(gen_input):通过第一层线性层。
    • out = out.view(out.shape[0], 128, self.init_size, self.init_size):重新整形为合适的形状。
    • img = self.conv_blocks(out):通过卷积层块生成图像。
    • return img:返回生成的图像。
      这段代码定义了一个生成器网络,它可以接受噪声和类别标签作为输入,并生成相应的图像。在实际应用中,这个生成器网络可能需要根据具体任务和数据集进行调整。
class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()

        # 定义判别器块的函数
        def discriminator_block(in_filters, out_filters, bn=True):
            """返回每个判别器块的层"""
            block = [nn.Conv2d(in_filters, out_filters, 3, 2, 1), nn.LeakyReLU(0.2, inplace=True), nn.Dropout2d(0.25)]
            if bn:
                block.append(nn.BatchNorm2d(out_filters, 0.8))
            return block

        # 判别器的卷积层块
        self.conv_blocks = nn.Sequential(
            *discriminator_block(opt.channels, 16, bn=False),
            *discriminator_block(16, 32),
            *discriminator_block(32, 64),
            *discriminator_block(64, 128),
        )

        # 下采样后图像的高度和宽度
        ds_size = opt.img_size // 2 ** 4

        # 输出层
        self.adv_layer = nn.Sequential(nn.Linear(128 * ds_size ** 2, 1), nn.Sigmoid())
        self.aux_layer = nn.Sequential(nn.Linear(128 * ds_size ** 2, opt.n_classes), nn.Softmax())

    def forward(self, img):
        out = self.conv_blocks(img)
        out = out.view(out.shape[0], -1)
        validity = self.adv_layer(out)
        label = self.aux_layer(out)

        return validity, label

# 损失函数
adversarial_loss = torch.nn.BCELoss()
auxiliary_loss = torch.nn.CrossEntropyLoss()

这段代码定义了一个判别器网络类Discriminator,它是用于区分真实图像和生成图像的深度学习模型。判别器网络是生成对抗网络(GAN)的另一部分,它的目标是区分输入的图像是否是真实图像。代码中定义了网络的结构和前向传播过程。

  1. 权重初始化函数
    • weights_init_normal(m):这是一个自定义的权重初始化函数,用于在判别器网络中初始化各种层的权重。
    • classname = m.__class__.__name__:获取当前层的类名。
    • if classname.find("Conv") != -1::如果层是卷积层,则进行相应的权重初始化。
    • elif classname.find("BatchNorm2d") != -1::如果层是批量归一化层,则进行相应的权重和偏置初始化。
    • torch.nn.init.normal_(m.weight.data, 0.0, 0.02):对权重进行正态分布初始化。
    • torch.nn.init.constant_(m.bias.data, 0.0):对偏置进行常数初始化。
  2. 判别器网络类
    • class Discriminator(nn.Module):定义了一个名为Discriminator的类,它继承自nn.Module
    • def __init__(self):这是判别器网络的构造函数。
    • super(Discriminator, self).__init__():调用父类的构造函数,初始化网络的基本结构。
    • self.conv_blocks = nn.Sequential(...):定义了一个包含多个卷积层、Leaky ReLU激活函数和批量归一化层的序列,用于判别输入的图像。
    • self.adv_layer = nn.Sequential(...):定义了一个包含线性层和Sigmoid激活函数的序列,用于输出判别结果。
    • self.aux_layer = nn.Sequential(...):定义了一个包含线性层和Softmax激活函数的序列,用于输出类别标签。
  3. 前向传播过程
    • def forward(self, img):定义了判别器的前向传播函数。
    • out = self.conv_blocks(img):通过卷积层块处理输入的图像。
    • out = out.view(out.shape[0], -1):重新整形为适合后续层的形状。
    • validity = self.adv_layer(out):通过判别层输出判别结果。
    • label = self.aux_layer(out):通过判别层输出类别标签。
    • return validity, label:返回判别结果和类别标签。
  4. 损失函数
    • adversarial_loss = torch.nn.BCELoss():定义了一个二元交叉熵损失函数,用于判别器中的对抗损失。
    • auxiliary_loss = torch.nn.CrossEntropyLoss():定义了一个交叉熵损失函数,用于判别器中的辅助损失。
      这段代码定义了一个判别器网络,它可以接受图像作为输入,并输出判别结果和类别标签。在实际应用中,这个判别器网络可能需要根据具体任务和数据集进行调整。
generator = Generator()
discriminator = Discriminator()

if cuda:
    generator.cuda()
    discriminator.cuda()
    adversarial_loss.cuda()
    auxiliary_loss.cuda()

# 初始化权重
generator.apply(weights_init_normal)
discriminator.apply(weights_init_normal)

# 配置数据加载器
os.makedirs("data/mnist", exist_ok=True)
dataloader = torch.utils.data.DataLoader(
    datasets.MNIST(
        "data/mnist",
        train=True,
        download=True,
        transform=transforms.Compose(
            [transforms.Resize(opt.img_size), transforms.ToTensor(), transforms.Normalize([0.5], [0.5])]
        ),
    ),
    batch_size=opt.batch_size,
    shuffle=True,
)

# 优化器
optimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))
optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))

FloatTensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor
LongTensor = torch.cuda.LongTensor if cuda else torch.LongTensor

# 保存生成图像的函数
def sample_image(n_row, batches_done):
    """保存从0到n_classes的生成数字的图像网格"""
    # 采样噪声
    z = Variable(FloatTensor(np.random.normal(0, 1, (n_row ** 2, opt.latent_dim))))
    # 为n行生成标签从0到n_classes
    labels = np.array([num for _ in range(n_row) for num in range(n_row)])
    labels = Variable(LongTensor(labels))
    gen_imgs = generator(z, labels)
    save_image(gen_imgs.data, "images1/%d.png" % batches_done, nrow=n_row, normalize=True)

这段代码是生成对抗网络(GAN)的训练过程的一部分,它包括生成器、判别器、数据加载器、优化器以及一个保存生成图像的函数。代码首先定义了生成器和判别器,然后设置GPU支持,初始化权重,配置数据加载器,创建优化器,并定义了一个保存生成图像的函数。

  1. 创建生成器和判别器
    • generator = Generator():创建一个Generator实例。
    • discriminator = Discriminator():创建一个Discriminator实例。
  2. 设置GPU支持
    • if cuda::如果启用了GPU,则将生成器和判别器移动到GPU上,并相应地调整损失函数。
    • generator.cuda():将生成器移动到GPU。
    • discriminator.cuda():将判别器移动到GPU。
    • adversarial_loss.cuda():将对抗损失函数移动到GPU。
    • auxiliary_loss.cuda():将辅助损失函数移动到GPU。
  3. 初始化权重
    • generator.apply(weights_init_normal):使用weights_init_normal函数初始化生成器的权重。
    • discriminator.apply(weights_init_normal):使用weights_init_normal函数初始化判别器的权重。
  4. 配置数据加载器
    • os.makedirs("data/mnist", exist_ok=True):创建一个名为"data/mnist"的目录,如果目录已存在,则不引发错误。
    • dataloader = torch.utils.data.DataLoader(...):创建一个MNIST数据集的DataLoader实例,用于加载训练数据。
  5. 创建优化器
    • optimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)):为生成器创建一个Adam优化器实例。
    • optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)):为判别器创建一个Adam优化器实例。
  6. 定义FloatTensor和LongTensor
    • FloatTensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor:根据是否使用GPU,定义一个浮点数张量类型。
    • LongTensor = torch.cuda.LongTensor if cuda else torch.LongTensor:根据是否使用GPU,定义一个长整数张量类型。
  7. 保存生成图像的函数
    • def sample_image(n_row, batches_done):定义了一个函数,用于保存生成的图像。
    • z = Variable(FloatTensor(np.random.normal(0, 1, (n_row ** 2, opt.latent_dim)))):生成一个随机噪声向量。
    • labels = np.array([num for _ in range(n_row) for num in range(n_row)]):为图像生成对应的标签。
    • labels = Variable(LongTensor(labels)):将标签转换为张量。
    • gen_imgs = generator(z, labels):使用生成器生成图像。
    • save_image(gen_imgs.data, "images1/%d.png" % batches_done, nrow=n_row, normalize=True):保存生成的图像。
      这段代码是GAN训练过程中的一部分,它定义了生成器和判别器,并设置了GPU支持、初始化权重、配置数据加载器、创建优化器,并定义了一个保存生成图像的函数。在实际应用中,这段代码可能需要根据具体任务和数据集进行调整。
for epoch in range(opt.n_epochs):
    for i, (imgs, labels) in enumerate(dataloader):

        batch_size = imgs.shape[0]

        # 真实数据的标签
        valid = Variable(FloatTensor(batch_size, 1).fill_(1.0), requires_grad=False)
        # 生成数据的标签
        fake = Variable(FloatTensor(batch_size, 1).fill_(0.0), requires_grad=False)

        # 配置输入
        real_imgs = Variable(imgs.type(FloatTensor))
        labels = Variable(labels.type(LongTensor))

        # -----------------
        # 训练生成器
        # -----------------

        optimizer_G.zero_grad()

        # 采样噪声和标签作为生成器的输入
        z = Variable(FloatTensor(np.random.normal(0, 1, (batch_size, opt.latent_dim))))
        gen_labels = Variable(LongTensor(np.random.randint(0, opt.n_classes, batch_size)))

        # 生成一批图像
        gen_imgs = generator(z, gen_labels)

        # 损失度量生成器的欺骗判别器的能力
        validity, pred_label = discriminator(gen_imgs)
        g_loss = 0.5 * (adversarial_loss(validity, valid) + auxiliary_loss(pred_label, gen_labels))

        g_loss.backward()
        optimizer_G.step()

        # ---------------------
        # 训练判别器
        # ---------------------

        optimizer_D.zero_grad()

        # 真实图像的损失
        real_pred, real_aux = discriminator(real_imgs)
        d_real_loss = (adversarial_loss(real_pred, valid) + auxiliary_loss(real_aux, labels)) / 2

        # 生成图像的损失
        fake_pred, fake_aux = discriminator(gen_imgs.detach())
        d_fake_loss = (adversarial_loss(fake_pred, fake) + auxiliary_loss(fake_aux, gen_labels)) / 2

        # 判别器的总损失
        d_loss = (d_real_loss + d_fake_loss) / 2

        # 计算判别器的准确率
        pred = np.concatenate([real_aux.data.cpu().numpy(), fake_aux.data.cpu().numpy()], axis=0)
        gt = np.concatenate([labels.data.cpu().numpy(), gen_labels.data.cpu().numpy()], axis=0)
        d_acc = np.mean(np.argmax(pred, axis=1) == gt)

        d_loss.backward()
        optimizer_D.step()

        
        batches_done = epoch * len(dataloader) + i
        if batches_done % opt.sample_interval == 0:
            save_image(gen_imgs.data[:25], "images1/%d.png" % batches_done, nrow=5, normalize=True)

    print(
        "[Epoch %d/%d] [Batch %d/%d] [D loss: %f, acc: %d%%] [G loss: %f]"
        % (epoch, opt.n_epochs, i, len(dataloader), d_loss.item(), 100 * d_acc, g_loss.item())
    )

这段代码是生成对抗网络(GAN)的训练过程,其中包含了多个循环,用于迭代地训练生成器和判别器。代码首先定义了生成器和判别器的优化器,然后遍历数据集,在每个批次上更新网络的权重。

  1. 循环遍历训练轮数
    • for epoch in range(opt.n_epochs)::循环遍历训练的轮数,opt.n_epochs是命令行参数中定义的总训练轮数。
  2. 循环遍历数据集的每个批次
    • for i, (imgs, labels) in enumerate(dataloader)::循环遍历数据加载器中的每个批次,imgs是真实图像,labels是图像对应的标签。
  3. 设置批次大小
    • batch_size = imgs.shape[0]:获取当前批次的图像数量,即批次大小。
  4. 定义真实数据和生成数据的标签
    • valid = Variable(FloatTensor(batch_size, 1).fill_(1.0), requires_grad=False):真实数据的标签,值为1。
    • fake = Variable(FloatTensor(batch_size, 1).fill_(0.0), requires_grad=False):生成数据的标签,值为0。
  5. 准备真实图像和标签
    • real_imgs = Variable(imgs.type(FloatTensor)):将真实图像转换为浮点数张量。
    • labels = Variable(labels.type(LongTensor)):将标签转换为长整数张量。
  6. 更新生成器
    • optimizer_G.zero_grad():清除生成器优化器的梯度。
    • z = Variable(FloatTensor(np.random.normal(0, 1, (batch_size, opt.latent_dim)))):生成一个随机噪声向量。
    • gen_labels = Variable(LongTensor(np.random.randint(0, opt.n_classes, batch_size))):为图像生成对应的标签。
    • gen_imgs = generator(z, gen_labels):使用生成器生成图像。
    • validity, pred_label = discriminator(gen_imgs):使用判别器评估生成图像的真实性。
    • g_loss = 0.5 * (adversarial_loss(validity, valid) + auxiliary_loss(pred_label, gen_labels)):计算生成器的损失。
    • g_loss.backward():计算生成器损失的梯度。
    • optimizer_G.step():使用梯度更新生成器的权重。
  7. 更新判别器
    • optimizer_D.zero_grad():清除判别器优化器的梯度。
    • real_pred, real_aux = discriminator(real_imgs):使用判别器评估真实图像的真实性。
    • d_real_loss = (adversarial_loss(real_pred, valid) + auxiliary_loss(real_aux, labels)) / 2:计算判别器对真实图像的损失。
    • fake_pred, fake_aux = discriminator(gen_imgs.detach()):使用判别器评估生成图像的真实性,但不对生成图像求梯度。
    • d_fake_loss = (adversarial_loss(fake_pred, fake) + auxiliary_loss(fake_aux, gen_labels)) / 2:计算判别器对生成图像的损失。
    • d_loss = (d_real_loss + d_fake_loss) / 2:计算判别器的总损失。
    • d_acc = np.mean(np.argmax(pred, axis=1) == gt):计算判别器的分类准确率。
    • d_loss.backward():计算判别器损失的梯度。
    • optimizer_D.step():使用梯度更新判别器的权重。
  8. 保存生成图像
    • if batches_done % opt.sample_interval == 0::检查当前批次完成的次数是否是opt.sample_interval的倍数。如果满足条件,则执行以下代码。
    • save_image(gen_imgs.data[:25], "images1/%d.png" % batches_done, nrow=5, normalize=True)
      • gen_imgs.data[:25]:从生成的图像中选择前25个图像用于保存。
      • "images1/%d.png" % batches_done:创建一个文件名,包含当前批次完成的次数。
      • nrow=5:将图像以5行每行的形式排列。
      • normalize=True:将图像的像素值从[-1, 1]范围转换为[0, 1]范围,以便于显示。
  9. 打印训练状态
    • print(...):打印当前的训练状态。
    • [Epoch %d/%d]:当前训练轮数和总训练轮数。
    • [Batch %d/%d]:当前批次和总批次。
    • [D loss: %f, acc: %d%%]:判别器的损失和分类准确率。
    • [G loss: %f]:生成器的损失。
    • %d:整数格式化占位符。
    • %f:浮点数格式化占位符。
    • epoch, opt.n_epochs, i, len(dataloader), d_loss.item(), 100 * d_acc, g_loss.item():实际要打印的值。

二、训练结果

Namespace(b1=0.5, b2=0.999, batch_size=128, channels=1, img_size=32, latent_dim=100, lr=0.0002, n_classes=10, n_cpu=8, n_epochs=100, sample_interval=200)
[Epoch 0/100] [Batch 468/469] [D loss: 1.186150, acc: 76%] [G loss: 1.278507]
[Epoch 1/100] [Batch 468/469] [D loss: 1.089216, acc: 91%] [G loss: 1.147808]
[Epoch 2/100] [Batch 468/469] [D loss: 1.077708, acc: 92%] [G loss: 1.162803]
[Epoch 3/100] [Batch 468/469] [D loss: 1.066667, acc: 94%] [G loss: 1.165272]
[Epoch 4/100] [Batch 468/469] [D loss: 1.071887, acc: 93%] [G loss: 1.119173]
[Epoch 5/100] [Batch 468/469] [D loss: 1.101875, acc: 93%] [G loss: 1.112627]
[Epoch 6/100] [Batch 468/469] [D loss: 1.085075, acc: 93%] [G loss: 1.184606]
[Epoch 7/100] [Batch 468/469] [D loss: 1.094645, acc: 96%] [G loss: 1.119984]
[Epoch 8/100] [Batch 468/469] [D loss: 1.086777, acc: 96%] [G loss: 1.113284]
[Epoch 9/100] [Batch 468/469] [D loss: 1.092487, acc: 96%] [G loss: 1.108529]
[Epoch 10/100] [Batch 468/469] [D loss: 1.115485, acc: 96%] [G loss: 1.087031]
[Epoch 11/100] [Batch 468/469] [D loss: 1.081023, acc: 96%] [G loss: 1.093937]
[Epoch 12/100] [Batch 468/469] [D loss: 1.095930, acc: 99%] [G loss: 1.099756]
[Epoch 13/100] [Batch 468/469] [D loss: 1.091788, acc: 97%] [G loss: 1.096789]
[Epoch 14/100] [Batch 468/469] [D loss: 1.099218, acc: 96%] [G loss: 1.109792]
[Epoch 15/100] [Batch 468/469] [D loss: 1.056762, acc: 98%] [G loss: 1.126807]
[Epoch 16/100] [Batch 468/469] [D loss: 1.088305, acc: 96%] [G loss: 1.103586]
[Epoch 17/100] [Batch 468/469] [D loss: 1.102751, acc: 97%] [G loss: 1.113332]
[Epoch 18/100] [Batch 468/469] [D loss: 1.082917, acc: 96%] [G loss: 1.093896]
[Epoch 19/100] [Batch 468/469] [D loss: 1.129379, acc: 98%] [G loss: 1.066369]
[Epoch 20/100] [Batch 468/469] [D loss: 1.088398, acc: 96%] [G loss: 1.124479]
[Epoch 21/100] [Batch 468/469] [D loss: 1.075817, acc: 97%] [G loss: 1.062265]
[Epoch 22/100] [Batch 468/469] [D loss: 1.092206, acc: 97%] [G loss: 1.080536]
[Epoch 23/100] [Batch 468/469] [D loss: 1.083714, acc: 99%] [G loss: 1.120035]
[Epoch 24/100] [Batch 468/469] [D loss: 1.065568, acc: 96%] [G loss: 1.092086]
[Epoch 25/100] [Batch 468/469] [D loss: 1.065326, acc: 98%] [G loss: 1.079625]
[Epoch 26/100] [Batch 468/469] [D loss: 1.083590, acc: 94%] [G loss: 1.066061]
[Epoch 27/100] [Batch 468/469] [D loss: 1.093708, acc: 98%] [G loss: 1.066264]
[Epoch 28/100] [Batch 468/469] [D loss: 1.098876, acc: 96%] [G loss: 1.046513]
[Epoch 29/100] [Batch 468/469] [D loss: 1.065514, acc: 98%] [G loss: 1.138119]
[Epoch 30/100] [Batch 468/469] [D loss: 1.082466, acc: 98%] [G loss: 1.091829]
[Epoch 31/100] [Batch 468/469] [D loss: 1.115253, acc: 98%] [G loss: 1.075734]
[Epoch 32/100] [Batch 468/469] [D loss: 1.083843, acc: 97%] [G loss: 1.094761]
[Epoch 33/100] [Batch 468/469] [D loss: 1.077276, acc: 98%] [G loss: 1.061793]
[Epoch 34/100] [Batch 468/469] [D loss: 1.051831, acc: 98%] [G loss: 1.061515]
[Epoch 35/100] [Batch 468/469] [D loss: 1.049085, acc: 97%] [G loss: 1.091401]
[Epoch 36/100] [Batch 468/469] [D loss: 1.107189, acc: 97%] [G loss: 1.104072]
[Epoch 37/100] [Batch 468/469] [D loss: 1.085251, acc: 98%] [G loss: 1.014494]
[Epoch 38/100] [Batch 468/469] [D loss: 1.055244, acc: 98%] [G loss: 1.128277]
[Epoch 39/100] [Batch 468/469] [D loss: 1.074688, acc: 97%] [G loss: 1.211257]
[Epoch 40/100] [Batch 468/469] [D loss: 1.020138, acc: 98%] [G loss: 1.099206]
[Epoch 41/100] [Batch 468/469] [D loss: 1.028032, acc: 98%] [G loss: 1.139912]
[Epoch 42/100] [Batch 468/469] [D loss: 1.094773, acc: 97%] [G loss: 1.123720]
[Epoch 43/100] [Batch 468/469] [D loss: 1.063132, acc: 98%] [G loss: 1.151915]
[Epoch 44/100] [Batch 468/469] [D loss: 1.044639, acc: 98%] [G loss: 1.127079]
[Epoch 45/100] [Batch 468/469] [D loss: 1.047207, acc: 97%] [G loss: 0.941165]
[Epoch 46/100] [Batch 468/469] [D loss: 1.153255, acc: 98%] [G loss: 1.064194]
[Epoch 47/100] [Batch 468/469] [D loss: 1.041365, acc: 97%] [G loss: 1.129444]
[Epoch 48/100] [Batch 468/469] [D loss: 1.117032, acc: 97%] [G loss: 1.110979]
[Epoch 49/100] [Batch 468/469] [D loss: 1.091151, acc: 97%] [G loss: 1.079596]
[Epoch 50/100] [Batch 468/469] [D loss: 1.045083, acc: 97%] [G loss: 1.115737]
[Epoch 51/100] [Batch 468/469] [D loss: 1.078201, acc: 98%] [G loss: 1.042152]
[Epoch 52/100] [Batch 468/469] [D loss: 0.993151, acc: 97%] [G loss: 1.135464]
[Epoch 53/100] [Batch 468/469] [D loss: 1.158597, acc: 97%] [G loss: 1.045841]
[Epoch 54/100] [Batch 468/469] [D loss: 1.077160, acc: 98%] [G loss: 1.180580]
[Epoch 55/100] [Batch 468/469] [D loss: 1.081528, acc: 98%] [G loss: 1.082192]
[Epoch 56/100] [Batch 468/469] [D loss: 1.051033, acc: 96%] [G loss: 1.181082]
[Epoch 57/100] [Batch 468/469] [D loss: 1.123516, acc: 94%] [G loss: 1.107539]
[Epoch 58/100] [Batch 468/469] [D loss: 1.066718, acc: 94%] [G loss: 1.013356]
[Epoch 59/100] [Batch 468/469] [D loss: 1.103453, acc: 98%] [G loss: 1.317525]
[Epoch 60/100] [Batch 468/469] [D loss: 1.007531, acc: 95%] [G loss: 0.980590]
[Epoch 61/100] [Batch 468/469] [D loss: 1.025996, acc: 96%] [G loss: 1.193597]
[Epoch 62/100] [Batch 468/469] [D loss: 1.042114, acc: 96%] [G loss: 1.175320]
[Epoch 63/100] [Batch 468/469] [D loss: 0.943264, acc: 98%] [G loss: 1.230064]
[Epoch 64/100] [Batch 468/469] [D loss: 1.079207, acc: 98%] [G loss: 1.161710]
[Epoch 65/100] [Batch 468/469] [D loss: 1.043449, acc: 98%] [G loss: 0.989506]
[Epoch 66/100] [Batch 468/469] [D loss: 1.066983, acc: 98%] [G loss: 1.354617]
[Epoch 67/100] [Batch 468/469] [D loss: 1.089749, acc: 98%] [G loss: 1.055511]
[Epoch 68/100] [Batch 468/469] [D loss: 1.203126, acc: 95%] [G loss: 1.052433]
[Epoch 69/100] [Batch 468/469] [D loss: 1.083899, acc: 98%] [G loss: 1.340578]
[Epoch 70/100] [Batch 468/469] [D loss: 1.103002, acc: 99%] [G loss: 1.214381]
[Epoch 71/100] [Batch 468/469] [D loss: 0.968297, acc: 99%] [G loss: 1.174415]
[Epoch 72/100] [Batch 468/469] [D loss: 1.024843, acc: 97%] [G loss: 1.083050]
[Epoch 73/100] [Batch 468/469] [D loss: 1.199783, acc: 98%] [G loss: 1.148810]
[Epoch 74/100] [Batch 468/469] [D loss: 1.085408, acc: 97%] [G loss: 1.163345]
[Epoch 75/100] [Batch 468/469] [D loss: 1.087018, acc: 97%] [G loss: 1.109405]
[Epoch 76/100] [Batch 468/469] [D loss: 1.010831, acc: 98%] [G loss: 1.325916]
[Epoch 77/100] [Batch 468/469] [D loss: 1.092120, acc: 96%] [G loss: 1.058283]
[Epoch 78/100] [Batch 468/469] [D loss: 1.082102, acc: 97%] [G loss: 1.159579]
[Epoch 79/100] [Batch 468/469] [D loss: 1.078881, acc: 96%] [G loss: 1.023906]
[Epoch 80/100] [Batch 468/469] [D loss: 1.134373, acc: 98%] [G loss: 1.261664]
[Epoch 81/100] [Batch 468/469] [D loss: 1.049532, acc: 98%] [G loss: 1.188655]
[Epoch 82/100] [Batch 468/469] [D loss: 1.060618, acc: 98%] [G loss: 1.166402]
[Epoch 83/100] [Batch 468/469] [D loss: 1.020341, acc: 96%] [G loss: 1.256302]
[Epoch 84/100] [Batch 468/469] [D loss: 1.116723, acc: 97%] [G loss: 1.056611]
[Epoch 85/100] [Batch 468/469] [D loss: 1.055123, acc: 97%] [G loss: 1.047174]
[Epoch 86/100] [Batch 468/469] [D loss: 1.036949, acc: 99%] [G loss: 1.130135]
[Epoch 87/100] [Batch 468/469] [D loss: 1.035721, acc: 97%] [G loss: 1.163391]
[Epoch 88/100] [Batch 468/469] [D loss: 1.082056, acc: 98%] [G loss: 1.516514]
[Epoch 89/100] [Batch 468/469] [D loss: 1.036912, acc: 98%] [G loss: 1.305870]
[Epoch 90/100] [Batch 468/469] [D loss: 1.161742, acc: 96%] [G loss: 1.124942]
[Epoch 91/100] [Batch 468/469] [D loss: 1.059311, acc: 95%] [G loss: 1.285748]
[Epoch 92/100] [Batch 468/469] [D loss: 1.060407, acc: 97%] [G loss: 1.189411]
[Epoch 93/100] [Batch 468/469] [D loss: 0.923837, acc: 97%] [G loss: 1.381471]
[Epoch 94/100] [Batch 468/469] [D loss: 0.947491, acc: 98%] [G loss: 1.243434]
[Epoch 95/100] [Batch 468/469] [D loss: 1.011180, acc: 97%] [G loss: 1.212379]
[Epoch 96/100] [Batch 468/469] [D loss: 1.023346, acc: 98%] [G loss: 1.094416]
[Epoch 97/100] [Batch 468/469] [D loss: 1.115852, acc: 96%] [G loss: 1.148246]
[Epoch 98/100] [Batch 468/469] [D loss: 1.025092, acc: 97%] [G loss: 1.255130]
[Epoch 99/100] [Batch 468/469] [D loss: 1.059351, acc: 97%] [G loss: 1.173633]

图片输出
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/581370.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

视频批量下载工具

1、功能演示 该工具实现了某个人主页视频批量下载,最多支持一次下载50个视频,这50个选取的是最新发布的50个视频,视频为高清的1080p,并直接将视频保存到本地。 2、软件使用介绍 2.1 解压 拿到工具软件后,首先是对软件…

什么是外汇爆仓?怎样避免?

外汇爆仓是指当交易者的保证金低于特定比例时,经纪商会自动平仓一个或所有的开仓头寸。避免外汇爆仓的关键在于合理配置资金、设置止损、适度交易、顺势而为以及调整心态。 外汇爆仓是外汇交易中的一种风险控制机制。当交易者的账户净值低于已用保证金的特定比例时&…

AI图书推荐:《企业AI转型:如何在企业中部署ChatGPT?》

Jay R. Enterprise AI in the Cloud. A Practical Guide...ChatGPT Solutions (《企业AI转型:如何在企业中部署ChatGPT?》)是一本由Rabi Jay撰写、于2024年由John Wiley & Sons出版的书籍,主要为企业提供实施AI转型…

【网络安全】00后程序员,找 Bug 赚了 6,700,000元!他是怎么做到的?

1. 漏洞赏金计划(Bug Bounty Programs) 2. 安全咨询服务 3. 安全培训和教育 4. 写作和发表研究 5. 参与安全竞赛(CTFs) 6. 开发和销售安全工具 在网络安全领域,通过合法的方式利用漏洞赚钱主要涉及以下几种方法。…

【服务器部署篇】Linux下Tomcat安装和配置

作者介绍:本人笔名姑苏老陈,从事JAVA开发工作十多年了,带过刚毕业的实习生,也带过技术团队。最近有个朋友的表弟,马上要大学毕业了,想从事JAVA开发工作,但不知道从何处入手。于是,产…

记录一次 vue3 + ele pls 改写 饿了么主题色实践

一、改写 element 主题色 在 main.ts 中引入需要改写的 scss 文件 main.ts: import ./styles/element-plus.scss在自定义的 element-plus.scss 文件中改写 ele pls 的变量 element-plus.scss: /** * 更改主题色 */ :root {--el-color-primary: #285fbb; // 主…

python使用opencv对图像的基本操作(3)

17.颜色空间的转换 17.1.rgb图像转gray图像 from skimage import io,color img io.imread(lbxx.jpg) img_gray color.rgb2gray(img) #将rgb图像转换成gray图像 io.imshow(img_gray)运行结果: 17.2.rgb图像转hsv图像 from skimage import io,color img io.im…

网红大佬的面子,高阶智驾的里子 | 2024北京车展

相关阅读:2023北京车展 《没有争奇斗艳的车模,只有往死里卷的智能汽车》。 文|刘俊宏 李想、李斌绑定“车圈新顶流”雷军互相抬轿子,红衣大叔周鸿祎高情商点评各家汽车新品...... 为了流量,今年车企大佬们比任何时候…

volatile的相关知识点

volatitle这个关键字,不管是在Java还是在C中都有使用到,但是在两种语言中,由于编译器的原因,他们存在一点点区别。 C中的volatile关键字 在C中volatile主要用于告诉编译器,这个变量的值可能会意外改变 ,例如被硬件或者…

力扣刷题 62.不同路径

题干 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径? …

HertzBeat:一款开源实时监控告警系统,简直太好用了!

😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~ 🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 🎐 个人CSND主页——Mi…

训练营第三十六天动态规划(基础题part2)

训练营第三十六天动态规划(基础题part2) 62.不同路径 力扣题目链接 题目 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&am…

企业计算机服务器中了rmallox勒索病毒怎么办,rmallox勒索病毒解密流程

对于众多的企业来说,通过网络开展各项工作业务已经成为常态,网络为企业的生产运营提供了极大便利,也大大加快了企业发展的步伐,但众多企业越来越重视企业发展中的核心数据安全问题。近期,云天数据恢复中心接到众多企业…

Linux的学习之路:21、线程(1)

摘要: 本章说一下线程 目录 摘要: 一、回忆一下 二、如何理解线程 三、命令行看线程 四、利用函数进行使用 五、本章总结 1、线程的优点 2、线程的缺点 3、线程的异常 4、线程的用途 一、回忆一下 1、exe就是一个文件 2、我们的可执行程序…

企业工厂如何逆风翻盘:VR全景打破多重桎梏

现阶段,制造业工厂面临的困境,就是用着上百万的设备,却赚着几毛钱的利润。传统的工厂参观方式也存在着很多的局限性,例如时间上不方便、不能实地参访、生产线具有隐患等,都会使得参观者不能深入地了解工厂的生产环境和…

大模型对数字营销的驱动赋能

一、大模型驱动的营销数智化个信未来发展趋势 1.模型算法能力全面升级 大模型凭借智能化的用户洞察,个性化的需求预测、系统化的数据分析、效率化的营销决策以及实实化的全域检测支持,为营销行业更加准确地把握市场动态和消费者需求提供了强大支持。可以…

ubuntu22.04 修改内核源码教程

1. 确认当前内核版本 uname -a 2. 去ubuntu官网下载对应版本内核源码 6.5.0-28.29 : linux package : Ubuntu (launchpad.net) 3. 准备编译环境 sudo apt-get install libncurses5-dev libssl-dev build-essential openssl flex bison libelf-dev tar -xzvf linux_6.5.…

【VS+QT】visual studio 2022配置和搭建QT

一、下载QT 可以去QT官网下载:https://www.qt.io/product/development-tools。 直接安装。 二、安装qt插件 打开visual studio 2022,选择菜单栏中扩展->管理扩展 ,然后直接在vs插件市场搜索Qt Visual Studio Tools就行。 安装的时候根据提示,关闭…

动态规划|714.买卖股票的最佳时机含手续费

力扣题目链接 class Solution { public:int maxProfit(vector<int>& prices, int fee) {int n prices.size();vector<vector<int>> dp(n, vector<int>(2, 0));dp[0][0] - prices[0]; // 持股票for (int i 1; i < n; i) {dp[i][0] max(dp[i …

java案例-服务端与客户端(传输对象)

需求 代码 SysUser 用户类Operation 操作类Client 客户端Server 服务端ServerReaderThread 服务端线程类 SysUser 用户类 需要实现Serializable 方便序列化&#xff0c;传输对象 public class SysUser implements Serializable {private String username;private String passwo…