定义参数

  • 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. C# Wke使用例子 (KyozyWke)

    概述 wke是国人大牛BlzFans封装的webkit, 基于chrome浏览器源代码的裁剪版本, 大小只有仅仅10M. 无需依赖其他的扩展库就可以在本地使用谷歌内核快速加载网页. wke是2011年 ...

  2. 如何使用Vite创建Vue3的uniapp项目

    项目结构 my-vue3-project ├─ .env //默认环境变量 ├─ .env.development //开发环境变量 ├─ .eslintrc-auto-import.json //( ...

  3. ES 2023新特性速解

    ES 2023新特性速解 一.新增数组方法 操作数组的方法 Array.prototype.toSorted(compareFn) //返回一个新数组,其中元素按升序排序,而不改变原始数组. Arra ...

  4. 慢SQL治理实践及落地成果分享

    一.治理背景 数据库系统性能问题会对应用程序的性能和用户体验产生负面影响.慢查询可能导致应用程序响应变慢.请求堆积.系统负载增加等问题,甚至引发系统崩溃或不可用的情况.慢SQL治理是在数据库系统中针对 ...

  5. JS逆向实战23 某市wss URL加密+请求头+ws收发

    声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 本文首发链接为: http ...

  6. 带宽优化新思路:RoCE网卡聚合实现X2增长

    本文分享自华为云社区<2个RoCE网卡Bond聚合,实现带宽X2>,作者: tsjsdbd . 我们知道操作系统里面,可以将2个实际的物理网卡,合体形成一个"逻辑网卡" ...

  7. Vue2系列(lqz)——Vue基础

    文章目录 Vue介绍 一 模板语法 1.1 插值 1.1.1 概述 1.1.2 案例 二 指令 2.1 文本相关指令 2.2 事件指令 2.3 属性指令 三 class与style 3.1 class ...

  8. Python并发编程——协程、Greenlet模块、Gevent模块、Gevent之同步与异步、Gevent应用

    文章目录 一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二 一 引子 本节的主题是基于单线程 ...

  9. Python来源介绍

    python来源 1.1 Python来源 1989年的圣诞节,一位来自荷兰,名叫Guidio van Rossum的年轻帅小伙子,为了打发无趣的时光,决定改善他参与设计,不是很满意的ABC语言,随着 ...

  10. Java-网络编程(TCP-UDP)

    Java-网络编程(TCP-UDP) 网络基础 网络编程最主要的工作就是在发送端把信息通过规定好的协议进行组装包,在接收端按照规定好的协议把包进行解析,从而提取出对应的信息,达到通信的目的.中间最主要 ...