GAN代码

[复制链接]
发表于 2025-10-30 17:13:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
  1. import argparse
  2. import os
  3. import numpy as np
  4. import math
  5. import torchvision.transforms as transforms
  6. from torchvision.utils import save_image
  7. from torch.utils.data import DataLoader
  8. from torchvision import datasets
  9. from torch.autograd import Variable
  10. import torch.nn as nn
  11. import torch.nn.functional as F
  12. import torch
  13. os.makedirs("images", exist_ok=True)
  14. parser = argparse.ArgumentParser()
  15. parser.add_argument("--n_epochs", type=int, default=200, help="number of epochs of training")
  16. parser.add_argument("--batch_size", type=int, default=64, help="size of the batches")
  17. parser.add_argument("--lr", type=float, default=0.0002, help="adam: learning rate")
  18. parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient")
  19. parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient")
  20. parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation")
  21. parser.add_argument("--latent_dim", type=int, default=100, help="dimensionality of the latent space")
  22. parser.add_argument("--img_size", type=int, default=28, help="size of each image dimension")
  23. parser.add_argument("--channels", type=int, default=1, help="number of image channels")
  24. parser.add_argument("--sample_interval", type=int, default=400, help="interval betwen image samples")
  25. opt = parser.parse_args()
  26. print(opt)
  27. img_shape = (opt.channels, opt.img_size, opt.img_size)
  28. cuda = True if torch.cuda.is_available() else False
  29. class Generator(nn.Module):
  30.     def __init__(self):
  31.         super(Generator, self).__init__()
  32.         def block(in_feat, out_feat, normalize=True):
  33.             layers = [nn.Linear(in_feat, out_feat)]
  34.             if normalize:
  35.                 layers.append(nn.BatchNorm1d(out_feat, 0.8))
  36.             layers.append(nn.LeakyReLU(0.2, inplace=True))
  37.             return layers
  38.         self.model = nn.Sequential(
  39.             *block(opt.latent_dim, 128, normalize=False),
  40.             *block(128, 256),
  41.             *block(256, 512),
  42.             *block(512, 1024),
  43.             nn.Linear(1024, int(np.prod(img_shape))),
  44.             nn.Tanh()
  45.         )
  46.     def forward(self, z):
  47.         img = self.model(z)
  48.         img = img.view(img.size(0), *img_shape)
  49.         return img
  50. class Discriminator(nn.Module):
  51.     def __init__(self):
  52.         super(Discriminator, self).__init__()
  53.         self.model = nn.Sequential(
  54.             nn.Linear(int(np.prod(img_shape)), 512),
  55.             nn.LeakyReLU(0.2, inplace=True),
  56.             nn.Linear(512, 256),
  57.             nn.LeakyReLU(0.2, inplace=True),
  58.             nn.Linear(256, 1),
  59.             nn.Sigmoid(),
  60.         )
  61.     def forward(self, img):
  62.         img_flat = img.view(img.size(0), -1)
  63.         validity = self.model(img_flat)
  64.         return validity
  65. # Loss function
  66. adversarial_loss = torch.nn.BCELoss()
  67. # Initialize generator and discriminator
  68. generator = Generator()
  69. discriminator = Discriminator()
  70. if cuda:
  71.     generator.cuda()
  72.     discriminator.cuda()
  73.     adversarial_loss.cuda()
  74. # Configure data loader
  75. os.makedirs("../data/mnist", exist_ok=True)
  76. dataloader = torch.utils.data.DataLoader(
  77.     datasets.MNIST(
  78.         "../data/mnist",
  79.         train=True,
  80.         download=True,
  81.         transform=transforms.Compose(
  82.             [transforms.Resize(opt.img_size), transforms.ToTensor(), transforms.Normalize([0.5], [0.5])]
  83.         ),
  84.     ),
  85.     batch_size=opt.batch_size,
  86.     shuffle=True,
  87. )
  88. # Optimizers
  89. optimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))
  90. optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))
  91. Tensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor
  92. # ----------
  93. #  Training
  94. # ----------
  95. for epoch in range(opt.n_epochs):
  96.     for i, (imgs, _) in enumerate(dataloader):
  97.         # Adversarial ground truths
  98.         valid = Variable(Tensor(imgs.size(0), 1).fill_(1.0), requires_grad=False)#真的
  99.         fake = Variable(Tensor(imgs.size(0), 1).fill_(0.0), requires_grad=False)#假的
  100.         # Configure input
  101.         real_imgs = Variable(imgs.type(Tensor))
  102.         # -----------------
  103.         #  Train Generator
  104.         # -----------------
  105.         optimizer_G.zero_grad()
  106.         # Sample noise as generator input
  107.         z = Variable(Tensor(np.random.normal(0, 1, (imgs.shape[0], opt.latent_dim))))
  108.         # Generate a batch of images
  109.         gen_imgs = generator(z)
  110.         # Loss measures generator's ability to fool the discriminator
  111.         g_loss = adversarial_loss(discriminator(gen_imgs), valid)
  112.         
  113.         g_loss.backward()
  114.         optimizer_G.step()
  115.         # ---------------------
  116.         #  Train Discriminator
  117.         # ---------------------
  118.         optimizer_D.zero_grad()
  119.         # Measure discriminator's ability to classify real from generated samples
  120.         real_loss = adversarial_loss(discriminator(real_imgs), valid)
  121.         fake_loss = adversarial_loss(discriminator(gen_imgs.detach()), fake)
  122.                 #.detach():阻止生成器的梯度传播,这里只更新判别器
  123.         d_loss = (real_loss + fake_loss) / 2
  124.         d_loss.backward()
  125.         optimizer_D.step()
  126.         print(
  127.             "[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f]"
  128.             % (epoch, opt.n_epochs, i, len(dataloader), d_loss.item(), g_loss.item())
  129.         )
  130.         batches_done = epoch * len(dataloader) + i
  131.         if batches_done % opt.sample_interval == 0:
  132.             save_image(gen_imgs.data[:25], "images/%d.png" % batches_done, nrow=5, normalize=True)
  133.             os.makedirs("model", exist_ok=True)
  134.             torch.save(generator, 'model/generator.pkl')
  135.             torch.save(discriminator, 'model/discriminator.pkl')
复制代码

  • 练习discriminator时,valid是真实图像的标签1(对),fake是天生图片的标签0(错),generator和discriminator末了都履历一个tanh或sigmoid激活函数将它转化成一个概率,抱负环境下,将真实图像判定为1,将天生图像判定为0。这里两句就是为了缩小valid和real_imgs,fake和gen_imgs的差距。
  • *用法:解包,将列表/元组拆开,block()函数返回一个列表,Sequential也是列表,由于不想[ […] ],以是将block的列表拆开
  • 维度标题:在创建网络的时间,始终有一个img.size(0),也就是bitchsize在最前面,不外没用明写。比如Generator中,末了实际上的外形是(b, 28/*28);而Discriminator必要传入的是(b, 28/*28),以是传入前必要img_flat = img.view(img.size(0), -1)
  1. class Generator(nn.Module):
  2.     def __init__(self):
  3.         super(Generator, self).__init__()
  4.         def block(in_feat, out_feat, normalize=True):
  5.             layers = [nn.Linear(in_feat, out_feat)]
  6.             if normalize:
  7.                 layers.append(nn.BatchNorm1d(out_feat, 0.8))
  8.             layers.append(nn.LeakyReLU(0.2, inplace=True))
  9.             return layers
  10.                
  11.         self.model = nn.Sequential(
  12.             *block(opt.latent_dim, 128, normalize=False),
  13.             *block(128, 256),
  14.             *block(256, 512),
  15.             *block(512, 1024),
  16.             nn.Linear(1024, int(np.prod(img_shape))),                # np.prod(img_shape)`元组的合并(28, 28)->784
  17.             nn.Tanh()   #(b, 28*28)
  18.         )
  19.     def forward(self, z):
  20.         img = self.model(z)                #img:(b, 28*28), z:(b,latent_dim)
  21.         img = img.view(img.size(0), *img_shape)        #img.view(),改变张量的形状,传入的图像转化成(B, C, H, W)
  22.         return img
  23. class Discriminator(nn.Module):
  24.     def __init__(self):
  25.         super(Discriminator, self).__init__()
  26.         self.model = nn.Sequential(
  27.             nn.Linear(int(np.prod(img_shape)), 512),
  28.             nn.LeakyReLU(0.2, inplace=True),
  29.             nn.Linear(512, 256),
  30.             nn.LeakyReLU(0.2, inplace=True),
  31.             nn.Linear(256, 1),
  32.             nn.Sigmoid(),
  33.         )
  34.     def forward(self, img):
  35.         img_flat = img.view(img.size(0), -1)
  36.         validity = self.model(img_flat)
  37.         return validity
复制代码

  • z的维度latent_dim,与图片的巨细无关,相称于用了100个数作为原质料。随着天生器的本领越来越好,越来越轻易将这些原质料变成易于诱骗的图片。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表