作者的代码包括两部分:models包下包含dcgan.py和mlp.py, 这两个py文件是两种不同的网络结构,在dcgan.py中判别器和生成器都含有卷积网络,而mlp.py中判别器和生成器都只是全连接。  此外main.py为主函数,通过引入import models中的生成器和判别器来完成训练与迭代。

参数说明(main.py中):

parser =argparse.ArgumentParser()

parser.add_argument('--dataset', required=True, help='cifar10 | lsun | imagenet | folder | lfw')

parser.add_argument('--dataroot', required=True, help='path to dataset')

parser.add_argument('--workers', type=int, help='number of data loading workers', default=2)

parser.add_argument('--batchSize', type=int, default=64, help='input batch size')

parser.add_argument('--imageSize', type=int, default=64, help='the height / width of the input image to network')

parser.add_argument('--nc', type=int, default=3, help='input image channels')

parser.add_argument('--nz', type=int, default=100, help='size of the latent z vector')

parser.add_argument('--ngf', type=int, default=64)

parser.add_argument('--ndf', type=int, default=64)

parser.add_argument('--niter', type=int, default=25, help='number of epochs to train for')

parser.add_argument('--lrD', type=float, default=0.00005, help='learning rate for Critic, default=0.00005')

parser.add_argument('--lrG', type=float, default=0.00005, help='learning rate for Generator, default=0.00005')

parser.add_argument('--beta1', type=float, default=0.5, help='beta1 for adam. default=0.5')

parser.add_argument('--cuda' , action='store_true', help='enables cuda')

parser.add_argument('--ngpu' , type=int, default=1, help='number of GPUs to use')

parser.add_argument('--netG', default='', help="path to netG (to continue training)")

parser.add_argument('--netD', default='', help="path to netD (to continue training)")

parser.add_argument('--clamp_lower', type=float, default=-0.01)

parser.add_argument('--clamp_upper', type=float, default=0.01)

parser.add_argument('--Diters', type=int, default=5, help='number of D iters per each G iter')

parser.add_argument('--noBN', action='store_true', help='use batchnorm or not (only for DCGAN)')

parser.add_argument('--mlp_G', action='store_true', help='use MLP for G')

parser.add_argument('--mlp_D', action='store_true', help='use MLP for D')

parser.add_argument('--n_extra_layers', type=int, default=0, help='Number of extra layers on gen and disc')

parser.add_argument('--experiment', default=None, help='Where to store samples and models')

parser.add_argument('--adam', action='store_true', help='Whether to use adam (default is rmsprop)')

1.models包中的mlp.py:

from __future__ importabsolute_importfrom __future__ importdivisionfrom __future__ importprint_functionfrom __future__ importunicode_literalsimporttorchimporttorch.nn as nnclassMLP_G(nn.Module):def __init__(self, isize, nz, nc, ngf, ngpu):

super(MLP_G, self).__init__()

self.ngpu=ngpu

main=nn.Sequential(#Z goes into a linear of size: ngf

nn.Linear(nz, ngf),

nn.ReLU(True),

nn.Linear(ngf, ngf),

nn.ReLU(True),

nn.Linear(ngf, ngf),

nn.ReLU(True),

nn.Linear(ngf, nc* isize *isize),

)

self.main=main

self.nc=nc

self.isize=isize

self.nz=nzdefforward(self, input):

input= input.view(input.size(0), input.size(1))if isinstance(input.data, torch.cuda.FloatTensor) and self.ngpu > 1:

output=nn.parallel.data_parallel(self.main, input, range(self.ngpu))else:

output=self.main(input)returnoutput.view(output.size(0), self.nc, self.isize, self.isize)classMLP_D(nn.Module):def __init__(self, isize, nz, nc, ndf, ngpu):

super(MLP_D, self).__init__()

self.ngpu=ngpu

main=nn.Sequential(#Z goes into a linear of size: ndf

nn.Linear(nc * isize *isize, ndf),

nn.ReLU(True),

nn.Linear(ndf, ndf),

nn.ReLU(True),

nn.Linear(ndf, ndf),

nn.ReLU(True),

nn.Linear(ndf,1),

)

self.main=main

self.nc=nc

self.isize=isize

self.nz=nzdefforward(self, input):

input=input.view(input.size(0),

input.size(1) * input.size(2) * input.size(3))if isinstance(input.data, torch.cuda.FloatTensor) and self.ngpu > 1:

output=nn.parallel.data_parallel(self.main, input, range(self.ngpu))else:

output=self.main(input)

output=output.mean(0)return output.view(1)

mlp.py

在利用全连接实现的网络中,生成器的结构为四层全连接,伴有4个ReLU激活函数。噪声即生成器的输入,其维度为 nz=100维。所以生成器的输入维度为(batch_size, nz), 输出为图像的尺寸(batch_size, nc, isize, isize)。注意的是torch.nn只支持mini_batch,若想输入单个样本,可利用input.unsqueeze(0)将batch_size设为1。WGAN的判别器与GAN不同之处是最后一层取消了sigmoid,其结构也为4层全连接。判别器的输入为图像的尺寸,同时判别器的输入为生成器的输出,而输出为1维,即batch_size大小的向量,求mean得到一个数。

此外代码中还对 ngpu>1 的情形下使用Multi-GPU layers:mini-batch划分到不同的设备上来实现给定module的并行。在forward过程中,module会在每个设备上都复制一遍,每个副本都会处理部分输入。在backward过程中,副本上的梯度会累加到原始module上。

batch的大小应该大于所使用的GPU的数量。还应当是GPU个数的整数倍,这样划分出来的每一块都会有相同的样本数量。

2.models包中的dcgan.py

importtorchimporttorch.nn as nnimporttorch.nn.parallelclassDCGAN_D(nn.Module):def __init__(self, isize, nz, nc, ndf, ngpu, n_extra_layers=0):

super(DCGAN_D, self).__init__()

self.ngpu=ngpuassert isize % 16 == 0, "isize has to be a multiple of 16"main=nn.Sequential()#input is nc x isize x isize

main.add_module('initial.conv.{0}-{1}'.format(nc, ndf),

nn.Conv2d(nc, ndf,4, 2, 1, bias=False))

main.add_module('initial.relu.{0}'.format(ndf),

nn.LeakyReLU(0.2, inplace=True))

csize, cndf= isize / 2, ndf#Extra layers

for t inrange(n_extra_layers):

main.add_module('extra-layers-{0}.{1}.conv'.format(t, cndf),

nn.Conv2d(cndf, cndf,3, 1, 1, bias=False))

main.add_module('extra-layers-{0}.{1}.batchnorm'.format(t, cndf),

nn.BatchNorm2d(cndf))

main.add_module('extra-layers-{0}.{1}.relu'.format(t, cndf),

nn.LeakyReLU(0.2, inplace=True))while csize > 4:

in_feat=cndf

out_feat= cndf * 2main.add_module('pyramid.{0}-{1}.conv'.format(in_feat, out_feat),

nn.Conv2d(in_feat, out_feat,4, 2, 1, bias=False))

main.add_module('pyramid.{0}.batchnorm'.format(out_feat),

nn.BatchNorm2d(out_feat))

main.add_module('pyramid.{0}.relu'.format(out_feat),

nn.LeakyReLU(0.2, inplace=True))

cndf= cndf * 2csize= csize / 2

#state size. K x 4 x 4

main.add_module('final.{0}-{1}.conv'.format(cndf, 1),

nn.Conv2d(cndf,1, 4, 1, 0, bias=False))

self.main=maindefforward(self, input):if isinstance(input.data, torch.cuda.FloatTensor) and self.ngpu > 1:

output=nn.parallel.data_parallel(self.main, input, range(self.ngpu))else:

output=self.main(input)

output=output.mean(0)return output.view(1)classDCGAN_G(nn.Module):def __init__(self, isize, nz, nc, ngf, ngpu, n_extra_layers=0):

super(DCGAN_G, self).__init__()

self.ngpu=ngpuassert isize % 16 == 0, "isize has to be a multiple of 16"cngf, tisize= ngf//2, 4

while tisize !=isize:

cngf= cngf * 2tisize= tisize * 2main=nn.Sequential()#input is Z, going into a convolution

main.add_module('initial.{0}-{1}.convt'.format(nz, cngf),

nn.ConvTranspose2d(nz, cngf,4, 1, 0, bias=False))

main.add_module('initial.{0}.batchnorm'.format(cngf),

nn.BatchNorm2d(cngf))

main.add_module('initial.{0}.relu'.format(cngf),

nn.ReLU(True))

csize, cndf= 4, cngfwhile csize < isize//2:

main.add_module('pyramid.{0}-{1}.convt'.format(cngf, cngf//2),

nn.ConvTranspose2d(cngf, cngf//2, 4, 2, 1, bias=False))

main.add_module('pyramid.{0}.batchnorm'.format(cngf//2),

nn.BatchNorm2d(cngf//2))

main.add_module('pyramid.{0}.relu'.format(cngf//2),

nn.ReLU(True))

cngf= cngf // 2csize= csize * 2

#Extra layers

for t inrange(n_extra_layers):

main.add_module('extra-layers-{0}.{1}.conv'.format(t, cngf),

nn.Conv2d(cngf, cngf,3, 1, 1, bias=False))

main.add_module('extra-layers-{0}.{1}.batchnorm'.format(t, cngf),

nn.BatchNorm2d(cngf))

main.add_module('extra-layers-{0}.{1}.relu'.format(t, cngf),

nn.ReLU(True))

main.add_module('final.{0}-{1}.convt'.format(cngf, nc),

nn.ConvTranspose2d(cngf, nc,4, 2, 1, bias=False))

main.add_module('final.{0}.tanh'.format(nc),

nn.Tanh())

self.main=maindefforward(self, input):if isinstance(input.data, torch.cuda.FloatTensor) and self.ngpu > 1:

output=nn.parallel.data_parallel(self.main, input, range(self.ngpu))else:

output=self.main(input)returnoutput###############################################################################

classDCGAN_D_nobn(nn.Module):def __init__(self, isize, nz, nc, ndf, ngpu, n_extra_layers=0):

super(DCGAN_D_nobn, self).__init__()

self.ngpu=ngpuassert isize % 16 == 0, "isize has to be a multiple of 16"main=nn.Sequential()#input is nc x isize x isize

#input is nc x isize x isize

main.add_module('initial.conv.{0}-{1}'.format(nc, ndf),

nn.Conv2d(nc, ndf,4, 2, 1, bias=False))

main.add_module('initial.relu.{0}'.format(ndf),

nn.LeakyReLU(0.2, inplace=True))

csize, cndf= isize / 2, ndf#Extra layers

for t inrange(n_extra_layers):

main.add_module('extra-layers-{0}.{1}.conv'.format(t, cndf),

nn.Conv2d(cndf, cndf,3, 1, 1, bias=False))

main.add_module('extra-layers-{0}.{1}.relu'.format(t, cndf),

nn.LeakyReLU(0.2, inplace=True))while csize > 4:

in_feat=cndf

out_feat= cndf * 2main.add_module('pyramid.{0}-{1}.conv'.format(in_feat, out_feat),

nn.Conv2d(in_feat, out_feat,4, 2, 1, bias=False))

main.add_module('pyramid.{0}.relu'.format(out_feat),

nn.LeakyReLU(0.2, inplace=True))

cndf= cndf * 2csize= csize / 2

#state size. K x 4 x 4

main.add_module('final.{0}-{1}.conv'.format(cndf, 1),

nn.Conv2d(cndf,1, 4, 1, 0, bias=False))

self.main=maindefforward(self, input):if isinstance(input.data, torch.cuda.FloatTensor) and self.ngpu > 1:

output=nn.parallel.data_parallel(self.main, input, range(self.ngpu))else:

output=self.main(input)

output=output.mean(0)return output.view(1)classDCGAN_G_nobn(nn.Module):def __init__(self, isize, nz, nc, ngf, ngpu, n_extra_layers=0):

super(DCGAN_G_nobn, self).__init__()

self.ngpu=ngpuassert isize % 16 == 0, "isize has to be a multiple of 16"cngf, tisize= ngf//2, 4

while tisize !=isize:

cngf= cngf * 2tisize= tisize * 2main=nn.Sequential()

main.add_module('initial.{0}-{1}.convt'.format(nz, cngf),

nn.ConvTranspose2d(nz, cngf,4, 1, 0, bias=False))

main.add_module('initial.{0}.relu'.format(cngf),

nn.ReLU(True))

csize, cndf= 4, cngfwhile csize < isize//2:

main.add_module('pyramid.{0}-{1}.convt'.format(cngf, cngf//2),

nn.ConvTranspose2d(cngf, cngf//2, 4, 2, 1, bias=False))

main.add_module('pyramid.{0}.relu'.format(cngf//2),

nn.ReLU(True))

cngf= cngf // 2csize= csize * 2

#Extra layers

for t inrange(n_extra_layers):

main.add_module('extra-layers-{0}.{1}.conv'.format(t, cngf),

nn.Conv2d(cngf, cngf,3, 1, 1, bias=False))

main.add_module('extra-layers-{0}.{1}.relu'.format(t, cngf),

nn.ReLU(True))

main.add_module('final.{0}-{1}.convt'.format(cngf, nc),

nn.ConvTranspose2d(cngf, nc,4, 2, 1, bias=False))

main.add_module('final.{0}.tanh'.format(nc),

nn.Tanh())

self.main=maindefforward(self, input):if isinstance(input.data, torch.cuda.FloatTensor) and self.ngpu > 1:

output=nn.parallel.data_parallel(self.main, input, range(self.ngpu))else:

output=self.main(input)return output

dcgan.py

此文件中共4个类,分为两组。第一组是DCGAN_D和DCGAN_G, 这两个类都使用了Batch normalization。而另一组是DCGAN_D_nobn和DCGAN_G_nobn, 这两个类都没有使用Batch normalization。首先看判别器,设定了image的尺寸为16的倍数,然后经过一个卷积层和一个LeakyReLU后来到Extra layers, 在这个其他层中当参数 n_extra_layers 为n时, 将Conv-BN-LeakyReLU重复n次,此时判断如果特征图大小 >4, 则再次进行Conv-BN-LeakyReLU操作直到特征图大小 =4,然后进行最后一次卷积核大小为4的卷积,此时输出为1维向量,求均值后得到一个数。

然后看生成器,生成器用到了反卷积,因为其输入为100维噪声数据(类似向量),输出为图像(类似矩阵)。首先经过ConvTranspose2d-BN-ReLU, 将100维的噪声反卷积为512维。然后经过一系列(3次)ConvTranspose2d-BN-ReLU将特征图维度改为了64通道。此时又来到了Extra layers, 在这个其他层中当参数 n_extra_layers 为n时,  将ConvTranspose2d-BN-ReLU重复n次,注意此时n次反卷积设置为通道数不变的反卷积,所以若经过这n次操作,通道数仍为64维。最后经过ConvTranspose2d-Tanh后,将通道数将为了3,数值大小都在-1至1之间。

对于两组文件不同之处只有BN的使用与否,所以不必赘述。

3.main.py

from __future__ importprint_functionimportargparseimportrandomimporttorchimporttorch.nn as nnimporttorch.nn.parallelimporttorch.backends.cudnn as cudnnimporttorch.optim as optimimporttorch.utils.dataimporttorchvision.datasets as dsetimporttorchvision.transforms as transformsimporttorchvision.utils as vutilsfrom torch.autograd importVariableimportosimportmodels.dcgan as dcganimportmodels.mlp as mlp

parser=argparse.ArgumentParser()

parser.add_argument('--dataset', required=True, help='cifar10 | lsun | imagenet | folder | lfw')

parser.add_argument('--dataroot', required=True, help='path to dataset')

parser.add_argument('--workers', type=int, help='number of data loading workers', default=2)

parser.add_argument('--batchSize', type=int, default=64, help='input batch size')

parser.add_argument('--imageSize', type=int, default=64, help='the height / width of the input image to network')

parser.add_argument('--nc', type=int, default=3, help='input image channels')

parser.add_argument('--nz', type=int, default=100, help='size of the latent z vector')

parser.add_argument('--ngf', type=int, default=64)

parser.add_argument('--ndf', type=int, default=64)

parser.add_argument('--niter', type=int, default=25, help='number of epochs to train for')

parser.add_argument('--lrD', type=float, default=0.00005, help='learning rate for Critic, default=0.00005')

parser.add_argument('--lrG', type=float, default=0.00005, help='learning rate for Generator, default=0.00005')

parser.add_argument('--beta1', type=float, default=0.5, help='beta1 for adam. default=0.5')

parser.add_argument('--cuda' , action='store_true', help='enables cuda')

parser.add_argument('--ngpu' , type=int, default=1, help='number of GPUs to use')

parser.add_argument('--netG', default='', help="path to netG (to continue training)")

parser.add_argument('--netD', default='', help="path to netD (to continue training)")

parser.add_argument('--clamp_lower', type=float, default=-0.01)

parser.add_argument('--clamp_upper', type=float, default=0.01)

parser.add_argument('--Diters', type=int, default=5, help='number of D iters per each G iter')

parser.add_argument('--noBN', action='store_true', help='use batchnorm or not (only for DCGAN)')

parser.add_argument('--mlp_G', action='store_true', help='use MLP for G')

parser.add_argument('--mlp_D', action='store_true', help='use MLP for D')

parser.add_argument('--n_extra_layers', type=int, default=0, help='Number of extra layers on gen and disc')

parser.add_argument('--experiment', default=None, help='Where to store samples and models')

parser.add_argument('--adam', action='store_true', help='Whether to use adam (default is rmsprop)')

opt=parser.parse_args()print(opt)if opt.experiment isNone:

opt.experiment= 'samples'os.system('mkdir {0}'.format(opt.experiment))

opt.manualSeed= random.randint(1, 10000) #fix seed

print("Random Seed:", opt.manualSeed)

random.seed(opt.manualSeed)

torch.manual_seed(opt.manualSeed)

cudnn.benchmark=Trueif torch.cuda.is_available() and notopt.cuda:print("WARNING: You have a CUDA device, so you should probably run with --cuda")if opt.dataset in ['imagenet', 'folder', 'lfw']:#folder dataset

dataset = dset.ImageFolder(root=opt.dataroot,

transform=transforms.Compose([

transforms.Scale(opt.imageSize),

transforms.CenterCrop(opt.imageSize),

transforms.ToTensor(),

transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),

]))elif opt.dataset == 'lsun':

dataset= dset.LSUN(db_path=opt.dataroot, classes=['bedroom_train'],

transform=transforms.Compose([

transforms.Scale(opt.imageSize),

transforms.CenterCrop(opt.imageSize),

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.dataroot, download=True,

transform=transforms.Compose([

transforms.Scale(opt.imageSize),

transforms.ToTensor(),

transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),

])

)assertdataset

dataloader= torch.utils.data.DataLoader(dataset, batch_size=opt.batchSize,

shuffle=True, num_workers=int(opt.workers))

ngpu=int(opt.ngpu)

nz=int(opt.nz)

ngf=int(opt.ngf)

ndf=int(opt.ndf)

nc=int(opt.nc)

n_extra_layers=int(opt.n_extra_layers)#custom weights initialization called on netG and netD

defweights_init(m):

classname= m.__class__.__name__

if classname.find('Conv') != -1:

m.weight.data.normal_(0.0, 0.02)elif classname.find('BatchNorm') != -1:

m.weight.data.normal_(1.0, 0.02)

m.bias.data.fill_(0)ifopt.noBN:

netG=dcgan.DCGAN_G_nobn(opt.imageSize, nz, nc, ngf, ngpu, n_extra_layers)elifopt.mlp_G:

netG=mlp.MLP_G(opt.imageSize, nz, nc, ngf, ngpu)else:

netG=dcgan.DCGAN_G(opt.imageSize, nz, nc, ngf, ngpu, n_extra_layers)

netG.apply(weights_init)if opt.netG != '': #load checkpoint if needed

netG.load_state_dict(torch.load(opt.netG))print(netG)ifopt.mlp_D:

netD=mlp.MLP_D(opt.imageSize, nz, nc, ndf, ngpu)else:

netD=dcgan.DCGAN_D(opt.imageSize, nz, nc, ndf, ngpu, n_extra_layers)

netD.apply(weights_init)if opt.netD != '':

netD.load_state_dict(torch.load(opt.netD))print(netD)

input= torch.FloatTensor(opt.batchSize, 3, opt.imageSize, opt.imageSize)

noise= torch.FloatTensor(opt.batchSize, nz, 1, 1)

fixed_noise= torch.FloatTensor(opt.batchSize, nz, 1, 1).normal_(0, 1)

one= torch.FloatTensor([1])

mone= one * -1

ifopt.cuda:

netD.cuda()

netG.cuda()

input=input.cuda()

one, mone=one.cuda(), mone.cuda()

noise, fixed_noise=noise.cuda(), fixed_noise.cuda()#setup optimizer

ifopt.adam:

optimizerD= optim.Adam(netD.parameters(), lr=opt.lrD, betas=(opt.beta1, 0.999))

optimizerG= optim.Adam(netG.parameters(), lr=opt.lrG, betas=(opt.beta1, 0.999))else:

optimizerD= optim.RMSprop(netD.parameters(), lr =opt.lrD)

optimizerG= optim.RMSprop(netG.parameters(), lr =opt.lrG)

gen_iterations=0for epoch inrange(opt.niter):

data_iter=iter(dataloader)

i=0while i

#(1) Update D network

###########################

for p in netD.parameters(): #reset requires_grad

p.requires_grad = True #they are set to False below in netG update

#train the discriminator Diters times

if gen_iterations < 25 or gen_iterations % 500 ==0:

Diters= 100

else:

Diters=opt.Diters

j=0while j < Diters and i

j+= 1

#clamp parameters to a cube

for p innetD.parameters():

p.data.clamp_(opt.clamp_lower, opt.clamp_upper)

data=data_iter.next()

i+= 1

#train with real

real_cpu, _ =data

netD.zero_grad()

batch_size=real_cpu.size(0)ifopt.cuda:

real_cpu=real_cpu.cuda()

input.resize_as_(real_cpu).copy_(real_cpu)

inputv=Variable(input)

errD_real=netD(inputv)

errD_real.backward(one)#train with fake

noise.resize_(opt.batchSize, nz, 1, 1).normal_(0, 1)

noisev= Variable(noise, volatile = True) #totally freeze netG

fake =Variable(netG(noisev).data)

inputv=fake

errD_fake=netD(inputv)

errD_fake.backward(mone)

errD= errD_real -errD_fake

optimizerD.step()############################

#(2) Update G network

###########################

for p innetD.parameters():

p.requires_grad= False #to avoid computation

netG.zero_grad()#in case our last batch was the tail batch of the dataloader,

#make sure we feed a full batch of noise

noise.resize_(opt.batchSize, nz, 1, 1).normal_(0, 1)

noisev=Variable(noise)

fake=netG(noisev)

errG=netD(fake)

errG.backward(one)

optimizerG.step()

gen_iterations+= 1

print('[%d/%d][%d/%d][%d] Loss_D: %f Loss_G: %f Loss_D_real: %f Loss_D_fake %f'

%(epoch, opt.niter, i, len(dataloader), gen_iterations,

errD.data[0], errG.data[0], errD_real.data[0], errD_fake.data[0]))if gen_iterations % 500 ==0:

real_cpu= real_cpu.mul(0.5).add(0.5)

vutils.save_image(real_cpu,'{0}/real_samples.png'.format(opt.experiment))

fake= netG(Variable(fixed_noise, volatile=True))

fake.data= fake.data.mul(0.5).add(0.5)

vutils.save_image(fake.data,'{0}/fake_samples_{1}.png'.format(opt.experiment, gen_iterations))#do checkpointing

torch.save(netG.state_dict(), '{0}/netG_epoch_{1}.pth'.format(opt.experiment, epoch))

torch.save(netD.state_dict(),'{0}/netD_epoch_{1}.pth'.format(opt.experiment, epoch))

main.py

首先利用parser = argparse.ArgumentParser()命令行解析工具设置了一堆参数,如文章最开始处。

然后利用net.apply(weighs_init)递归进行权重初始化:

defweights_init(m):

classname= m.__class__.__name__

if classname.find('Conv') != -1:

m.weight.data.normal_(0.0, 0.02)elif classname.find('BatchNorm') != -1:

m.weight.data.normal_(1.0, 0.02)

m.bias.data.fill_(0)

接着选择dcgan结构或者mlp结构,尽量不要在 D 中使用 batch normalization,即不选DCGAN_D_nobn。可选的优化器为Adam和RMSprop。在WGAN中尽量使用RMSProp 或 SGD 。

迭代训练的epoch为25,注意参数 Diters默认为5,是指每迭代generator 1 次,迭代descriminator 5 次。为什么迭代判别器多于生成器呢?因为如果判别器太弱,那么生成器的质量就会受到影响导致生成的图片质量太低。在代码中我们看可以看到:

if gen_iterations < 25 or gen_iterations % 500 ==0:

Diters= 100

else:

Diters= opt.Diters

gen_iterations(生成器迭代次数)在epoch循环外被初始化为0,也即是说当在第一个epoch中,将判别器迭代100次,将生成器迭代1次。然后当gen_iteration>=25时,即生成器迭代了25次以上时,生成器每迭代一次,判别器迭代默认的5次。此外还有一些细节例如:

one = torch.FloatTensor([1])

mone= one * -1...

errD_real.backward(one)

...

errD_fake.backward(mone)

...

errG.backward(one)

为啥反向传播参数有的为1,有的为-1?先看WGAN的损失函数:

即对于判别器:maxmize LD

对于生成器:maxmize LG

最大化判LD可以看做最大化E(D(x)), 最小化E(D(G(z)))。所以第一项求梯度后系数为1,即梯度上升求最大值,而第二项最小化得利用梯度下降法,所以反向传播时得加个负号变为负梯度。

最大化LG可以看做最大化E(D(G(z)))。即利用梯度上升法,所以反向传播时系数为1,即梯度方向就是最速上升方向。

wgan 不理解 损失函数_WGAN源码解读相关推荐

  1. wgan 不理解 损失函数_WGAN

    GAN-QP 写到一半发现关于 WGAN 以及它相关约束部分之前没有完全读懂,需要重读,那顺手也把笔记给谢了吧 WGAN 在之前阅读的背景是 GAN 在许多条件下有比较严重的不稳定性,在寻找解决方案的 ...

  2. wgan 不理解 损失函数_WGAN学习笔记

    GAN自从被提出之后就受到了广泛的关注,GAN也被逐渐用于各种有趣的应用之中.虽然GAN的idea对研究者们有着巨大的吸引力,但是GAN的训练却不像普通DNN那样简单,generator和discri ...

  3. Pseudo-document-based Topic Model(基于伪文档的主题模型)的理解以及源码解读

    本文作者:合肥工业大学 管理学院 钱洋 email:1563178220@qq.com 内容可能有不到之处,欢迎交流. 未经本人允许禁止转载. 论文来源 Zuo Y, Wu J, Zhang H, e ...

  4. 【 非线性回归 Logistics-Regression 模块实现与源码解读 深度学习 Pytorch笔记 B站刘二大人(5/10)】

    非线性回归 Logistics-Regression 模块实现与源码解读 深度学习 Pytorch笔记 B站刘二大人(5/10) 数学推导 什么是logistics函数 在定义上Logistic函数或 ...

  5. Bert系列(二)——源码解读之模型主体

    本篇文章主要是解读模型主体代码modeling.py.在阅读这篇文章之前希望读者们对bert的相关理论有一定的了解,尤其是transformer的结构原理,网上的资料很多,本文内容对原理部分就不做过多 ...

  6. Bert系列(三)——源码解读之Pre-train

    https://www.jianshu.com/p/22e462f01d8c pre-train是迁移学习的基础,虽然Google已经发布了各种预训练好的模型,而且因为资源消耗巨大,自己再预训练也不现 ...

  7. Alamofire源码解读系列(九)之响应封装(Response)

    本篇主要带来Alamofire中Response的解读 前言 在每篇文章的前言部分,我都会把我认为的本篇最重要的内容提前讲一下.我更想同大家分享这些顶级框架在设计和编码层次究竟有哪些过人的地方?当然, ...

  8. Feflow 源码解读

    Feflow 源码解读 Feflow(Front-end flow)是腾讯IVWEB团队的前端工程化解决方案,致力于改善多类型项目的开发流程中的规范和非业务相关的问题,可以让开发者将绝大部分精力集中在 ...

  9. Alamofire源码解读系列(五)之结果封装(Result)

    本篇讲解Result的封装 前言 有时候,我们会根据现实中的事物来对程序中的某个业务关系进行抽象,这句话很难理解.在Alamofire中,使用Response来描述请求后的结果.我们都知道Alamof ...

最新文章

  1. Lucene:依据索引查找文档
  2. 2013下半年福建高等学校非计算机专业学生计算机二级c语言原题,2013年福建省计算机二级c语言真题及答案(填空题部分)...
  3. 无连接网络通信程序UDP
  4. 7宗命案,潜逃23年,大数据还是认出了她
  5. Xen虚拟机两大迁移方法详解
  6. Windows下编写的脚本文件无法在Linux上运行的问题
  7. 12020.硬件电路
  8. Kafka常用命令之kafka-console-consumer.sh
  9. 获取页面iframe里的元素
  10. [浪风分享]推荐一些不错的计算机书籍
  11. 工程师素质拓展课程主页(2012级)
  12. mimics能导出什么格式_Mimics到底支持怎样的图像格式(修正版)
  13. Selenium加速执行方法
  14. java初级程序员成长之路
  15. Moodle中的session用法
  16. 斯嘉丽约翰逊60张pdf什么时间的?_巩俐入围威尼斯电影节的作品叫什么?巩俐为什么被称为女皇?...
  17. Java+控制台 商城销售系统
  18. 微信公众号注册时提示该主体注册数量已超过上限怎么办?
  19. 只有python扩展库才需要导入以后才能使用其中对象_只有Python扩展库才需要导入以后才能使用其中的对象,Python标准库不需要导入即可使用其中的所有对象和方法。...
  20. Win10十二月更新系统讲了什么?

热门文章

  1. java如何实现配置文件动态刷新_Spring Cloud 动态刷新配置信息教程详解
  2. TestBench中的timescale 时间延迟与时间精度
  3. The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _itoa. See onl
  4. Oracle +JDBC
  5. LTC(litecoin)测试环境搭建
  6. 位于[ ] 的网页无法加载,因为:net::ERR_CLEARTEXT_NOT_PERMITTED
  7. Pascal Voc数据集详细分析
  8. 蓝绿发布、滚动发布、灰度发布等部署方案对比与总结
  9. 高手才知道!七个你所不知道的 D3.js 秘技
  10. 通达信版弘历软件指标_弘历软件指标源码汇总。