[复习随笔]python_dcgan网络复习小知识:模型定义
定义参数
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()
)
)
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
\]
- 二分类交叉熵:n.BCELoss
\]
# 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网络复习小知识:模型定义的更多相关文章
- 【RL-TCPnet网络教程】第2章 嵌入式网络协议栈基础知识
第2章 嵌入式网络协议栈基础知识 本章教程为大家介绍嵌入式网络协议栈基础知识,本章先让大家有一个全面的认识,后面章节中会为大家逐一讲解用到的协议. 基础知识整理自百度百科,wiki百科等 ...
- js中级小知识1
首先我们复习之前的小知识,本期博客与之前有关 js数据类型 基本数据类型:string undefined null boolean numbe ...
- iOS网络相关零散知识总结
iOS网络相关零散知识总结 1. URL和HTTP知识 (1) URL的全称是Uniform Resource Locator(统一资源定位符). URL的基本格式 = 协议://主机地址/路径 ...
- [小知识] 获取浏览器UA标识
这个随笔纯粹是小知识的积累,以后都会打上小知识的标签. 经常见的,下载移动app时,只有一个二维码,但扫码后,会根据手机是iphone还是android下载不同app,下面就是这个操作的代码: < ...
- JVM(七),JVM面试小知识
七.JVM面试小知识 1.JVM三大性能调优参数 -Xms -Xmx -Xss 的含义 2.java内存模型中堆和栈的区别 3.不同JDK版本中的intern()方法的区别
- 蓝牙Bluetooth技术小知识
蓝牙Bluetooth技术以及广泛的应用于各种设备,并将继续在物联网IoT领域担任重要角色.下面搜集整理了一些关于蓝牙技术的小知识,以备参考. 蓝牙Bluetooth技术始创于1994年,其名字来源于 ...
- HTML+CSS中的一些小知识
今天分享一些HTML.CSS的小知识,希望能够对大家有所帮助! 1.解决网页乱码的问题:最重要的是要保证各个环节的字符编码一致! (1)编辑器的编辑环境的字符集(默认字符集):Crtl+U 常见的编码 ...
- iOS APP开发的小知识(分享)
亿合科技小编发现从2007年第一款智能手机横空出世,由此开启了人们的移动智能时代.我们从一开始对APP的陌生,到现在的爱不释手,可见APP开发的出现对我们的生活改变有多巨大.而iOS AP ...
- Unix系统小知识(转)
Unix操作系统的小知识 2.VI添加行号/翻页/清屏 .在对话模式时(即输完Esc再输入: ),输入“:set number”可以将编辑的文本加上行号.跟玩俄罗斯方块一样方便的上下左右移动箭头的快捷 ...
- salesforce 零基础开发入门学习(十)IDE便捷小知识
在这里介绍两个IDE的便捷开发的小知识. 一) 本地调试 由于salesforce代码只能提交以后才能调试,所以很多时候调试代码很麻烦.新版增加了一个特性:即可以在本地调试相关的代码或者查看相关代码运 ...
随机推荐
- 园子的脱困努力-云厂商合作:领取阿里云免费ECS试用资源,部署Java Web环境,送小礼品
在园子脱困的关键时期,每一笔收入都很重要,一边在会员救园,一边我们要努力把握每一个商务合作机会,争取早日走出困境. 之前园子维持生存的收入主要来自于与云厂商的合作,但去年由于云厂商推广策略的调整,这块 ...
- 浅谈 Linux 下 vim 的使用
Vim 是从 vi 发展出来的一个文本编辑器,其代码补全.编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用. Vi 是老式的字处理器,功能虽然已经很齐全了,但还有可以进步的地方.Vim 可 ...
- 一次Python本地cache不当使用导致的内存泄露
背景 近期一个大版本上线后,Python编写的api主服务使用内存有较明显上升,服务重启后数小时就会触发机器的90%内存占用告警,分析后发现了本地cache不当使用导致的一个内存泄露问题,这里记录一下 ...
- Python操作Redis大全
一.字符串 string Python操作Redis的redis模块对字符串(string)的主要操作函数包括:SET.GET.GETSET.SETEX.SETNX.MSET.MSETNX.INCR( ...
- 超全技术学习资料PDF分享
技术学习资料分享,目前共20G,持续更新... Java学习资料: 大数据Hadoop: 这里不一一截图了,资源持续更新中. 关注下面公众号进行下载.
- html页面底部添加版权信息
话不多说,直接上代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:/ ...
- Kong网关
Kong网关 一.kong网关核心概念 1. Upstream upstream 对象表示虚拟主机名,可用于通过多个服务对传入请求进行负载远的 2. Target 目标ip地址/主机名,其端口表示后端 ...
- jenkin部署(docker+gitlab)
第一部分 安装部署 1.1 gitlab安装部署 最小配置 内存至少4g,系统内核至少在3.10以上 uname -r 可查看系统内核版本 默认docker已经安装 1.安装gitlab 127机器 ...
- 文心一言 VS 讯飞星火 VS chatgpt (94)-- 算法导论9.2 3题
三.用go语言,给出 RANDOMIZED-SELECT的一个基于循环的版本. 文心一言: 在循环中实现 RANDOMIZED-SELECT 的一个版本可以如下所示.这个版本使用 Go 语言编写,利用 ...
- vscode自动格式化python代码符合pep8
vscode自动格式化python代码符合pep8 安装格式化工具打开命令行窗口安装以下工具 $ pip install -U flake8$ pip install -U autopep812在VS ...