深度学习--DCGAN

news2024/11/30 12:53:01

代码之后的注释和GAN的一样,大家如果已经掌握GAN,可以忽略掉哦!!!

在学习DCGAN之前,我们要先掌握GAN,深度学习--生成对抗网络GAN-CSDN博客  这篇博客讲的就是GAN的相关知识,还是很详细的。

DCGAN论文:1511.06434 (arxiv.org)

我们先来了解一下DCGAN的原理

DCGAN原理

在学习原理之前,我们要先复习一下GAN的结构,如下图:

DCGAN模型

 它的生成器的结构如下:

生成器的输入是噪声,输出是图片。

在生成器之中,我们就用到了转置卷积的结构,进行了上采样。 

它在不断地提高分辨率,减少通道数。

判别器的结构:

使用的是下采样的卷积 。

它的输入是64*64的图像,输出是真假的判别。

他在不断地提高通道数,减少分辨率。

DCGAN工程技巧

也就是DCGAN与GAN的不同之处:

 简单翻译一下,意思就是:

1.在网络深层去除全连接层,

2.使用带步长的卷积替换池化,

3.在生成器的输出层使用Tanh激活函数,在其他层使用ReLu,

4.在判别器中使用LeakyReLu激活函数,

5.只对生成器模型的输出层和判别器模型的输入层Batch Normalization,BN可以稳定学习,有助于处理初始化不良导致的训练问题。也就是采用了批归一化, 将每一层的输入变换到0均值和单位方差(或者说转变到[0,1]范围内)。

预备知识

torch.nn.BatchNorm1d

nn.BatchNorm1d 是 PyTorch 中的一个用于一维数据(例如序列或时间序列)的批标准化(Batch Normalization)层。

批标准化是一种常用的神经网络正则化技术,旨在加速训练过程并提高模型的收敛性和稳定性。它通过对每个输入小批次的特征进行归一化处理来规范化输入数据的分布。

在一维数据上使用 nn.BatchNorm1d 层时,它会对每个特征维度上的数据进行标准化处理。具体而言,它会计算每个特征维度的均值和方差,并将输入数据进行中心化和缩放,以使其分布接近均值为0、方差为1的标准正态分布。

torch.nn.ConvTranspose2d

这是反卷积,也就是转置卷积的函数.

参数如下:

torch.nn.ConvTranspose2d(

in_channels, out_channels, kernel_size, stride=1, padding=0,

output_padding=0, groups=1,  bias=True, dilation=1, padding_mode='zeros',

device=None, dtype=None)

转置卷积的计算步骤在下面的视频中,简单粗暴

转置卷积这样算就简单多了~_哔哩哔哩_bilibili

torch.nn.Dropout2d

有多个channel的二维输出。赋值对象是彩色的图像数据(batch N,通道 C,高度 H,宽 W)的一个通道里的每一个数据。即输入为 Input: (N, C, H, W) 时,对每一个通道维度 C 按概率赋值为 0

适用性:nn.Dropout2d用于将 dropout 正则化应用于卷积层,要求输入和输出数据为4维(N,C,H,W)。卷积层用于处理空间数据,例如图像,它们具有二维结构。

维度:它在二维张量上运行。如果您有一个 shape 的输入张量(batch_size, channels, height, width),nn.Dropout2d则会独立地将 dropout 应用于每个通道的空间维度,使每个通道独立清零

有利于促进独立性特征图。

torch.nn.functional.leaky_relu

相当于LeakyReLu函数

函数图像如下 

代码

导库

import matplotlib.pyplot as plt
import matplotlib
import torch
from torch.utils.data import DataLoader
import torchvision
from torchvision import transforms
import numpy as np
import torch.nn.functional as F

加载处理数据集

# 导入数据集并且进行数据处理
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize(0.5, 0.5)])
traindata = torchvision.datasets.MNIST(root='D:\learn_pytorch\数据集', train=True, download=True,
                                       transform=transform)  # 训练集60,000张用于训练
# 利用DataLoader加载数据集
trainload = DataLoader(dataset=traindata, shuffle=True, batch_size=64)

在加载数据集时,我们要将数据进行归一化,在GAN中,我们就需要将数据归一化到(-1,1)之间,这是为什么呢?原因是我们在下面会用到Tanh激活函数,而Tanh函数的范围是在-1到1之间的,见下图

在我们既然知道了为什么要这样,下面就要学会如何做到了 

ToTensor中,我们是将数据的范围限制在了(0,1)之间,而后面的Normalize是将数据限制在(-1,1)之间,计算公式为(x-均值)/方差 

生成器

class Generator(torch.nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.linear1 = torch.nn.Linear(100, 7 * 7 * 256)
        self.bn1 = torch.nn.BatchNorm1d(7 * 7 * 256)
        self.uconv1 = torch.nn.ConvTranspose2d(256, 128, kernel_size=(3, 3), padding=1)
        self.bn2 = torch.nn.BatchNorm2d(128)
        self.uconv2 = torch.nn.ConvTranspose2d(128, 64, kernel_size=(4, 4), stride=2, padding=1)
        self.bn3 = torch.nn.BatchNorm2d(64)
        self.uconv3 = torch.nn.ConvTranspose2d(64, 1, kernel_size=(4, 4), stride=2, padding=1)

    def forward(self, x):
        # print('--------------------------------------')
        # print('x.shape:',x.shape)
        x = F.relu(self.linear1(x))  # torchsize([,])    .
        x = F.relu(self.bn1(x))
        # print('x.shape:',x.shape)
        x = self.bn1(x)
        x = x.view(-1, 256, 7, 7)  # 64,256,7,7
        # print('x.shape:',x.shape)
        x = F.relu(self.uconv1(x))
        # print('x.shape:',x.shape)
        x = self.bn2(x)
        # print('x.shape:', x.shape)
        x = F.relu(self.uconv2(x))
        # print('x.shape:', x.shape)
        x = self.bn3(x)
        # print('x.shape:', x.shape)
        x = torch.tanh(self.uconv3(x))
        # print('x.shape:', x.shape)#torch.Size([64, 1, 28, 28])
        return x

判别器

# 判别器,最后判断0,1,这意味着最后可以是一个神经元或者两个神经元
class Discraiminator(torch.nn.Module):
    def __init__(self):
        super(Discraiminator, self).__init__()

        self.conv1 = torch.nn.Conv2d(1, 64, 3, 2)
        self.conv2 = torch.nn.Conv2d(64, 128, 3, 2)
        self.bn = torch.nn.BatchNorm2d(128)
        self.fc = torch.nn.Linear(128 * 6 * 6, 1)

    def forward(self, x):
        # print('--------------------')
        # print('x.shape:', x.shape)#x.shape: torch.Size([64, 1, 28, 28])
        x = F.dropout2d(F.leaky_relu(self.conv1(x)), p=0.3)
        # print('x.shape:', x.shape)#x.shape: torch.Size([64, 128, 6, 6])
        x = F.dropout2d(F.leaky_relu(self.conv2(x)), p=0.3)
        # print('x.shape:', x.shape)#x.shape: torch.Size([64, 128, 6, 6])
        x = self.bn(x)
        x = x.view(-1, 128 * 6 * 6)
        # print('x.shape:', x.shape)#x.shape: torch.Size([64, 4608])
        x = torch.sigmoid(self.fc(x))
        # print('x.shape:', x.shape)#torch.size([64,1])
        return x

 定义损失函数,优化函数和优化器

# 定义损失函数和优化函数
device = 'cuda' if torch.cuda.is_available() else 'cpu'
gen = Generator().to(device)
dis = Discraiminator().to(device)
# 定义优化器
gen_opt = torch.optim.Adam(gen.parameters(), lr=0.0001)
dis_opt = torch.optim.Adam(dis.parameters(), lr=0.0001)
loss_fn = torch.nn.BCELoss()  # 损失函数

在这里,我们选择使用BCELoss,交叉熵损失函数,这是因为在GAN中,判别器通常被视为一个二分类器,它试图区分输入是真实样本还是由生成器生成的假样本,而BCELoss就是用来做二分类的损失函数,正好对应。

在优化器部分,它们分别对生成器和判别器的参数进行优化。

图像显示

# 图像显示
def gen_img_plot(model, testdata):
    pre = np.squeeze(model(testdata).detach().cpu().numpy())
    # tensor.detach()
    # 返回一个新的tensor,从当前计算图中分离下来的,但是仍指向原变量的存放位置,不同之处只是requires_grad为false,得到的这个tensor永远不需要计算其梯度,不具有grad。
    # 即使之后重新将它的requires_grad置为true,它也不会具有梯度grad
    # 这样我们就会继续使用这个新的tensor进行计算,后面当我们进行反向传播时,到该调用detach()的tensor就会停止,不能再继续向前进行传播
    plt.figure()
    for i in range(16):
        plt.subplot(4, 4, i + 1)
        plt.imshow(pre[i])
    plt.show()

因为我们最终要得到要得到的是处理数据输出的数组,所以我们要用squeeze将额外的单维度删除。

detach是单独开辟空间来保存数据,从而保证数据的稳定性。

plt.figure用来生成一个新画布。

 使用subplot函数在一个4x4的网格中定位每个子图。i + 1是因为子图的索引是从1开始的,而不是从0开始。 

imshow是在子图中显示图像。

最后的show来显示整体的图像。

后向传播及可视化

# 后向传播
dis_loss = []  # 判别器损失值记录
gen_loss = []  # 生成器损失值记录
lun = []  # 轮数
for epoch in range(100):
    d_epoch_loss = 0
    g_epoch_loss = 0
    cout = len(trainload)  # 938批次
    for step, (img, _) in enumerate(trainload):
        img = img.to(device)  # 图像数据
        # print('img.size:',img.shape)#img.size: torch.Size([64, 1, 28, 28])
        size = img.size(0)  # 一批次的图片数量64
        # 随机生成一批次的100维向量样本,或者说100个像素点
        random_noise = torch.randn(size, 100, device=device)
        # 先进性判断器的后向传播
        dis_opt.zero_grad()
        real_output = dis(img)
        d_real_loss = loss_fn(real_output, torch.ones_like(real_output))  # 真实数据的损失函数值
        d_real_loss.backward()

        gen_img = gen(random_noise)
        fake_output = dis(gen_img.detach())
        d_fake_loss = loss_fn(fake_output, torch.zeros_like(fake_output))  # 人造的数据的损失函数值
        d_fake_loss.backward()

        d_loss = d_real_loss + d_fake_loss
        dis_opt.step()

        # 生成器的后向传播
        gen_opt.zero_grad()
        fake_output = dis(gen_img)
        g_loss = loss_fn(fake_output, torch.ones_like(fake_output))
        g_loss.backward()
        gen_opt.step()
        d_epoch_loss += d_loss
        g_epoch_loss += g_loss
    dis_loss.append(float(d_epoch_loss))
    gen_loss.append(float(g_epoch_loss))
    print(f'第{epoch + 1}轮的生成器损失值:{g_epoch_loss},判别器损失值{d_epoch_loss}')
    lun.append(epoch + 1)
matplotlib.rcParams['font.sans-serif'] = ['KaiTi']
plt.figure()
plt.plot(lun, dis_loss, 'r', label='判别器损失值')
plt.plot(lun, gen_loss, 'b', label='生成器损失值')
plt.xlabel('训练轮数',  fontsize=12)
plt.ylabel('损失值', fontsize=12)
plt.title('损失值随着训练轮数得变化情况:',fontsize=18)
plt.show()
random_noise = torch.randn(16, 100, device=device)
gen_img_plot(gen, random_noise)

使用enumerate遍历训练数据集trainload,其中img是图像数据,但_表示我们在这里不使用标签(因为GAN是无监督的)。

step()用来更新判别器的模型参数。

在生成器的后向传播部分,

我们先进行梯度清零,然后通过生成器生成假图像,然后进行前向传播。

我们期望判别器对假图像的评分接近1(真实),因此我们将目标标签设置为与fake_output形状相同的全1张量torch.ones_like(fake_output)。

在这里,d_loss和g_loss是一张图像中的损失值,而d_epoch_loss和g_epoch_loss是每一轮损失值的累加,用于最后图像的绘制。

随机生成的噪声有16个样本,100个维度

全部代码

import matplotlib.pyplot as plt
import matplotlib
import torch
from torch.utils.data import DataLoader
import torchvision
from torchvision import transforms
import numpy as np
import torch.nn.functional as F

# 导入数据集并且进行数据处理
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize(0.5, 0.5)])
traindata = torchvision.datasets.MNIST(root='D:\learn_pytorch\数据集', train=True, download=True,
                                       transform=transform)  # 训练集60,000张用于训练
# 利用DataLoader加载数据集
trainload = DataLoader(dataset=traindata, shuffle=True, batch_size=64)


# GAN生成对抗网络,步骤:
# 首先编写生成器和判别器
# 然后固定生成器,用我们的数据优化判别器,试得我们最开始生成器生成的图片判断为0,真实图片判断为1
# 接着固定判别器,利用我们的判别器判断生成器生成的图片,以判断的尽可能接近一为目的优化我们的生成器
# 生成器的代码(针对手写字体识别)
class Generator(torch.nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.linear1 = torch.nn.Linear(100, 7 * 7 * 256)
        self.bn1 = torch.nn.BatchNorm1d(7 * 7 * 256)
        self.uconv1 = torch.nn.ConvTranspose2d(256, 128, kernel_size=(3, 3), padding=1)
        self.bn2 = torch.nn.BatchNorm2d(128)
        self.uconv2 = torch.nn.ConvTranspose2d(128, 64, kernel_size=(4, 4), stride=2, padding=1)
        self.bn3 = torch.nn.BatchNorm2d(64)
        self.uconv3 = torch.nn.ConvTranspose2d(64, 1, kernel_size=(4, 4), stride=2, padding=1)

    def forward(self, x):
        # print('--------------------------------------')
        # print('x.shape:',x.shape)
        x = F.relu(self.linear1(x))  # torchsize([,])    .
        x = F.relu(self.bn1(x))
        # print('x.shape:',x.shape)
        x = self.bn1(x)
        x = x.view(-1, 256, 7, 7)  # 64,256,7,7
        # print('x.shape:',x.shape)
        x = F.relu(self.uconv1(x))
        # print('x.shape:',x.shape)
        x = self.bn2(x)
        # print('x.shape:', x.shape)
        x = F.relu(self.uconv2(x))
        # print('x.shape:', x.shape)
        x = self.bn3(x)
        # print('x.shape:', x.shape)
        x = torch.tanh(self.uconv3(x))
        # print('x.shape:', x.shape)#torch.Size([64, 1, 28, 28])
        return x


# 判别器,最后判断0,1,这意味着最后可以是一个神经元或者两个神经元
class Discraiminator(torch.nn.Module):
    def __init__(self):
        super(Discraiminator, self).__init__()

        self.conv1 = torch.nn.Conv2d(1, 64, 3, 2)
        self.conv2 = torch.nn.Conv2d(64, 128, 3, 2)
        self.bn = torch.nn.BatchNorm2d(128)
        self.fc = torch.nn.Linear(128 * 6 * 6, 1)

    def forward(self, x):
        # print('--------------------')
        # print('x.shape:', x.shape)#x.shape: torch.Size([64, 1, 28, 28])
        x = F.dropout2d(F.leaky_relu(self.conv1(x)), p=0.3)
        # print('x.shape:', x.shape)#x.shape: torch.Size([64, 128, 6, 6])
        x = F.dropout2d(F.leaky_relu(self.conv2(x)), p=0.3)
        # print('x.shape:', x.shape)#x.shape: torch.Size([64, 128, 6, 6])
        x = self.bn(x)
        x = x.view(-1, 128 * 6 * 6)
        # print('x.shape:', x.shape)#x.shape: torch.Size([64, 4608])
        x = torch.sigmoid(self.fc(x))
        # print('x.shape:', x.shape)#torch.size([64,1])
        return x


# 定义损失函数和优化函数
device = 'cuda' if torch.cuda.is_available() else 'cpu'
gen = Generator().to(device)
dis = Discraiminator().to(device)
# 定义优化器
gen_opt = torch.optim.Adam(gen.parameters(), lr=0.0001)
dis_opt = torch.optim.Adam(dis.parameters(), lr=0.0001)
loss_fn = torch.nn.BCELoss()  # 损失函数


# 图像显示
def gen_img_plot(model, testdata):
    pre = np.squeeze(model(testdata).detach().cpu().numpy())
    # tensor.detach()
    # 返回一个新的tensor,从当前计算图中分离下来的,但是仍指向原变量的存放位置,不同之处只是requires_grad为false,得到的这个tensor永远不需要计算其梯度,不具有grad。
    # 即使之后重新将它的requires_grad置为true,它也不会具有梯度grad
    # 这样我们就会继续使用这个新的tensor进行计算,后面当我们进行反向传播时,到该调用detach()的tensor就会停止,不能再继续向前进行传播
    plt.figure()
    for i in range(16):
        plt.subplot(4, 4, i + 1)
        plt.imshow(pre[i])
    plt.show()


# 后向传播
dis_loss = []  # 判别器损失值记录
gen_loss = []  # 生成器损失值记录
lun = []  # 轮数
for epoch in range(100):
    d_epoch_loss = 0
    g_epoch_loss = 0
    cout = len(trainload)  # 938批次
    for step, (img, _) in enumerate(trainload):
        img = img.to(device)  # 图像数据
        # print('img.size:',img.shape)#img.size: torch.Size([64, 1, 28, 28])
        size = img.size(0)  # 一批次的图片数量64
        # 随机生成一批次的100维向量样本,或者说100个像素点
        random_noise = torch.randn(size, 100, device=device)
        # 先进性判断器的后向传播
        dis_opt.zero_grad()
        real_output = dis(img)
        d_real_loss = loss_fn(real_output, torch.ones_like(real_output))  # 真实数据的损失函数值
        d_real_loss.backward()

        gen_img = gen(random_noise)
        fake_output = dis(gen_img.detach())
        d_fake_loss = loss_fn(fake_output, torch.zeros_like(fake_output))  # 人造的数据的损失函数值
        d_fake_loss.backward()

        d_loss = d_real_loss + d_fake_loss
        dis_opt.step()

        # 生成器的后向传播
        gen_opt.zero_grad()
        fake_output = dis(gen_img)
        g_loss = loss_fn(fake_output, torch.ones_like(fake_output))
        g_loss.backward()
        gen_opt.step()
        d_epoch_loss += d_loss
        g_epoch_loss += g_loss
    dis_loss.append(float(d_epoch_loss))
    gen_loss.append(float(g_epoch_loss))
    print(f'第{epoch + 1}轮的生成器损失值:{g_epoch_loss},判别器损失值{d_epoch_loss}')
    lun.append(epoch + 1)
matplotlib.rcParams['font.sans-serif'] = ['KaiTi']
plt.figure()
plt.plot(lun, dis_loss, 'r', label='判别器损失值')
plt.plot(lun, gen_loss, 'b', label='生成器损失值')
plt.xlabel('训练轮数',  fontsize=12)
plt.ylabel('损失值', fontsize=12)
plt.title('损失值随着训练轮数得变化情况:',fontsize=18)
plt.show()
random_noise = torch.randn(16, 100, device=device)
gen_img_plot(gen, random_noise)

运行结果

第1轮的生成器损失值:1637.9466552734375,判别器损失值464.1025695800781
第2轮的生成器损失值:2530.494384765625,判别器损失值305.1524353027344
第3轮的生成器损失值:2997.694580078125,判别器损失值222.53155517578125
第4轮的生成器损失值:3006.974365234375,判别器损失值275.3566589355469
第5轮的生成器损失值:3013.507080078125,判别器损失值306.8394775390625
第6轮的生成器损失值:3041.133056640625,判别器损失值317.3689270019531
第7轮的生成器损失值:3017.63427734375,判别器损失值323.7129821777344
第8轮的生成器损失值:3007.423828125,判别器损失值324.5998840332031
第9轮的生成器损失值:3128.52783203125,判别器损失值313.85247802734375
第10轮的生成器损失值:3165.2890625,判别器损失值310.9962158203125
第11轮的生成器损失值:3216.90673828125,判别器损失值292.4429931640625
第12轮的生成器损失值:3296.56396484375,判别器损失值286.9037780761719
第13轮的生成器损失值:3320.12255859375,判别器损失值291.0125732421875
第14轮的生成器损失值:3348.47802734375,判别器损失值278.4036560058594
第15轮的生成器损失值:3400.251708984375,判别器损失值286.7728576660156
第16轮的生成器损失值:3417.241943359375,判别器损失值287.98321533203125
第17轮的生成器损失值:3390.15380859375,判别器损失值282.5353088378906
第18轮的生成器损失值:3410.00732421875,判别器损失值281.8512878417969
第19轮的生成器损失值:3500.480224609375,判别器损失值294.86407470703125
第20轮的生成器损失值:3470.27392578125,判别器损失值292.0498046875
第21轮的生成器损失值:3449.343505859375,判别器损失值283.53033447265625
第22轮的生成器损失值:3558.106689453125,判别器损失值301.805908203125
第23轮的生成器损失值:3544.840087890625,判别器损失值284.54559326171875
第24轮的生成器损失值:3507.136474609375,判别器损失值296.3019104003906
第25轮的生成器损失值:3535.285888671875,判别器损失值292.21417236328125
第26轮的生成器损失值:3483.247802734375,判别器损失值319.2896728515625
第27轮的生成器损失值:3452.71533203125,判别器损失值300.94207763671875
第28轮的生成器损失值:3441.982177734375,判别器损失值305.394287109375
第29轮的生成器损失值:3545.740234375,判别器损失值292.4477233886719
第30轮的生成器损失值:3500.8740234375,判别器损失值299.3537902832031
第31轮的生成器损失值:3530.58837890625,判别器损失值290.83367919921875
第32轮的生成器损失值:3547.6357421875,判别器损失值303.5927734375
第33轮的生成器损失值:3536.327392578125,判别器损失值299.1307373046875
第34轮的生成器损失值:3599.991943359375,判别器损失值293.924560546875
第35轮的生成器损失值:3553.3603515625,判别器损失值307.1707763671875
第36轮的生成器损失值:3607.927734375,判别器损失值301.6771240234375
第37轮的生成器损失值:3578.015380859375,判别器损失值307.1168212890625
第38轮的生成器损失值:3564.02197265625,判别器损失值304.1378479003906
第39轮的生成器损失值:3477.672119140625,判别器损失值307.8915100097656
第40轮的生成器损失值:3523.138427734375,判别器损失值300.7839660644531
第41轮的生成器损失值:3580.55615234375,判别器损失值296.95367431640625
第42轮的生成器损失值:3537.208984375,判别器损失值317.746826171875
第43轮的生成器损失值:3497.8994140625,判别器损失值333.478759765625
第44轮的生成器损失值:3499.179443359375,判别器损失值309.1123352050781
第45轮的生成器损失值:3470.083984375,判别器损失值319.6141052246094
第46轮的生成器损失值:3515.869873046875,判别器损失值321.9976806640625
第47轮的生成器损失值:3509.823486328125,判别器损失值310.7447814941406
第48轮的生成器损失值:3486.165283203125,判别器损失值330.5418395996094
第49轮的生成器损失值:3492.86083984375,判别器损失值324.3530578613281
第50轮的生成器损失值:3480.895263671875,判别器损失值343.64190673828125
第51轮的生成器损失值:3458.932373046875,判别器损失值335.3240661621094
第52轮的生成器损失值:3449.647216796875,判别器损失值320.6033630371094
第53轮的生成器损失值:3507.733154296875,判别器损失值340.7387390136719
第54轮的生成器损失值:3528.40185546875,判别器损失值352.86712646484375
第55轮的生成器损失值:3414.6552734375,判别器损失值343.109130859375
第56轮的生成器损失值:3427.310546875,判别器损失值352.00225830078125
第57轮的生成器损失值:3446.245849609375,判别器损失值371.7415771484375
第58轮的生成器损失值:3488.618896484375,判别器损失值343.9029846191406
第59轮的生成器损失值:3388.469482421875,判别器损失值351.0376281738281
第60轮的生成器损失值:3410.164794921875,判别器损失值354.8907165527344
第61轮的生成器损失值:3424.15625,判别器损失值354.5815124511719
第62轮的生成器损失值:3369.984130859375,判别器损失值371.8444519042969
第63轮的生成器损失值:3419.359619140625,判别器损失值375.1051025390625
第64轮的生成器损失值:3432.91796875,判别器损失值344.61578369140625
第65轮的生成器损失值:3324.12109375,判别器损失值364.02874755859375
第66轮的生成器损失值:3386.9599609375,判别器损失值387.5386962890625
第67轮的生成器损失值:3340.77392578125,判别器损失值369.8281555175781
第68轮的生成器损失值:3354.0810546875,判别器损失值367.2720642089844
第69轮的生成器损失值:3291.53662109375,判别器损失值378.1933898925781
第70轮的生成器损失值:3375.2119140625,判别器损失值350.12457275390625
第71轮的生成器损失值:3324.4580078125,判别器损失值357.1696472167969
第72轮的生成器损失值:3334.96875,判别器损失值363.599365234375
第73轮的生成器损失值:3353.963623046875,判别器损失值372.2528381347656
第74轮的生成器损失值:3279.52001953125,判别器损失值381.4432678222656
第75轮的生成器损失值:3248.873291015625,判别器损失值359.6973876953125
第76轮的生成器损失值:3334.107177734375,判别器损失值385.186279296875
第77轮的生成器损失值:3272.5595703125,判别器损失值373.97161865234375
第78轮的生成器损失值:3282.48388671875,判别器损失值374.6603698730469
第79轮的生成器损失值:3315.8173828125,判别器损失值400.2161865234375
第80轮的生成器损失值:3250.458984375,判别器损失值406.6080627441406
第81轮的生成器损失值:3347.8037109375,判别器损失值359.7836608886719
第82轮的生成器损失值:3269.06982421875,判别器损失值390.88812255859375
第83轮的生成器损失值:3244.718994140625,判别器损失值386.9516906738281
第84轮的生成器损失值:3229.3994140625,判别器损失值402.3242492675781
第85轮的生成器损失值:3282.469482421875,判别器损失值392.0705871582031
第86轮的生成器损失值:3261.463134765625,判别器损失值367.95782470703125
第87轮的生成器损失值:3246.7060546875,判别器损失值398.2889099121094
第88轮的生成器损失值:3325.021240234375,判别器损失值391.1697692871094
第89轮的生成器损失值:3181.181396484375,判别器损失值400.4288024902344
第90轮的生成器损失值:3212.197998046875,判别器损失值384.01031494140625
第91轮的生成器损失值:3181.767578125,判别器损失值386.2222595214844
第92轮的生成器损失值:3253.033447265625,判别器损失值381.6040344238281
第93轮的生成器损失值:3239.474853515625,判别器损失值393.23797607421875
第94轮的生成器损失值:3275.764404296875,判别器损失值387.4879150390625
第95轮的生成器损失值:3249.69482421875,判别器损失值353.1047668457031
第96轮的生成器损失值:3305.953857421875,判别器损失值386.5541687011719
第97轮的生成器损失值:3298.284423828125,判别器损失值380.4208068847656
第98轮的生成器损失值:3199.724609375,判别器损失值389.3112487792969
第99轮的生成器损失值:3217.61962890625,判别器损失值392.8823547363281
第100轮的生成器损失值:3273.804443359375,判别器损失值378.09771728515625

进程已结束,退出代码为 0

生成图片 

这里训练了100轮,其实30轮就差不多,这里可以清楚的看出来,我们生成器生成的图片(我们是以手写字体数据集为例子),很接近真实图片了。 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

8个免费无版权视频素材网站,高清无水印视频任性下载

在数字化时代,优质的视频素材成为各种项目不可缺少的元素,从短片制作到商业广告,高品质的视频能显著提高作品的吸引力和传播效果。然而,寻找既免费又无版权问题的高清视频素材并非易事。以下介绍几个优秀的免费视频素材网站&#…

ORA-609频繁出现在alert.log,如何解决?

ORA-609就alertlog中比较常见的一个报错,虽然并没有太大的影响,但是频繁的出现在alert log也是很让人厌烦的事情,本文介绍如何排查解决ORA-609问题。 1.ORA-609官方定义 could not attach to incoming connection Cause Oracle process cou…

通过linux花里胡哨的控制台,学习linux基础命令

今天这个B我装定了! 前言命令集 开始1、cowsay (让牛说话,够无聊的,但牛说的话是你输入的,细思极恐!)Debian/Ubuntu 安装命令:RHEL/CentOS/Fedora 安装:运行解释 2、fort…

libssh C++封装之七(File)

1 概述 libssh是一个在客户端和服务器端实现SSHv2协议的多平台C库。使用libssh,您可以远程执行程序、传输文件、使用安全透明的隧道、管理公钥等等。本文描述的对libssh客户端功能的C++封装。 libssh下载地址 3 实现 3.6 File File类型可以读写远程文件。 3.6.1 File定义 …

李宏毅-注意力机制详解

原视频链接:attention 一. 基本问题分析 1. 模型的input 无论是预测视频观看人数还是图像处理,输入都可以看作是一个向量,输出是一个数值或类别。然而,若输入是一系列向量,长度可能会不同,例如把句子里的…

Attention Sink

论文发现自回归LLM存在的一个有趣现象:对于输入文本最靠前的少量几个token,无论它们在语义上与语言建模任务的相关性如何,大量的注意力分数都会分配给他们,如下图所示: 模型的前两层还能保持attention score更多分配给…

第四步->手撕spring源码之bena注入实现和依赖

本步骤目标 上述几个步骤 定义和注册Bean (opens new window)、实例化Bean (opens new window),按照是否包含构造函数实现不同的实例化策略 (opens new window),那么在创建对象实例化这我们还缺少什么?其实还缺少一个关于类中是否有属性的问题…

【应用浅谈】Odoo的库存计价与产品成本(二)

序言:时间是我们最宝贵的财富,珍惜手上的每个时分 Odoo的库存(Stock)模块拥有众多功能,其中库存计价是一项非常重要的功能,原生的成本方法分三种:【标准成本】,【平均成本】,【先进先出】&#…

【算法】竞赛常用知识之字符串1

前言: 本系列是学习了董晓老师所讲的知识点做的笔记 董晓算法的个人空间-董晓算法个人主页-哔哩哔哩视频 (bilibili.com) 动态规划系列(还没学完) 【算法】动态规划之线性DP问题-CSDN博客 【算法】动态规划之背包DP问题(2024…

Mybatis-Plus大批量插入数据到MySQL

MyBatis-Plus的saveBatch方法 GetMapping("/save1") public void save1() {// 数据准备List<MallOrder> orderList getMallOrderList();// mybatis-pluslong start System.currentTimeMillis();mallOrderService.saveBatch(orderList);System.out.println(&…

java中EQ、NE、GE、GT、LE、LT

关系运算符 包括EQ、NE、GE、GT、LE、LT几个&#xff0c;关系运算符返回的是真“True”或假“False”。 eq&#xff08;Equal to&#xff09; 等 运算符 &#xff0c;如果运算符两边相同则返回真&#xff0c;否则返回假&#xff1b; ne&#xff08;Not Equal to&#xff09; 不…

美术:模型动画

游戏模型制作流程&#xff0c;SP和BP根据情况来选择软件对UV进行处理 3Dmax 制作模型和动画&#xff08;橘肉&#xff09;RizomUV 对模型进行展UV&#xff08;橘皮&#xff09;Substance Painter 纹理手绘&#xff08;给橘皮制定想要的皮肤&#xff09;BodyPaint 3D 纹理手绘&a…

Hive Transaction事务表(含实现原理)

Hive Transaction事务表 在Hive中&#xff0c;事务表&#xff08;Transactional Tables&#xff09;允许用户执行事务性操作&#xff0c;包括ACID&#xff08;原子性、一致性、隔离性、持久性&#xff09;特性。事务表是在Hive 0.14版本引入的&#xff0c;并且在后续版本中不断…

最新的云渲染100活动有哪些?渲染100邀请码1a12

随着科技的进步&#xff0c;云渲染已经成为设计行业的必备工具&#xff0c;各个云渲染平台为了吸引用户也推出各种各样的活动&#xff0c;今天我们以广受好评的渲染100为例&#xff0c;来说下它们的活动体系。 1、新用户活动 渲染100对新用户很友好&#xff0c;提供了充足的测…

PyTorch的卷积和池化

卷积计算 input 表示输入的图像filter 表示卷积核, 也叫做滤波器input 经过 filter 的得到输出为最右侧的图像&#xff0c;该图叫做特征图 卷积的计算是将卷积核放入左上角&#xff0c;在局部区域间做点积&#xff0c;然后将卷积核在Input上面依次从左向右&#xff0c;从上到下…

STM32串口通信入门

文章目录 一、串口协议和RS-232标准&#xff0c;以及RS232电平与TTL电平的区别1.串口通信协议2.RS-232标准3.RS232电平与TTL电平的区别4.USB/TTL转232“模块&#xff08;CH340芯片为例&#xff09; 二、补充实验&#xff08;一&#xff09;几个常见的库函数、结构体1.时钟配置函…

LeetCode—用队列实现栈

一.题目 二.思路 1.后入先出的实现&#xff1a; 创建两个队列来实现栈&#xff08;后入先出&#xff09;&#xff1a; 两个队列&#xff0c;保持一个存数据&#xff0c;另一个为空&#xff0c;入数据&#xff08;push&#xff09;要入不为空的队列&#xff0c;&#xff08;p…

深圳晶彩智能ESP32-1732S019实时观看GPIO的状态

深圳晶彩智能ESP32-1732S019介绍 ESP32-1732S019开发板是基于ESP32-S3-WROOM-1模块作为主控&#xff0c;双核MCU ,集成WI-FI和蓝牙功能&#xff0c;主控频率可达240MHz , 512KB SRAM , 384KB ROM&#xff0c;8M PSRAM&#xff0c;16MB Flash&#xff0c;显示分辨率为170*320 I…

冯喜运:5.12黄金回撤继续上涨,下周原油走势分析

【黄金消息面分析】&#xff1a;本周&#xff0c;黄金市场迎来了自4月中旬以来的最佳单周表现。周五&#xff08;3月9日&#xff09;&#xff0c;金价攀升至2360.54美元/盎司&#xff0c;涨幅0.62%&#xff0c;而纽约商品交易所6月交割的黄金期货价格上涨1.5%&#xff0c;收报2…

Springboot+Vue项目-基于Java+MySQL的毕业就业信息管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…