Pytorch使用MNIST数据集实现基础GAN和DCGAN详解
原始生成对抗网络GenerativeAdversarialNetworksGAN包含生成器Generator和判别器Discriminator,数据有真实数据groundtruth,还有需要网络生成的“fake”数据,目的是网络生成的fake数据可以“骗过”判别器,让判别器认不出来,就是让判别器分不清进入的数据是真实数据还是fake数据。总的来说是:判别器区分真实数据和fake数据的能力越强越好;生成器生成的数据骗过判别器的能力越强越好,这个是矛盾的,所以只能交替训练网络。
需要搭建生成器网络和判别器网络,训练的时候交替训练。
首先训练判别器的参数,固定生成器的参数,让判别器判断生成器生成的数据,让其和0接近,让判别器判断真实数据,让其和1接近;
接着训练生成器的参数,固定判别器的参数,让生成器生成的数据进入判别器,让判断结果和1接近。生成器生成数据需要给定随机初始值
线性版:
importtorch fromtorch.utils.dataimportDataLoader fromtorchvision.datasetsimportMNIST fromtorchvisionimporttransforms fromtorchimportoptim importtorch.nnasnn importmatplotlib.pyplotasplt importnumpyasnp importmatplotlib.gridspecasgridspec defshowimg(images,count): images=images.detach().numpy()[0:16,:] images=255*(0.5*images+0.5) images=images.astype(np.uint8) grid_length=int(np.ceil(np.sqrt(images.shape[0]))) plt.figure(figsize=(4,4)) width=int(np.sqrt((images.shape[1]))) gs=gridspec.GridSpec(grid_length,grid_length,wspace=0,hspace=0) #gs.update(wspace=0,hspace=0) print('starting...') fori,imginenumerate(images): ax=plt.subplot(gs[i]) ax.set_xticklabels([]) ax.set_yticklabels([]) ax.set_aspect('equal') plt.imshow(img.reshape([width,width]),cmap=plt.cm.gray) plt.axis('off') plt.tight_layout() print('showing...') plt.tight_layout() plt.savefig('./GAN_Image/%d.png'%count,bbox_inches='tight') defloadMNIST(batch_size):#MNIST图片的大小是28*28 trans_img=transforms.Compose([transforms.ToTensor()]) trainset=MNIST('./data',train=True,transform=trans_img,download=True) testset=MNIST('./data',train=False,transform=trans_img,download=True) #device=torch.device("cuda:0"iftorch.cuda.is_available()else"cpu") trainloader=DataLoader(trainset,batch_size=batch_size,shuffle=True,num_workers=10) testloader=DataLoader(testset,batch_size=batch_size,shuffle=False,num_workers=10) returntrainset,testset,trainloader,testloader classdiscriminator(nn.Module): def__init__(self): super(discriminator,self).__init__() self.dis=nn.Sequential( nn.Linear(784,300), nn.LeakyReLU(0.2), nn.Linear(300,150), nn.LeakyReLU(0.2), nn.Linear(150,1), nn.Sigmoid() ) defforward(self,x): x=self.dis(x) returnx classgenerator(nn.Module): def__init__(self,input_size): super(generator,self).__init__() self.gen=nn.Sequential( nn.Linear(input_size,150), nn.ReLU(True), nn.Linear(150,300), nn.ReLU(True), nn.Linear(300,784), nn.Tanh() ) defforward(self,x): x=self.gen(x) returnx if__name__=="__main__": criterion=nn.BCELoss() num_img=100 z_dimension=100 D=discriminator() G=generator(z_dimension) trainset,testset,trainloader,testloader=loadMNIST(num_img)#data d_optimizer=optim.Adam(D.parameters(),lr=0.0003) g_optimizer=optim.Adam(G.parameters(),lr=0.0003) ''' 交替训练的方式训练网络 先训练判别器网络D再训练生成器网络G 不同网络的训练次数是超参数 也可以两个网络训练相同的次数 这样就可以不用分别训练两个网络 ''' count=0 #鉴别器D的训练,固定G的参数 epoch=100 gepoch=1 foriinrange(epoch): for(img,label)intrainloader: #num_img=img.size()[0] real_img=img.view(num_img,-1)#展开为28*28=784 real_label=torch.ones(num_img)#真实label为1 fake_label=torch.zeros(num_img)#假的label为0 #computelossofreal_img real_out=D(real_img)#真实图片送入判别器D输出0~1 d_loss_real=criterion(real_out,real_label)#得到loss real_scores=real_out#真实图片放入判别器输出越接近1越好 #computelossoffake_img z=torch.randn(num_img,z_dimension)#随机生成向量 fake_img=G(z)#将向量放入生成网络G生成一张图片 fake_out=D(fake_img)#判别器判断假的图片 d_loss_fake=criterion(fake_out,fake_label)#假的图片的loss fake_scores=fake_out#假的图片放入判别器输出越接近0越好 #Dbpandoptimize d_loss=d_loss_real+d_loss_fake d_optimizer.zero_grad()#判别器D的梯度归零 d_loss.backward()#反向传播 d_optimizer.step()#更新判别器D参数 #生成器G的训练computelossoffake_img forjinrange(gepoch): fake_label=torch.ones(num_img)#真实label为1 z=torch.randn(num_img,z_dimension)#随机生成向量 fake_img=G(z)#将向量放入生成网络G生成一张图片 output=D(fake_img)#经过判别器得到结果 g_loss=criterion(output,fake_label)#得到假的图片与真实标签的loss #bpandoptimize g_optimizer.zero_grad()#生成器G的梯度归零 g_loss.backward()#反向传播 g_optimizer.step()#更新生成器G参数 print('Epoch[{}/{}],d_loss:{:.6f},g_loss:{:.6f}' 'Dreal:{:.6f},Dfake:{:.6f}'.format( i,epoch,d_loss.data[0],g_loss.data[0], real_scores.data.mean(),fake_scores.data.mean())) showimg(fake_img,count) #plt.show() count+=1
这里的图分别是epoch为0、50、100、150、190的运行结果,可以看到图片中的数字并不单一
卷积版DeepConvolutionalGenerativeAdversarialNetworks:
importtorch fromtorch.utils.dataimportDataLoader fromtorchvision.datasetsimportMNIST fromtorchvisionimporttransforms fromtorchimportoptim importtorch.nnasnn importmatplotlib.pyplotasplt importnumpyasnp fromtorch.autogradimportVariable importmatplotlib.gridspecasgridspec importos defshowimg(images,count): images=images.to('cpu') images=images.detach().numpy() images=images[[6,12,18,24,30,36,42,48,54,60,66,72,78,84,90,96]] images=255*(0.5*images+0.5) images=images.astype(np.uint8) grid_length=int(np.ceil(np.sqrt(images.shape[0]))) plt.figure(figsize=(4,4)) width=images.shape[2] gs=gridspec.GridSpec(grid_length,grid_length,wspace=0,hspace=0) print(images.shape) fori,imginenumerate(images): ax=plt.subplot(gs[i]) ax.set_xticklabels([]) ax.set_yticklabels([]) ax.set_aspect('equal') plt.imshow(img.reshape(width,width),cmap=plt.cm.gray) plt.axis('off') plt.tight_layout() #print('showing...') plt.tight_layout() #plt.savefig('./GAN_Imaget/%d.png'%count,bbox_inches='tight') defloadMNIST(batch_size):#MNIST图片的大小是28*28 trans_img=transforms.Compose([transforms.ToTensor()]) trainset=MNIST('./data',train=True,transform=trans_img,download=True) testset=MNIST('./data',train=False,transform=trans_img,download=True) #device=torch.device("cuda:0"iftorch.cuda.is_available()else"cpu") trainloader=DataLoader(trainset,batch_size=batch_size,shuffle=True,num_workers=10) testloader=DataLoader(testset,batch_size=batch_size,shuffle=False,num_workers=10) returntrainset,testset,trainloader,testloader classdiscriminator(nn.Module): def__init__(self): super(discriminator,self).__init__() self.dis=nn.Sequential( nn.Conv2d(1,32,5,stride=1,padding=2), nn.LeakyReLU(0.2,True), nn.MaxPool2d((2,2)), nn.Conv2d(32,64,5,stride=1,padding=2), nn.LeakyReLU(0.2,True), nn.MaxPool2d((2,2)) ) self.fc=nn.Sequential( nn.Linear(7*7*64,1024), nn.LeakyReLU(0.2,True), nn.Linear(1024,1), nn.Sigmoid() ) defforward(self,x): x=self.dis(x) x=x.view(x.size(0),-1) x=self.fc(x) returnx classgenerator(nn.Module): def__init__(self,input_size,num_feature): super(generator,self).__init__() self.fc=nn.Linear(input_size,num_feature)#1*56*56 self.br=nn.Sequential( nn.BatchNorm2d(1), nn.ReLU(True) ) self.gen=nn.Sequential( nn.Conv2d(1,50,3,stride=1,padding=1), nn.BatchNorm2d(50), nn.ReLU(True), nn.Conv2d(50,25,3,stride=1,padding=1), nn.BatchNorm2d(25), nn.ReLU(True), nn.Conv2d(25,1,2,stride=2), nn.Tanh() ) defforward(self,x): x=self.fc(x) x=x.view(x.size(0),1,56,56) x=self.br(x) x=self.gen(x) returnx if__name__=="__main__": criterion=nn.BCELoss() num_img=100 z_dimension=100 D=discriminator() G=generator(z_dimension,3136)#1*56*56 trainset,testset,trainloader,testloader=loadMNIST(num_img)#data D=D.cuda() G=G.cuda() d_optimizer=optim.Adam(D.parameters(),lr=0.0003) g_optimizer=optim.Adam(G.parameters(),lr=0.0003) ''' 交替训练的方式训练网络 先训练判别器网络D再训练生成器网络G 不同网络的训练次数是超参数 也可以两个网络训练相同的次数, 这样就可以不用分别训练两个网络 ''' count=0 #鉴别器D的训练,固定G的参数 epoch=100 gepoch=1 foriinrange(epoch): for(img,label)intrainloader: #num_img=img.size()[0] img=Variable(img).cuda() real_label=Variable(torch.ones(num_img)).cuda()#真实label为1 fake_label=Variable(torch.zeros(num_img)).cuda()#假的label为0 #computelossofreal_img real_out=D(img)#真实图片送入判别器D输出0~1 d_loss_real=criterion(real_out,real_label)#得到loss real_scores=real_out#真实图片放入判别器输出越接近1越好 #computelossoffake_img z=Variable(torch.randn(num_img,z_dimension)).cuda()#随机生成向量 fake_img=G(z)#将向量放入生成网络G生成一张图片 fake_out=D(fake_img)#判别器判断假的图片 d_loss_fake=criterion(fake_out,fake_label)#假的图片的loss fake_scores=fake_out#假的图片放入判别器输出越接近0越好 #Dbpandoptimize d_loss=d_loss_real+d_loss_fake d_optimizer.zero_grad()#判别器D的梯度归零 d_loss.backward()#反向传播 d_optimizer.step()#更新判别器D参数 #生成器G的训练computelossoffake_img forjinrange(gepoch): fake_label=Variable(torch.ones(num_img)).cuda()#真实label为1 z=Variable(torch.randn(num_img,z_dimension)).cuda()#随机生成向量 fake_img=G(z)#将向量放入生成网络G生成一张图片 output=D(fake_img)#经过判别器得到结果 g_loss=criterion(output,fake_label)#得到假的图片与真实标签的loss #bpandoptimize g_optimizer.zero_grad()#生成器G的梯度归零 g_loss.backward()#反向传播 g_optimizer.step()#更新生成器G参数 #if((i+1)%1000==0): #print("[%d/%d]GLoss:%.5f"%(i+1,gepoch,g_loss.data[0])) print('Epoch[{}/{}],d_loss:{:.6f},g_loss:{:.6f}' 'Dreal:{:.6f},Dfake:{:.6f}'.format( i,epoch,d_loss.data[0],g_loss.data[0], real_scores.data.mean(),fake_scores.data.mean())) showimg(fake_img,count) plt.show() count+=1
这里的gepoch设置为1,运行39次的结果是:
gepoch设置为2,运行0、25、50、75、100次的结果是:
gepoch设置为3,运行25、50、75次的结果是:
gepoch设置为4,运行0、10、20、30、35次的结果是:
gepoch设置为5,运行0、10、20、25、29次的结果是:
gepoch设置为3,z_dimension设置为190,epoch运行0、10、15、20、25、35的结果是:
可以看到生成的数字基本没有太多的规律,可能最终都是同个数字,不能生成指定的数字,CGAN就很好的解决这个问题,可以生成指定的数字Pytorch使用MNIST数据集实现CGAN和生成指定的数字方式
以上这篇Pytorch使用MNIST数据集实现基础GAN和DCGAN详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。