100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 深度学习-DRGAN对抗神经网络生成动漫头像

深度学习-DRGAN对抗神经网络生成动漫头像

时间:2018-09-26 19:12:13

相关推荐

深度学习-DRGAN对抗神经网络生成动漫头像

动漫头像素材,项目中新建data文件夹放进去

具体思路是,生成器是将一个噪点生成一副假图片,然后将假图片传给判别器进行判断,如果判别器判断为真,则代码生成器性能很好,而判别器是从真实图片中学习模型,对生成的假图片进行判断,如果判断出来为假则代码判别器性能很好。

关于代码的具体注释已经写上,需要单独开博客讲的内容在前几篇博客里写了,直接上代码吧:

train.py主运行页面:

import argparseimport torchimport torchvisionimport torchvision.utils as vutilsimport torch.nn as nnfrom model import NetD, NetG# 定义是否使用GPUdevice = torch.device("cuda" if torch.cuda.is_available() else "cpu") #判断是否能用GPU# 图像读入与预处理transforms = pose([torchvision.transforms.Resize(96), #处理图像尺寸,短边变为96,长边对应比例缩放torchvision.transforms.ToTensor(), #数据集加载时,默认的图片格式是 numpy,所以通过 transforms 转换成 Tensor,图像范围[0, 255] -> [0.0,1.0]torchvision.transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), ]) #使用公式进行归一化channel=(channel-mean)/std,因为transforms.ToTensor()已经把数据处理成[0,1],那么(x-0.5)/0.5就是[-1.0, 1.0]dataset = torchvision.datasets.ImageFolder('data/', transform=transforms)dataloader = torch.utils.data.DataLoader(dataset=dataset,batch_size=64, #因为需要生成包含64张小图的大图片,所以把64定位一个批度shuffle=True,drop_last=True, #如何处理数据集长度除于batch_size余下的数据。True就抛弃,否则保留)netG = NetG(64, 100).to(device) #操作过程中通道数都是64的倍数,最后由64一下子变为3,100是噪声维度,噪声用来生成假图片netD = NetD(64).to(device) #操作过程中通道数都是64的倍数,最后由64一下子变为1criterion = nn.BCELoss() #用于二分类optimizerG = torch.optim.Adam(netG.parameters(), lr=0.0002, betas=(0.5, 0.999)) #生成器的优化器optimizerD = torch.optim.Adam(netD.parameters(), lr=0.0002, betas=(0.5, 0.999)) #判别器的优化器label = torch.FloatTensor(64) #创建一个元素个数为64的tensor标签,随机赋值real_label = 1 #真图片标签为1fake_label = 0 #假图片标签为0for epoch in range(1, 25 + 1):for i, (imgs, _) in enumerate(dataloader):# 固定生成器G,训练鉴别器D(判别器的好坏要通过是否能判断出假图片来体现)optimizerD.zero_grad() #判别器优化器梯度全部降为0## 让D尽可能的把真图片判别为1imgs = imgs.to(device) #将图片数据copy一份到device指定的GPU上去output = netD(imgs) #判别器输出label.data.fill_(real_label) #标签全部改为1,一开始判断真实图片label = label.to(device) #将labelcopy放入GPUoutput=output.squeeze() #output.shape为(64,1,1,1)维度,label为(64),这一句是将output中所有维度为一的去掉,不加这一句运行不会出错,但是会有警告errD_real = criterion(output, label) #计算判断真实图片的损失值errD_real.backward() #反向传播## 让D尽可能把假图片判别为0label.data.fill_(fake_label) #标签全部改为0,一开始假图片noise = torch.randn(64, 100, 1, 1) #随机生成64个噪点,每个噪点维度为(100,1,1)noise = noise.to(device) #将噪点放入GPUfake = netG(noise) # 生成假图output = netD(fake.detach()) # 使用判别器对一个批次假图片进行分类output=output.squeeze()errD_fake = criterion(output, label) #计算判断假图片为假的损失值errD_fake.backward() #反向传播errD = errD_fake + errD_real #判断真图片和判断假图片的损失值加和作为总损失optimizerD.step() #对判别器进行优化# 固定鉴别器D,训练生成器G(生成器性能的好坏要通过判别器是否判断为真来体现)optimizerG.zero_grad() #生成器梯度全部降为0# 让D尽可能把G生成的假图判别为1label.data.fill_(real_label) #标签全部改为1,一开始判断真实图片label = label.to(device)output = netD(fake) #判别刚才生成的假图片output=output.squeeze()errG = criterion(output, label) #计算判断假图片为真的损失值errG.backward() #反向传播optimizerG.step() #对生成器进行优化print('[%d/%d][%d/%d] Loss_D: %.3f Loss_G %.3f'% (epoch, 25, i, len(dataloader), errD.item(), errG.item()))vutils.save_image(fake.data,'%s/fake_samples_epoch_%03d.png' % ('imgs/', epoch), #保存图像normalize=True)

model.py模型结构页面:

import torch.nn as nn# 定义生成器网络G,从噪声中生成一张彩色图片class NetG(nn.Module): #注意这里图片都是四维,第一维都是批度64,为了方便将第一个省去def __init__(self, ngf, nz): #操作过程中通道数都是ngf的倍数,最后由ngf一下子变为3,nz是噪点维度,噪声用来生成假图片super(NetG, self).__init__()# layer1输入的是一个100x1x1的随机噪声, 输出尺寸(ngf*8)x4x4self.layer1 = nn.Sequential( #(100,1,1)-->(64*8,4,4)nn.ConvTranspose2d(nz, ngf * 8, kernel_size=4, stride=1, padding=0, bias=False), #o=(i-1)*s-2*p+knn.BatchNorm2d(ngf * 8), #参数为输出通道数nn.ReLU(inplace=True) #implace=True是原地操作,直接替换掉以前的变量,比如x=x+5)# layer2输出尺寸(ngf*4)x8x8self.layer2 = nn.Sequential( #(64*8,4,4)-->(64*4,8,8)nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False),nn.BatchNorm2d(ngf * 4),nn.ReLU(inplace=True))# layer3输出尺寸(ngf*2)x16x16self.layer3 = nn.Sequential( #(64*4,8,8)-->(64*2,16,16)nn.ConvTranspose2d(ngf * 4, ngf * 2, 4, 2, 1, bias=False),nn.BatchNorm2d(ngf * 2),nn.ReLU(inplace=True))# layer4输出尺寸(ngf)x32x32self.layer4 = nn.Sequential( #(64*2,16,16)-->(64,32,32)nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 1, bias=False),nn.BatchNorm2d(ngf),nn.ReLU(inplace=True))# layer5输出尺寸 3x96x96self.layer5 = nn.Sequential( #(64,32,32)-->(3,96,96)nn.ConvTranspose2d(ngf, 3, 5, 3, 1, bias=False),nn.Tanh())# 定义NetG的前向传播def forward(self, x):out = self.layer1(x)out = self.layer2(out)out = self.layer3(out)out = self.layer4(out)out = self.layer5(out)return out# 定义鉴别器网络Dclass NetD(nn.Module):def __init__(self, ndf): #操作过程中图片的通道数一直是ndf的倍数super(NetD, self).__init__()# layer1 输入 3 x 96 x 96, 输出 (ndf) x 32 x 32self.layer1 = nn.Sequential( #(3,96,96)-->(64,32,32)nn.Conv2d(3, ndf, kernel_size=5, stride=3, padding=1, bias=False),nn.BatchNorm2d(ndf),nn.LeakyReLU(0.2, inplace=True) #relu中f=maxy(0,x),而leakyrelu中f=x>0?x:ax(a=栏目大))# layer2 输出 (ndf*2) x 16 x 16self.layer2 = nn.Sequential( #(64,32,32)-->(128,16,16)nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False),nn.BatchNorm2d(ndf * 2),nn.LeakyReLU(0.2, inplace=True))# layer3 输出 (ndf*4) x 8 x 8self.layer3 = nn.Sequential( #(128,16,16)-->(256,8,8)nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False),nn.BatchNorm2d(ndf * 4),nn.LeakyReLU(0.2, inplace=True))# layer4 输出 (ndf*8) x 4 x 4self.layer4 = nn.Sequential( #(256,8,8)-->(512,4,4)nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, bias=False),nn.BatchNorm2d(ndf * 8),nn.LeakyReLU(0.2, inplace=True))# layer5 输出一个数(概率)self.layer5 = nn.Sequential( #(512,4,4)-->(1,1,1)nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False),nn.Sigmoid())# 定义NetD的前向传播def forward(self,x):out = self.layer1(x)out = self.layer2(out)out = self.layer3(out)out = self.layer4(out)out = self.layer5(out)return out

生成的假图片:

epoch=1:

epoch=10:

epoch=20:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。