定义参数

  • dataroot - the path to the root of the dataset folder. We will talk more about the dataset in the next section.

  • workers - the number of worker threads for loading the data with the DataLoader.

  • batch_size - the batch size used in training. The DCGAN paper uses a batch size of 128.

  • image_size - the spatial size of the images used for training. This implementation defaults to 64x64. If another size is desired, the structures of D and G must be changed. See here for more details.

  • nc - number of color channels in the input images. For color images this is 3.

  • nz - length of latent vector.

  • ngf - relates to the depth of feature maps carried through the generator.

  • ndf - sets the depth of feature maps propagated through the discriminator.

  • num_epochs - number of training epochs to run. Training for longer will probably lead to better results but will also take much longer.

  • lr - learning rate for training. As described in the DCGAN paper, this number should be 0.0002.

  • beta1 - beta1 hyperparameter for Adam optimizers. As described in paper, this number should be 0.5.

  • ngpu - number of GPUs available. If this is 0, code will run in CPU mode. If this number is greater than 0 it will run on that number of GPUs.

# Root directory for dataset
dataroot = "data/celeba" # 加载数据的线程数
workers = 2 # Batch size during training
batch_size = 128 # 训练图像的大小 64*64
image_size = 64 # 输入图像的颜色通道数 彩色图像
nc = 3 # Size of z latent vector (i.e. size of generator input)
# 潜在矢量 生成器的初始输入
nz = 100 # Size of feature maps in generator
ngf = 64 # Size of feature maps in discriminator
ndf = 64 # Number of training epochs
num_epochs = 5 # Learning rate for optimizers
lr = 0.0002 # Beta1 hyperparameter for Adam optimizers
# ADAM优化器的超参数
beta1 = 0.5 # Number of GPUs available. Use 0 for CPU mode.
ngpu = 1
# We can use an image folder dataset the way we have it setup.
# 创建数据集
dataset = dset.ImageFolder(root=dataroot,
transform=transforms.Compose([
transforms.Resize(image_size),
transforms.CenterCrop(image_size), #从图像中间裁剪
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), #数据标准化处理
]))
# 创建dataloader
dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size,
shuffle=True, num_workers=workers) # Decide which device we want to run on
device = torch.device("cuda:0" if (torch.cuda.is_available() and ngpu > 0) else "cpu") # Plot some training images
real_batch = next(iter(dataloader))
plt.figure(figsize=(8,8))
plt.axis("off")
plt.title("Training Images")
plt.imshow(np.transpose(vutils.make_grid(real_batch[0].to(device)[:64], padding=2, normalize=True).cpu(),(1,2,0)))
# 定义生成器
# Generator Code class Generator(nn.Module):
def __init__(self, ngpu):
super(Generator, self).__init__()
self.ngpu = ngpu
self.main = nn.Sequential(
# input is Z, going into a convolution
nn.ConvTranspose2d( nz, ngf * 8, 4, 1, 0, bias=False),
nn.BatchNorm2d(ngf * 8),
nn.ReLU(True),
# state size. ``(ngf*8) x 4 x 4``
nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False),
nn.BatchNorm2d(ngf * 4),
nn.ReLU(True),
# state size. ``(ngf*4) x 8 x 8``
nn.ConvTranspose2d( ngf * 4, ngf * 2, 4, 2, 1, bias=False),
nn.BatchNorm2d(ngf * 2),
nn.ReLU(True),
# state size. ``(ngf*2) x 16 x 16``
nn.ConvTranspose2d( ngf * 2, ngf, 4, 2, 1, bias=False),
nn.BatchNorm2d(ngf),
nn.ReLU(True),
# state size. ``(ngf) x 32 x 32``
nn.ConvTranspose2d( ngf, nc, 4, 2, 1, bias=False),
nn.Tanh()
# state size. ``(nc) x 64 x 64``
) def forward(self, input):
return self.main(input)

这段代码定义了生成器(Generator)的网络结构。

生成器的输入是一个随机噪声向量 Z,通过一系列转置卷积层(ConvTranspose2d)和批归一化层(BatchNorm2d),最终输出一个与真实数据相似的合成样本。

具体来说,生成器包含以下层:

第一层:将输入的随机噪声 Z 经过转置卷积层(nn.ConvTranspose2d)得到 ngf * 8 个特征图,尺寸为 4x4,然后经过批归一化层(nn.BatchNorm2d)和激活函数 ReLU 进行非线性变换。

第二层:将第一层的输出经过转置卷积层得到 ngf * 4 个特征图,尺寸为 8x8,然后经过批归一化层和激活函数 ReLU 进行非线性变换。

第三层:将第二层的输出经过转置卷积层得到 ngf * 2 个特征图,尺寸为 16x16,然后经过批归一化层和激活函数 ReLU 进行非线性变换。

第四层:将第三层的输出经过转置卷积层得到 ngf 个特征图,尺寸为 32x32,然后经过批归一化层和激活函数 ReLU 进行非线性变换。

最后一层:将第四层的输出经过转置卷积层得到 nc 个特征图,尺寸为 64x64,然后经过 Tanh 激活函数将像素值映射到 -1 到 1 的范围内,得到最终的生成样本。

这个生成器结构可以通过调整输入的随机噪声 Z 来生成不同的合成样本。根据具体应用场景的需求,可以调整网络结构和参数来优化生成效果。

nn.ConvTranspose2d()

nn.ConvTranspose2d()函数中各个参数的解释:

nz:输入通道数(input channels),也就是随机噪声向量 Z 的维度。

ngf * 8:输出通道数(output channels),生成器第一层转置卷积后得到的特征图数量。

4:转置卷积核大小,指定了卷积核在空间维度上的大小,这里是一个正方形卷积核,边长为 4。

1:步幅(stride),指定了卷积核在每个空间维度上的移动步长。

0:填充(padding),指定了在进行卷积操作之前在输入的空间维度周围添加的零值像素数。在这里,填充为 0 表示不进行填充操作。

bias=False:是否使用偏置项(bias)。这里设置为 False 表示不使用偏置项,意味着转置卷积层没有可学习的偏置参数。

nn.BatchNorm2d(ngf * 8)

这是 PyTorch 中的一个二维批标准化层 (BatchNorm2d) 操作。其中,ngf 是一个变量,表示生成器的第一层卷积层中使用的特征图数量(feature map),ngf * 8 表示该层中输入数据的通道数。BatchNorm2d 层会对该层输入的每个通道在 mini-batch 上计算均值和方差,并对其进行标准化处理,使得数据分布更加平稳、收敛更快。它通常用于卷积神经网络中的全连接层和卷积层之间,以及激活函数之前。

netG = Generator(ngpu).to(device)

# Handle multi-GPU if desired
if (device.type == 'cuda') and (ngpu > 1):
netG = nn.DataParallel(netG, list(range(ngpu))) # Apply the ``weights_init`` function to randomly initialize all weights
# to ``mean=0``, ``stdev=0.02``.
netG.apply(weights_init) # Print the model
print(netG)
Generator(
(main): Sequential(
(0): ConvTranspose2d(100, 512, kernel_size=(4, 4), stride=(1, 1), bias=False)
(1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU(inplace=True)
(3): ConvTranspose2d(512, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)
(4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(5): ReLU(inplace=True)
(6): ConvTranspose2d(256, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)
(7): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(8): ReLU(inplace=True)
(9): ConvTranspose2d(128, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)
(10): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(11): ReLU(inplace=True)
(12): ConvTranspose2d(64, 3, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)
(13): Tanh()
)
)

在PyTorch中,有两种常见的卷积运算的padding值可以由“地板除法”来计算。

  • 第一种情况:对转置卷积来说,当输入特征图尺寸(高和宽)为偶数时,可以选择一个kernel_size为偶数,步长stride=2的卷积核,此时padding用kernel_size//2 可以实现精确的2倍上采样(如4x4变8x8)。
  • 第二种情况:对普通卷积来说,当输入特征图尺寸(高和宽)为奇数时,可以选择一个kernel_size为奇数,步长stride=1的卷积核,此时padding用kernel_size//2 可以实现输出特征图尺寸不变。

判别器

class Discriminator(nn.Module):
def __init__(self, ngpu):
super(Discriminator, self).__init__()
self.ngpu = ngpu
self.main = nn.Sequential(
# input is ``(nc) x 64 x 64``
nn.Conv2d(nc, ndf, 4, 2, 1, bias=False),
nn.LeakyReLU(0.2, inplace=True),
# state size. ``(ndf) x 32 x 32``
nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False),
nn.BatchNorm2d(ndf * 2),
nn.LeakyReLU(0.2, inplace=True),
# state size. ``(ndf*2) x 16 x 16``
nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False),
nn.BatchNorm2d(ndf * 4),
nn.LeakyReLU(0.2, inplace=True),
# state size. ``(ndf*4) x 8 x 8``
nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, bias=False),
nn.BatchNorm2d(ndf * 8),
nn.LeakyReLU(0.2, inplace=True),
# state size. ``(ndf*8) x 4 x 4``
nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False),
nn.Sigmoid()
) def forward(self, input):
return self.main(input)
Discriminator(
(main): Sequential(
(0): Conv2d(3, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)
(1): LeakyReLU(negative_slope=0.2, inplace=True)
(2): Conv2d(64, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)
(3): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(4): LeakyReLU(negative_slope=0.2, inplace=True)
(5): Conv2d(128, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)
(6): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(7): LeakyReLU(negative_slope=0.2, inplace=True)
(8): Conv2d(256, 512, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)
(9): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(10): LeakyReLU(negative_slope=0.2, inplace=True)
(11): Conv2d(512, 1, kernel_size=(4, 4), stride=(1, 1), bias=False)
(12): Sigmoid()
)
)
\[ℓ(x,y)=L={l_
1
,…,l_
N
}
^⊤
,l
n
=−[y
n
⋅logx
n
+(1−y
n
)⋅log(1−x
n
)]\]
#BCEloss
# Initialize the ``BCELoss`` function
criterion = nn.BCELoss() # Create batch of latent vectors that we will use to visualize
# the progression of the generator
fixed_noise = torch.randn(64, nz, 1, 1, device=device) # Establish convention for real and fake labels during training
real_label = 1.
fake_label = 0. # Setup Adam optimizers for both G and D
optimizerD = optim.Adam(netD.parameters(), lr=lr, betas=(beta1, 0.999))
optimizerG = optim.Adam(netG.parameters(), lr=lr, betas=(beta1, 0.999))

损失函数

  • 交叉熵:nn.CrossEntropyLoss
\[H(P,Q)=−∑_{i=1} ^NP(x_i)logQ(x_i)
\]
  • 二分类交叉熵:n.BCELoss
\[l n=−wn[y_n⋅logx_n+(1−y_n)⋅log(1−x_n)]
\]
# Training Loop

# Lists to keep track of progress
img_list = []
G_losses = []
D_losses = []
iters = 0 print("Starting Training Loop...")
# For each epoch
for epoch in range(num_epochs):
# For each batch in the dataloader
for i, data in enumerate(dataloader, 0): ############################
# (1) Update D network: maximize log(D(x)) + log(1 - D(G(z)))
###########################
## Train with all-real batch
netD.zero_grad()
# Format batch
real_cpu = data[0].to(device)
b_size = real_cpu.size(0)
label = torch.full((b_size,), real_label, dtype=torch.float, device=device)
# Forward pass real batch through D
output = netD(real_cpu).view(-1)
# Calculate loss on all-real batch
errD_real = criterion(output, label)
# Calculate gradients for D in backward pass
errD_real.backward()
D_x = output.mean().item() ## Train with all-fake batch
# Generate batch of latent vectors
noise = torch.randn(b_size, nz, 1, 1, device=device)
# Generate fake image batch with G
fake = netG(noise)
label.fill_(fake_label)
# Classify all fake batch with D
output = netD(fake.detach()).view(-1)
# Calculate D's loss on the all-fake batch
errD_fake = criterion(output, label)
# Calculate the gradients for this batch, accumulated (summed) with previous gradients
errD_fake.backward()
D_G_z1 = output.mean().item()
# Compute error of D as sum over the fake and the real batches
errD = errD_real + errD_fake
# Update D
optimizerD.step() ############################
# (2) Update G network: maximize log(D(G(z)))
###########################
netG.zero_grad()
label.fill_(real_label) # fake labels are real for generator cost
# Since we just updated D, perform another forward pass of all-fake batch through D
output = netD(fake).view(-1)
# Calculate G's loss based on this output
errG = criterion(output, label)
# Calculate gradients for G
errG.backward()
D_G_z2 = output.mean().item()
# Update G
optimizerG.step() # Output training stats
if i % 50 == 0:
print('[%d/%d][%d/%d]\tLoss_D: %.4f\tLoss_G: %.4f\tD(x): %.4f\tD(G(z)): %.4f / %.4f'
% (epoch, num_epochs, i, len(dataloader),
errD.item(), errG.item(), D_x, D_G_z1, D_G_z2)) # Save Losses for plotting later
G_losses.append(errG.item())
D_losses.append(errD.item()) # Check how the generator is doing by saving G's output on fixed_noise
if (iters % 500 == 0) or ((epoch == num_epochs-1) and (i == len(dataloader)-1)):
with torch.no_grad():
fake = netG(fixed_noise).detach().cpu()
img_list.append(vutils.make_grid(fake, padding=2, normalize=True)) iters += 1

[复习随笔]python_dcgan网络复习小知识:模型定义的更多相关文章

  1. 【RL-TCPnet网络教程】第2章 嵌入式网络协议栈基础知识

    第2章        嵌入式网络协议栈基础知识 本章教程为大家介绍嵌入式网络协议栈基础知识,本章先让大家有一个全面的认识,后面章节中会为大家逐一讲解用到的协议. 基础知识整理自百度百科,wiki百科等 ...

  2. js中级小知识1

    首先我们复习之前的小知识,本期博客与之前有关 js数据类型 基本数据类型:string    undefined         null         boolean          numbe ...

  3. iOS网络相关零散知识总结

    iOS网络相关零散知识总结 1. URL和HTTP知识 (1) URL的全称是Uniform Resource Locator(统一资源定位符). URL的基本格式 = 协议://主机地址/路径   ...

  4. [小知识] 获取浏览器UA标识

    这个随笔纯粹是小知识的积累,以后都会打上小知识的标签. 经常见的,下载移动app时,只有一个二维码,但扫码后,会根据手机是iphone还是android下载不同app,下面就是这个操作的代码: < ...

  5. JVM(七),JVM面试小知识

    七.JVM面试小知识 1.JVM三大性能调优参数 -Xms -Xmx -Xss 的含义 2.java内存模型中堆和栈的区别 3.不同JDK版本中的intern()方法的区别

  6. 蓝牙Bluetooth技术小知识

    蓝牙Bluetooth技术以及广泛的应用于各种设备,并将继续在物联网IoT领域担任重要角色.下面搜集整理了一些关于蓝牙技术的小知识,以备参考. 蓝牙Bluetooth技术始创于1994年,其名字来源于 ...

  7. HTML+CSS中的一些小知识

    今天分享一些HTML.CSS的小知识,希望能够对大家有所帮助! 1.解决网页乱码的问题:最重要的是要保证各个环节的字符编码一致! (1)编辑器的编辑环境的字符集(默认字符集):Crtl+U 常见的编码 ...

  8. iOS APP开发的小知识(分享)

          亿合科技小编发现从2007年第一款智能手机横空出世,由此开启了人们的移动智能时代.我们从一开始对APP的陌生,到现在的爱不释手,可见APP开发的出现对我们的生活改变有多巨大.而iOS AP ...

  9. Unix系统小知识(转)

    Unix操作系统的小知识 2.VI添加行号/翻页/清屏 .在对话模式时(即输完Esc再输入: ),输入“:set number”可以将编辑的文本加上行号.跟玩俄罗斯方块一样方便的上下左右移动箭头的快捷 ...

  10. salesforce 零基础开发入门学习(十)IDE便捷小知识

    在这里介绍两个IDE的便捷开发的小知识. 一) 本地调试 由于salesforce代码只能提交以后才能调试,所以很多时候调试代码很麻烦.新版增加了一个特性:即可以在本地调试相关的代码或者查看相关代码运 ...

随机推荐

  1. SRC赏金猎人—笔记二

    以下是如何将速率限制漏洞的影响从低增加到高甚至严重 过程 1.我访问了该网站,然后开始在网站的主文件中手动查找main.js 2.我发现有一个 Web 服务托管在 http:// redacted.c ...

  2. 《最新出炉》系列初窥篇-Python+Playwright自动化测试-12-playwright操作iframe-中篇

    1.简介 按照计划今天就要用实际的例子进行iframe自动化测试.经过宏哥长时间的查找,终于找到了一个含有iframe的网页(QQ邮箱和163邮箱),别的邮箱宏哥就没有细看了.所以今天这一篇的主要内容 ...

  3. JSTL fn函数使用

    首先,我们要在页面的最上方引用: <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/function ...

  4. Antd Form表单中Input输入框 在IE9下按下任何按键都会报校验失败

    antd Form表单中Input输入框 在IE9下按下任何按键都会报校验失败,导致输入框输入不了任何内容! 可能你的react及react-dom版本由于过高导致antd组件不能兼容,需要对reac ...

  5. glog 日志库简介与测试【GO 常用的库】

    〇.前言 golang/glog 是 C++ 版本 google/glog 的 Go 版本实现,基本实现了原生 glog 的日志格式. 在 Kuberntes 中,glog 是默认日志库.因此需要详细 ...

  6. SpringBoot使用@Async注解8大坑点

    前言 SpringBoot中,@Async注解可以实现异步线程调用,用法简单,体验舒适. 但是你一定碰到过异步调用不生效的情况,今天,我就列出90%的人都可能会遇到的8大坑点. 正文 1.未启用异步支 ...

  7. destoon9.0游戏自媒体类型综合资讯门户模板

    随着时代发展,自媒体资讯适合当前的互联网情形.呕心沥血开发的一套自媒体综合门户网站模板,本模板采用纯手写开发,带会员中心.首页,列表页,内容页,搜索页面精心编写,非常大气,并配移动端.注意:模板目前只 ...

  8. mooc第五单元《管理组织》单元测试

    第五单元<管理组织>单元测试     返回 本次得分为:30.00/50.00, 本次测试的提交时间为:2020-08-30, 如果你认为本次测试成绩不理想,你可以选择 再做一次 . 1 ...

  9. MySQL误删恢复方法2

    实际工作中总会发生数据误删除的场景,在没有备份情况下,如何快速恢复误删数据就显得非常重要. 本文基于MySQL的binlog日志机制,当日志格式设置为"binlog_format=ROW&q ...

  10. vue 基于原生动画的自动滚动表格

    前言 公司展示大屏需要写滚动表格,通过滚动播放数据,自己随便摸了一个基于动画的自动滚动表格 原理 根据每行的大小和设置的每行滚动时间设置滚动位置,动态添加动画,并把数组第一项移动到最后一项,并订阅该动 ...