4399知名游戏-赛尔号之随机生成精灵图鉴(DCGAN)

4399知名游戏-赛尔号之随机生成精灵图鉴(DCGAN)

面向对象:

1.疫情居家无聊之人
2.有一点点PyTorch基础就行


数据集获取:

点此查看获取方式


头文件:

已经搭好pytorch环境的,还缺头文件的直接pip install即可

import random
import tqdm
import torch
import torch.nn as nn
import torch.nn.parallel
import torch.optim as optim
import torch.utils.data as Data
import torchvision.datasets as datasets
import torchvision.transforms as transforms
import numpy as np

参数设置:

采用和DCGAN一模一样的参数设置,数据集放在同目录的seer文件夹下

root = "./seer"    #你的数据集的相对路径
workers = 2
batch_size = 128
image_size = 64
nc = 3
nz = 100
ngf = 64
ndf = 64
num_epochs = 1000    #想训练几轮就训练几轮
lr = 0.0002
beta1 = 0.5
ngpu = 2    #gpu的个数

由于我是在服务器上跑的,一个EPOCH大概两秒左右,毕竟数据集比较小,也没有考虑数据增强等操作,直接用transform意思一下,用起来很方便也很简单。数据集获取以及批训练载入dataloader如下:

dataset = datasets.ImageFolder(root,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 = Data.DataLoader(dataset, batch_size=batch_size,shuffle=True, num_workers=workers)

模型搭建:

1.生成器部分:【和DCGAN一模一样,动都没动过,生成器输入通道:100,输出通道:nc,也就是RGB三个通道,最后的激活函数使用Tanh,使模型输出分布在-1到1之间】

class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.main = nn.Sequential(
            nn.ConvTranspose2d( nz, ngf * 8, 4, 1, 0, bias=False),
            nn.BatchNorm2d(ngf * 8),
            nn.ReLU(True),
            nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf * 4),
            nn.ReLU(True),
            nn.ConvTranspose2d( ngf * 4, ngf * 2, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf * 2),
            nn.ReLU(True),
            nn.ConvTranspose2d( ngf * 2, ngf, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf),
            nn.ReLU(True),
            nn.ConvTranspose2d( ngf, nc, 4, 2, 1, bias=False),
            nn.Tanh()
        )

    def forward(self, input):
        return self.main(input)

2.判别器部分:【原封不动的判别器,判别器主要用来接收两个地方的输入,一个是经过transform过的原始图片,其值分布在-1到1之间,另一个是生成器的输出,由于Tanh的激活函数作用使得其值也分布在-1到1之间,最终经过sigmoid输出一个值域在0到1之间的分数】

class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.main = nn.Sequential(
            nn.Conv2d(nc, ndf, 4, 2, 1, bias=False),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ndf * 2),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ndf * 4),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ndf * 8),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False),
            nn.Sigmoid()
        )

    def forward(self, input):
        return self.main(input)

模型加载以及优化器的选择:

将模型移植到GPU上,采用并行的方式加载模型,优化参数也是没有动过hh

netG = Generator().cuda()
netG = nn.DataParallel(netG, list(range(ngpu)))
netG.apply(weights_init)
netD = Discriminator().cuda()
netD = nn.DataParallel(netD, list(range(ngpu)))    
netD.apply(weights_init)

criterion = nn.BCELoss()
optimizerD = optim.Adam(netD.parameters(), lr=lr, betas=(beta1, 0.999))
optimizerG = optim.Adam(netG.parameters(), lr=lr, betas=(beta1, 0.999))

模型训练:

其基本原理就是
1.先让判别器去认识真实图片,也就是我们爬取的赛尔号精灵原图,让判别器觉得它们是原图,更新判别器。
2.让判别器去辨别生成器输出的虚假图片,让判别器觉得他们不是原图,更新判别器。
3.让判别器去认为生成器生成的虚假图片是我们爬取的赛尔号精灵原图,更新生成器。

print("Training...")
for epoch in range(num_epochs):
    for i, (data,label) in tqdm.tqdm(enumerate(dataloader, 0)):
        length = len(data)
        netD.zero_grad()
        data = data.cuda()
        labelt = torch.ones(length,1).cuda()
        output = netD(data).view(length,-1)
        errD_real = criterion(output, labelt)
        errD_real.backward()

        noise = torch.randn(length, nz, 1, 1).cuda()
        fake = netG(noise)
        labelf = torch.zeros(length,1).cuda()
        output = netD(fake.detach()).view(length,-1)
        errD_fake = criterion(output, labelf)
        errD_fake.backward()
        optimizerD.step()
    
        netG.zero_grad()
        output = netD(fake).view(length,-1)
        errG = criterion(output, labelt)
        errG.backward()
        optimizerG.step()    

    torch.save(netG.state_dict(),'./model/seer-'+str(epoch))

最后保存模型位于同目录下的model文件夹中。

查看效果:

1.可以在训练代码中添加临时变量查看每次保存模型时候D(G(X))的值是不是趋于0.5,就是当判别器足够强大时,真实图和生成器生成的虚假图让判别器分不出来时,模型就能达到一个很好的效果。
2.直接用肉眼看

查看效果的代码如下:(文件名为saveres.py)运行命令为 {python saveres.py [model-name] [一个大于64的数用于后续筛选] }

import random
import torch
import torch.nn as nn
import torch.nn.parallel
import torch.backends.cudnn as cudnn
import torch.optim as optim
import torch.utils.data
import torchvision.datasets as dset
import torchvision.transforms as transforms
import torchvision.utils as vutils
import numpy as np
import sys

nc = 3
nz = 100
ngf = 64
ndf = 64
ngpu = 2
manualSeed = 666
print("Random Seed: ", manualSeed)
random.seed(manualSeed)
torch.manual_seed(manualSeed)

class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.main = nn.Sequential(
            nn.ConvTranspose2d( nz, ngf * 8, 4, 1, 0, bias=False),
            nn.BatchNorm2d(ngf * 8),
            nn.ReLU(True),
            nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf * 4),
            nn.ReLU(True),
            nn.ConvTranspose2d( ngf * 4, ngf * 2, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf * 2),
            nn.ReLU(True),
            nn.ConvTranspose2d( ngf * 2, ngf, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf),
            nn.ReLU(True),
            nn.ConvTranspose2d( ngf, nc, 4, 2, 1, bias=False),
            nn.Tanh()
        )

    def forward(self, input):
        return self.main(input)

class DIS(nn.Module):
    def __init__(self):
        super(DIS, self).__init__()
        self.main = nn.Sequential(
            nn.Conv2d(3, 64, 4, 2, 1, bias=False),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Conv2d(64, 64 * 2, 4, 2, 1, bias=False),
            nn.BatchNorm2d(64 * 2),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Conv2d(64 * 2, 64 * 4, 4, 2, 1, bias=False),
            nn.BatchNorm2d(64 * 4),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Conv2d(64 * 4, 64 * 8, 4, 2, 1, bias=False),
            nn.BatchNorm2d(64 * 8),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Conv2d(64 * 8, 1, 4, 1, 0, bias=False),
            nn.Sigmoid()
        )

    def forward(self, input):
        return self.main(input)


netG = Generator().cuda()
netG = nn.DataParallel(netG, list(range(ngpu)))
cudnn.benchmark = True
modelname = './model/'+str(sys.argv[1])
netG.load_state_dict(torch.load(modelname))
noise = torch.randn(int(sys.argv[2]), nz, 1, 1).cuda()    #这里就是一个大于64的数
out = netG(noise)

netD = DIS().cuda()
netD = nn.DataParallel(netD, list(range(2)))
cudnn.benchmark = True
scores = netD(out).detach().view(int(sys.argv[2]),-1)
index = scores.topk(64,dim = 0)[1]    #这里就是为什么那个数要大于64
result = []
for ii in index:
    result.append(out.data[ii].squeeze())

vutils.save_image(torch.stack(result),'res.png',range = (-1,1))

其实这个看效果的代码只是载入了模型,生成一个【num,100,1,1】维度的随机数输入生成器,生成器输出维度为【num,3,64,64】的虚假图片,这些图片输入判别器输出维度为【num,1,1,1】的score序列,筛选前面64个最好的生成结果合并为同一个图片后保存本地。

生成结果展示:

epoch1:
在这里插入图片描述

epoch10:
在这里插入图片描述
epoch100:
在这里插入图片描述
epoch1000:
在这里插入图片描述
上图中所生成的精灵是通过随机数输入生成器模型输出的并不存在的精灵。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 哪吒 2. 无情的游戏 3. 逆战 4. 荒野行动 5. 绝地求生 6. 阴阳师 7. 征途2 8. 最强王者 9. 格斗之王 10. 王者荣耀 11. 穿越火线 12. 变形金刚 13. 刺激战场 14. 逆水寒 15. 明日之后 16. 街头篮球 17. 小小军团 18. 风暴英雄 19. 镇魂街 20. 皇室战争 21. 神武4 22. 神龙猎手 23. 三国杀 24. 战争雷霆 25. 天涯明月刀 26. 猎魔群英传 27. 剑网3 28. 天龙八部 29. 火影忍者 30. 小米枪战 31. 大话西游2 32. 守望先锋 33. 问道 34. 诛仙3 35. 神鬼传奇 36. 魔兽世界 37. 真三国无双 38. 赛尔号 39. 命运2 40. 龙之谷 41. 大天使之剑 42. 劲舞团 43. 热血江湖 44. 神仙道 45. 使命召唤 46. 洛奇英雄传 47. 梦幻西游 48. 钢铁雄心 49. 光荣使命 50. 大话封神 51. 永恒之塔 52. 塔防三国志 53. 魔域 54. DNF 55. 神话 56. 奇迹MU 57. 神雕侠侣 58. 火影忍者OL 59. 奇迹世界 60. 热血传奇 61. 鬼泣 62. 王牌战士 63. 传奇霸业 64. 十万个冷笑话 65. 传世之爱 66. 风暴战区 67. 御龙在天 68. 乱斗西游 69. 九阴真经 70. 九州缥缈录 71. 一起来捉妖 72. 诸神之战 73. 飞车 74. 突围行动 75. 乱世王者 76. 梦幻诛仙 77. 梦想世界 78. 洛克王国 79. 问道九州 80. 掌上英雄联盟 81. 梦幻西游手游 82. LOL 83. 神雕侠侣手游 84. 问道手游 85. 天龙八部手游 86. 神武4手游 87. 逆水寒手游 88. 大话西游手游 89. 火影忍者手游 90. 格斗之王手游 91. 进击的巨人手游 92. 剑网3手游 93. 王者荣耀手游 94. 神龙猎手手游 95. 小米枪战手游 96. 穿越火线手游 97. 绝地求生手游 98. 刺激战场手游 99. 决战!平安京 100. 皇室战争手游

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值