torch学习 (三十七):DCGAN详解

article/2025/8/26 22:21:35

文章目录

  • 引入
  • 1 生成器
  • 2 鉴别器
  • 3 模型训练:生成器与鉴别器的交互
  • 4 参数设置
  • 5 数据载入
  • 6 完整代码
  • 7 部分输出图像示意
    • 7.1 真实图像
    • 7.2 训练200个批次
    • 7.2 训练400个批次
    • 7.2 训练600个批次

引入

  论文详解Unsupervised representation learning with deep convolutional generative adversarial networks
  对抗生成网络的核心在于生成器鉴别器以及两者之间的交互,本文将详细对这几个部分进行介绍。

1 生成器

  DCGAN生成器的本质是多个卷积层、批量归一化、激活函数的堆叠,具体结构如下表:

结构输入通道输出通道卷积核大小步幅填充后续
ConvTranspose2dnzngf × \times × 8410BatchNorm2d+ReLU
ConvTranspose2dngf × \times × 8ngf × \times × 4421BatchNorm2d+ReLU
ConvTranspose2dngf × \times × 4ngf × \times × 2421BatchNorm2d+ReLU
ConvTranspose2dngf × \times × 2ngf421BatchNorm2d+ReLU
ConvTranspose2dngfnc421Tanh

其中nz为输入通道数,ngf为给定结点数,nc是输出类别数。例如对于MNIST数据集,可设置nz=100,ngf=64,nc=1。
  对应代码如下:

class Generator(nn.Module):"""生成器"""def __init__(self):super(Generator, self).__init__()# 使用的GPU数量self.ngpu = ngpu# 生成器结构,与表格中一致self.main = nn.Sequential(# 输入大小:nznn.ConvTranspose2d(nz, ngf * 8, 4, 1, 0, bias=False),nn.BatchNorm2d(ngf * 8),nn.ReLU(True),# 大小:(ngf*8) x 4 x 4nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False),nn.BatchNorm2d(ngf * 4),nn.ReLU(True),# 大小:(ngf*4) x 8 x 8nn.ConvTranspose2d(ngf * 4, ngf * 2, 4, 2, 1, bias=False),nn.BatchNorm2d(ngf * 2),nn.ReLU(True),# 大小:(ngf*2) x 16 x 16nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 1, bias=False),nn.BatchNorm2d(ngf),nn.ReLU(True),# 大小:(ngf) x 32 x 32nn.ConvTranspose2d(ngf, nc, 4, 2, 1, bias=False),nn.Tanh()# 大小:(nc) x 64 x 64)def forward(self, input):if input.is_cuda and self.ngpu > 1:output = nn.parallel.data_parallel(self.main, input, range(self.ngpu))else:output = self.main(input)return output

  生成器的结构输出如下 (接下来都以mnist为例):

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, 1, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)(13): Tanh())
)

2 鉴别器

  鉴别器与生成器的不同之处在于,其卷积层、激活函数的设置不同,输入通道数也是逐渐增加的:

结构输入通道输出通道卷积核大小步幅填充后续
Conv2dncndf421LeakyReLU(0.2)
Conv2dndfndf × \times × 2421BatchNorm2d+LeakyReLU(0.2)
Conv2dndf × \times × 2ndf × \times × 4421BatchNorm2d+LeakyReLU(0.2)
Conv2dndf × \times × 4ndf × \times × 8421BatchNorm2d+LeakyReLU(0.2)
Conv2dndf × \times × 81410Sigmid()

其中nc为输入通道数,ndf为给定结点数。注意输出通道变为1了哟。
  对应代码如下:

class Discriminator(nn.Module):"""鉴别器"""def __init__(self):super(Discriminator, self).__init__()# 使用的GPU数量self.ngpu = ngpu# 鉴别器的结构self.main = nn.Sequential(# 输入大小: (nc) x 64 x 64nn.Conv2d(nc, ndf, 4, 2, 1, bias=False),nn.LeakyReLU(0.2, inplace=True),# state size. (ndf) x 32 x 32nn.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 16nn.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 8nn.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 4nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False),nn.Sigmoid())def forward(self, input):# 与生成器类似哟if input.is_cuda and self.ngpu > 1:output = nn.parallel.data_parallel(self.main, input, range(self.ngpu))else:output = self.main(input)# 注意输出已经延展成一列的张量了return output.view(-1, 1).squeeze(1)

  鉴别器的结构输出如下:

Discriminator((main): Sequential((0): Conv2d(1, 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())
)

3 模型训练:生成器与鉴别器的交互

  下图绘制的是DCGAN生成器与鉴别器的交互过程,数字代表该步骤在程序中的运行过程:

  训练过程的代码如下:

def DCGAN():"""DCGAN主函数"""# 每一轮训练for epoch in range(opt.nepoch):# 每一个批次的训练for i, data in enumerate(dataset, 0):"""步骤1:训练鉴别器,即最大化log(D(x)) + log(1 - D(G(z)))"""# 首先基于真实图像进行训练# 鉴别器的梯度清零netD.zero_grad()# 格式化当前批次,这里data = data[0]的原因是因为所有批次的图像是放在一个列表里面的data = data[0].to(device)# 获取当前批次的图像的数量batch_size = data.size(0)# 将当前批次所有图像的标签设置为指定的真实标签,如1label = torch.full((batch_size, ), real_label, dtype=data.dtype, device=device)# 先鉴别器输出一下output = netD(data)# 计算鉴别器上基于真实图像计算的损失errorD_real = loss(output, label)errorD_real.backward()D_x = output.mean().item()# 训练虚假图像# 随机生成一个虚假图像noise = torch.randn(batch_size, nz, 1, 1, device=device)# 生成器开始造假fake = netG(noise)# 标签设置为假的标签label.fill_(fake_label)# 鉴别器来判断output = netD(fake.detach())# 假图片的损失errorD_fake = loss(output, label)errorD_fake.backward()# 假图片的梯度D_G_z1 = output.mean().item()# 鉴别器的总损失errorD = errorD_real + errorD_fake# 鉴别器优化一下optimD.step()"""训练生成器"""# 生成器梯度清零netG.zero_grad()# 生成器填真实标签,毕竟想造假label.fill_(real_label)# 得到假图片的输出output = netD(fake)# 计算生成器的损失errorG = loss(output, label)# 生成器梯度清零errorG.backward()# 再一次假图片的梯度D_G_z2 = output.mean().item()optimG.step()# 输出一些关键信息print("[%d/%d][%d/%d] lossD: %.4f lossG: %.4f ""D(x): %.4f D(G(z)): %.4f/%.4f" % (epoch, opt.nepoch, i, len(dataset),errorD.item(), errorG.item(),D_x, D_G_z1, D_G_z2))# 存储图像,可以设置想要的存储时间结点哈if i % 100 == 0:vutils.save_image(data, "real_image.png", normalize=True)fake = netG(fixed_noise)vutils.save_image(fake.detach(),'fake_image_%03d_%03d.png' % (epoch, i), normalize=True)

4 参数设置

  用的如下:

from __future__ import print_function
import argparse
import random
import torch
import torch.nn as nn
import torch.nn.parallel
import torch.optim as optim
import torch.utils.data
import torchvision.datasets as dset
import torchvision.transforms as transforms
import torchvision.utils as vutils

  相关参数设置,变量的信息于help中给出:

def get_parser():"""获取参数设置器"""parser = argparse.ArgumentParser()# 设置实验用数据集的类型,help中为所支持的数据集类型parser.add_argument("--dataset", required=False, default="mnist",help="数据集类型:cifar10 | lsun | mnist |imagenet | folder | lfw | fake")parser.add_argument("--data_root", required=False, help="数据集的存储路径",default=r"D:\Data\OneDrive\Code\MIL1\Data")parser.add_argument("--workers", type=int, default=2, help="数据集下载并行数")parser.add_argument("--batch_size", type=int, default=64, help="数据集的输入批次大小")parser.add_argument("--image_size", type=int, default=64, help="输入图像的高/宽")parser.add_argument("--nz", type=int, default=100, help="隐含向量z的大小")parser.add_argument("--ngf", type=int, default=64, help="生成器隐藏层结点数")parser.add_argument("--ndf", type=int, default=64, help="鉴别器隐藏层结点数")parser.add_argument("--nepoch", type=int, default=5, help="训练轮次数")parser.add_argument("--lr", type=float, default=0.0002, help="学习率")parser.add_argument("--beta1", type=float, default=0.5, help="Adam的beta1")parser.add_argument("--cuda", action="store_true", help="CUDA是否可用")parser.add_argument("--ngpu", type=int, default=1, help="GPU使用数量")parser.add_argument("--manual_seed", type=int, help="随机种子")parser.add_argument("--classes", default="bedroom", help="LSUN卧室数据集的列表划分分隔符")return parser.parse_args()

  管理随机种子

def get_seed():"""管理随机种子"""if opt.manual_seed is None:opt.manual_seed = random.randint(1, 10000)random.seed(opt.manual_seed)torch.manual_seed(opt.manual_seed)

  网络的权重等设置:

def init_weight(m):"""初始化权重"""classname = m.__class__.__name__if classname.find("Conv") != -1:torch.nn.init.normal_(m.weight, 0.0, 0.02)elif classname.find("BatchNorm") != -1:torch.nn.init.normal_(m.weight, 1.0, 0.02)torch.nn.init.zeros_(m.bias)

  主函数

if __name__ == '__main__':# 参数管理器opt = get_parser()# 设备device = torch.device("cuda:0" if opt.cuda else "cpu")# GPU数量、生成器输入通道数、生成器结点数设置、鉴别器结点数设置ngpu, nz, ngf, ndf = int(opt.ngpu), int(opt.nz), int(opt.ngf), int(opt.ndf)# 数据集、输出通道数dataset, nc = get_data()# 启动生成器netG = Generator().to(device)netG.apply(init_weight)# 启动鉴别器netD = Discriminator().to(device)netD.apply(init_weight)# 损失函数loss = nn.BCELoss()# 设置噪声及标签fixed_noise, real_label, fake_label = torch.randn(opt.batch_size, nz, 1, 1, device=device), 1, 0# 启动优化器optimG = optim.Adam(netG.parameters(), lr=opt.lr, betas=(opt.beta1, 0.999))optimD = optim.Adam(netD.parameters(), lr=opt.lr, betas=(opt.beta1, 0.999))DCGAN()

5 数据载入

  所集成的数据集如下:

def get_data():"""获取数据集"""# 输出通道数nc = 3if opt.dataset in ["imagenet", "folder", "lfw"]:dataset = dset.ImageFolder(root=opt.data_root,transform=transforms.Compose([transforms.Resize(opt.image_size),transforms.CenterCrop(opt.image_size),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),]))elif opt.dataset == "lsun":classes = [c + "_train" for c in opt.classes.split(',')]dataset = dset.LSUN(root=opt.data_root, classes=classes,transform=transforms.Compose([transforms.Resize(opt.image_size),transforms.CenterCrop(opt.image_size),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),]))elif opt.dataset == "cifar10":dataset = dset.CIFAR10(root=opt.data_root, download=True,transform=transforms.Compose([transforms.Resize(opt.image_size),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),]))elif opt.dataset == "mnist":dataset = dset.MNIST(root=opt.data_root, download=True,transform=transforms.Compose([transforms.Resize(opt.image_size),transforms.ToTensor(),transforms.Normalize((0.5,), (0.5,)),]))nc = 1else:dataset = dset.FakeData(image_size=(3, opt.image_size, opt.image_size),transform=transforms.ToTensor())return (torch.utils.data.DataLoader(dataset, batch_size=opt.batch_size, shuffle=True, num_workers=int(opt.workers)),nc)

6 完整代码

from __future__ import print_function
import argparse
import random
import torch
import torch.nn as nn
import torch.nn.parallel
import torch.optim as optim
import torch.utils.data
import torchvision.datasets as dset
import torchvision.transforms as transforms
import torchvision.utils as vutilsdef get_parser():"""获取参数设置器"""parser = argparse.ArgumentParser()# 设置实验用数据集的类型,help中为所支持的数据集类型parser.add_argument("--dataset", required=False, default="mnist",help="数据集类型:cifar10 | lsun | mnist |imagenet | folder | lfw | fake")parser.add_argument("--data_root", required=False, help="数据集的存储路径",default=r"D:\Data\OneDrive\Code\MIL1\Data")parser.add_argument("--workers", type=int, default=2, help="数据集下载并行数")parser.add_argument("--batch_size", type=int, default=64, help="数据集的输入批次大小")parser.add_argument("--image_size", type=int, default=64, help="输入图像的高/宽")parser.add_argument("--nz", type=int, default=100, help="隐含向量z的大小")parser.add_argument("--ngf", type=int, default=64, help="生成器隐藏层结点数")parser.add_argument("--ndf", type=int, default=64, help="鉴别器隐藏层结点数")parser.add_argument("--nepoch", type=int, default=5, help="训练轮次数")parser.add_argument("--lr", type=float, default=0.0002, help="学习率")parser.add_argument("--beta1", type=float, default=0.5, help="Adam的beta1")parser.add_argument("--cuda", action="store_true", help="CUDA是否可用")parser.add_argument("--ngpu", type=int, default=1, help="GPU使用数量")parser.add_argument("--manual_seed", type=int, help="随机种子")parser.add_argument("--classes", default="bedroom", help="LSUN卧室数据集的列表划分分隔符")return parser.parse_args()def get_seed():"""管理随机种子"""if opt.manual_seed is None:opt.manual_seed = random.randint(1, 10000)random.seed(opt.manual_seed)torch.manual_seed(opt.manual_seed)def get_data():"""获取数据集"""# 输出通道数nc = 3if opt.dataset in ["imagenet", "folder", "lfw"]:dataset = dset.ImageFolder(root=opt.data_root,transform=transforms.Compose([transforms.Resize(opt.image_size),transforms.CenterCrop(opt.image_size),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),]))elif opt.dataset == "lsun":classes = [c + "_train" for c in opt.classes.split(',')]dataset = dset.LSUN(root=opt.data_root, classes=classes,transform=transforms.Compose([transforms.Resize(opt.image_size),transforms.CenterCrop(opt.image_size),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),]))elif opt.dataset == "cifar10":dataset = dset.CIFAR10(root=opt.data_root, download=True,transform=transforms.Compose([transforms.Resize(opt.image_size),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),]))elif opt.dataset == "mnist":dataset = dset.MNIST(root=opt.data_root, download=True,transform=transforms.Compose([transforms.Resize(opt.image_size),transforms.ToTensor(),transforms.Normalize((0.5,), (0.5,)),]))nc = 1else:dataset = dset.FakeData(image_size=(3, opt.image_size, opt.image_size),transform=transforms.ToTensor())return (torch.utils.data.DataLoader(dataset, batch_size=opt.batch_size, shuffle=True, num_workers=int(opt.workers)),nc)def init_weight(m):"""初始化权重"""classname = m.__class__.__name__if classname.find("Conv") != -1:torch.nn.init.normal_(m.weight, 0.0, 0.02)elif classname.find("BatchNorm") != -1:torch.nn.init.normal_(m.weight, 1.0, 0.02)torch.nn.init.zeros_(m.bias)class Generator(nn.Module):"""生成器"""def __init__(self):super(Generator, self).__init__()# 使用的GPU数量self.ngpu = ngpu# 生成器结构,与表格中一致self.main = nn.Sequential(# 输入大小:nznn.ConvTranspose2d(nz, ngf * 8, 4, 1, 0, bias=False),nn.BatchNorm2d(ngf * 8),nn.ReLU(True),# 大小:(ngf*8) x 4 x 4nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False),nn.BatchNorm2d(ngf * 4),nn.ReLU(True),# 大小:(ngf*4) x 8 x 8nn.ConvTranspose2d(ngf * 4, ngf * 2, 4, 2, 1, bias=False),nn.BatchNorm2d(ngf * 2),nn.ReLU(True),# 大小:(ngf*2) x 16 x 16nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 1, bias=False),nn.BatchNorm2d(ngf),nn.ReLU(True),# 大小:(ngf) x 32 x 32nn.ConvTranspose2d(ngf, nc, 4, 2, 1, bias=False),nn.Tanh()# 大小:(nc) x 64 x 64)def forward(self, input):if input.is_cuda and self.ngpu > 1:output = nn.parallel.data_parallel(self.main, input, range(self.ngpu))else:output = self.main(input)return outputclass Discriminator(nn.Module):"""鉴别器"""def __init__(self):super(Discriminator, self).__init__()# 使用的GPU数量self.ngpu = ngpu# 鉴别器的结构self.main = nn.Sequential(# 输入大小: (nc) x 64 x 64nn.Conv2d(nc, ndf, 4, 2, 1, bias=False),nn.LeakyReLU(0.2, inplace=True),# state size. (ndf) x 32 x 32nn.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 16nn.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 8nn.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 4nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False),nn.Sigmoid())def forward(self, input):# 与生成器类似哟if input.is_cuda and self.ngpu > 1:output = nn.parallel.data_parallel(self.main, input, range(self.ngpu))else:output = self.main(input)# 注意输出已经延展成一列的张量了return output.view(-1, 1).squeeze(1)def DCGAN():"""DCGAN主函数"""# 每一轮训练for epoch in range(opt.nepoch):# 每一个批次的训练for i, data in enumerate(dataset, 0):"""步骤1:训练鉴别器,即最大化log(D(x)) + log(1 - D(G(z)))"""# 首先基于真实图像进行训练# 鉴别器的梯度清零netD.zero_grad()# 格式化当前批次,这里data = data[0]的原因是因为所有批次的图像是放在一个列表里面的data = data[0].to(device)# 获取当前批次的图像的数量batch_size = data.size(0)# 将当前批次所有图像的标签设置为指定的真实标签,如1label = torch.full((batch_size, ), real_label, dtype=data.dtype, device=device)# 先鉴别器输出一下output = netD(data)# 计算鉴别器上基于真实图像计算的损失errorD_real = loss(output, label)errorD_real.backward()D_x = output.mean().item()# 训练虚假图像# 随机生成一个虚假图像noise = torch.randn(batch_size, nz, 1, 1, device=device)# 生成器开始造假fake = netG(noise)# 标签设置为假的标签label.fill_(fake_label)# 鉴别器来判断output = netD(fake.detach())# 假图片的损失errorD_fake = loss(output, label)errorD_fake.backward()# 假图片的梯度D_G_z1 = output.mean().item()# 鉴别器的总损失errorD = errorD_real + errorD_fake# 鉴别器优化一下optimD.step()"""训练生成器"""# 生成器梯度清零netG.zero_grad()# 生成器填真实标签,毕竟想造假label.fill_(real_label)# 得到假图片的输出output = netD(fake)# 计算生成器的损失errorG = loss(output, label)# 生成器梯度清零errorG.backward()# 再一次假图片的梯度D_G_z2 = output.mean().item()optimG.step()# 输出一些关键信息print("[%d/%d][%d/%d] lossD: %.4f lossG: %.4f ""D(x): %.4f D(G(z)): %.4f/%.4f" % (epoch, opt.nepoch, i, len(dataset),errorD.item(), errorG.item(),D_x, D_G_z1, D_G_z2))# 存储图像,可以设置想要的存储时间结点哈if i % 100 == 0:vutils.save_image(data, "real_image.png", normalize=True)fake = netG(fixed_noise)vutils.save_image(fake.detach(),'fake_image_%03d_%03d.png' % (epoch, i), normalize=True)if __name__ == '__main__':# 参数管理器opt = get_parser()# 设备device = torch.device("cuda:0" if opt.cuda else "cpu")# GPU数量、生成器输入通道数、生成器结点数设置、鉴别器结点数设置ngpu, nz, ngf, ndf = int(opt.ngpu), int(opt.nz), int(opt.ngf), int(opt.ndf)# 数据集、输出通道数dataset, nc = get_data()# 启动生成器netG = Generator().to(device)netG.apply(init_weight)# 启动鉴别器netD = Discriminator().to(device)netD.apply(init_weight)# 损失函数loss = nn.BCELoss()# 设置噪声及标签fixed_noise, real_label, fake_label = torch.randn(opt.batch_size, nz, 1, 1, device=device), 1, 0# 启动优化器optimG = optim.Adam(netG.parameters(), lr=opt.lr, betas=(opt.beta1, 0.999))optimD = optim.Adam(netD.parameters(), lr=opt.lr, betas=(opt.beta1, 0.999))DCGAN()

7 部分输出图像示意

7.1 真实图像

7.2 训练200个批次

7.2 训练400个批次

7.2 训练600个批次

  设备有限,就这么多了:


http://chatgpt.dhexx.cn/article/Pa8NPb5r.shtml

相关文章

GANs系列:DCGAN原理简介与基础GAN的区别对比

本文长期不定时更新最新知识,防止迷路记得收藏哦! 还未了解基础GAN的,可以先看下面两篇文章: GNA笔记--GAN生成式对抗网络原理以及数学表达式解剖 入门GAN实战---生成MNIST手写数据集代码实现pytorch 背景介绍 2016年&#…

Pix2Pix和CycleGAN

GAN的局限性 即便如此,传统的GAN也不是万能的,它有下面两个不足: 1. 没有**用户控制(user control)**能力 在传统的GAN里,输入一个随机噪声,就会输出一幅随机图像。 但用户是有想法滴&#xff…

PyTorch 实现Image to Image (pix2pix)

目录 一、前言 二、数据集 三、网络结构 四、代码 (一)net (二)dataset (三)train (四)test 五、结果 (一)128*128 (二)256*256 …

pix2pix、pix2pixHD 通过损失日志进行训练可视化

目录 背景 代码 结果 总结 背景 pix2pix(HD)代码在训练时会自动保存一个损失变化的txt文件,通过该文件能够对训练过程进行一个简单的可视化,代码如下。 训练的损失文件如图,对其进行可视化。 代码 #coding:utf-8 ## #author: QQ&#x…

Pix2Pix代码解析

参考链接:https://github.com/yenchenlin/pix2pix-tensorflow https://blog.csdn.net/stdcoutzyx/article/details/78820728 utils.py from __future__ import division import math import json import random import pprint import scipy.misc import numpy as…

pix2pix 与 pix2pixHD的大致分析

目录 pix2pix与pix2pixHD的生成器 判别器 PatchGAN(马尔科夫判别器) 1、pix2pix 简单粗暴的办法 如何解决模糊呢? 其他tricks 2、pix2pixHD 高分辨率图像生成 模型结构 Loss设计 使用Instance-map的图像进行训练 语义编辑 总结 …

Tensorflow2.0之Pix2pix

文章目录 Pix2pix介绍Pix2pix应用Pix2pix生成器及判别器网络结构代码实现1、导入需要的库2、下载数据包3、加载并展示数据包中的图片4、处理图片4.1 将图像调整为更大的高度和宽度4.2 随机裁剪到目标尺寸4.3 随机将图像做水平镜像处理4.4 图像归一化4.5 处理训练集图片4.6 处理…

pix2pix算法笔记

论文:Image-to-Image Translation with Conditional Adversarial Networks 论文链接:https://arxiv.org/abs/1611.07004 代码链接:https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix 这篇论文发表在CVPR2017,简称pix2pix,是将GAN应用于有监督的图像到图像翻译的经…

Pix2Pix原理解析以及代码流程

文章目录 1、网络搭建2、反向传播过程3、PatchGAN4.与CGAN的不同之处 1、网络搭建 class UnetGenerator(nn.Module):"""Create a Unet-based generator"""def __init__(self, input_nc, output_nc, num_downs, ngf64, norm_layernn.BatchNorm2d…

图像翻译网络模型Pix2Pix

Pix2pix算法(Image-to-Image Translation,图像翻译),它的核心技术有三点:基于条件GAN的损失函数,基于U-Net的生成器和基于PatchGAN的判别器。Pix2Pix能够在诸多图像翻译任务上取得令人惊艳的效果,但因为它的输入是图像对&#xff…

GAN系列之pix2pix、pix2pixHD

1. 摘要 图像处理的很多问题都是将一张输入的图片转变为一张对应的输出图片,比如灰度图、梯度图、彩色图之间的转换等。通常每一种问题都使用特定的算法(如:使用CNN来解决图像转换问题时,要根据每个问题设定一个特定的loss funct…

Pix2Pix原理解析

1.网络搭建 class UnetGenerator(nn.Module):"""Create a Unet-based generator"""def __init__(self, input_nc, output_nc, num_downs, ngf64, norm_layernn.BatchNorm2d, use_dropoutFalse):"""Construct a Unet generatorPa…

如何利用Pix2Pix将黑白图片自动变成彩色图片

实现黑白图片自动变成彩色图片 如果你有一幅黑白图片,你该如何上色让他变成彩色的呢?通常做法可能是使用PS工具来进行上色。那么,有没有什么办法进行自动上色呢?自动将黑白图片变成彩色图片?答案是有的,使用深度学习中的Pix2Pix网络就可以实现这一功能。 如图所示,我们…

Pix2Pix进一步了解

参考:Pix2Pix视频解读 一、Pix2Pix是输入图片矩阵而不是标签向量 1、生成器方面 Pix2Pix与CGAN之间的联系:CGAN生成器输入的是一个label,而我们现在要做的是把这个lable换成一个图片,如下所示。这个图片是一个建筑物的模…

CycleGAN与pix2pix训练自己的数据集-Pytorch

github:https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix 参考:https://blog.csdn.net/Gavinmiaoc/article/details/80585531 文章目录 CycleganDownload&Prerequisitesbefore your work数据集训练测试 pix2pix数据集训练测试 Cyclegan Do…

pix2pix学习系列(1):预训练模型测试pix2pix

pix2pix学习系列(1):预训练模型测试pix2pix 参考文献: [Pytorch系列-66]:生成对抗网络GAN - 图像生成开源项目pytorch-CycleGAN-and-pix2pix - 使用预训练模型测试pix2pix模型 运行环境 win 10 1、代码下载 Gith…

pix2pix简要笔记

参考(40条消息) 全文翻译&杂记《Image-to-Image Translation with Conditional Adversarial NetWorks》_Maples丶丶的博客-CSDN博客_image-to-image translation 图像到图像通常有特定方法(没有通用),但本质是像素到像素的映射问题。本文…

简单理解Pix2Pix

论文名:Image-to-Image Translation with Conditional Adversarial Networks 论文地址:https://arxiv.org/abs/1611.07004 代码链接:https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix Pix2Pix是做什么的 图像风格迁移,一…

Pix2pix网络的基本实现

Pix2pix Gan 主要用于图像之间的转换,又称图像翻译《Image-to-Image Translation with Conditional Adversarial Networks》 普通的GAN接受的G部分的输入是随机向量,输出的是图像。D部分接受的输入是图像(生成的或是真实的)&…

Pix2Pix(2017)+CycleGAN+Pix2PixHD

GAN 常规的深度学习任务如图像分类、目标检测以及语义分割或者实例分割,这些任务的结果都可以归结为预测。图像分类是预测单一的类别,目标检测是预测Bbox和类别,语义分割或者实例分割是预测每个像素的类别。而GAN是生成一个新的东西如一张图…