code: import torch
  import torch.nn as nn
  
  
  # custom weights initialization called on netG and netD
  def weights_init(m):
      classname = m.__class__.__name__
      if classname.find('Conv') != -1:
          nn.init.normal_(m.weight.data, 0.0, 0.02)
      elif classname.find('BatchNorm') != -1:
          nn.init.normal_(m.weight.data, 1.0, 0.02)
          nn.init.constant_(m.bias.data, 0)
  
  
  class Generator(nn.Module):
      def __init__(self, latent_dim, img_size=32):
          super(Generator, self).__init__()
  
          self.init_size = img_size // 4
          self.l1 = nn.Sequential(nn.Linear(latent_dim, 128 * self.init_size ** 2))
  
          self.conv_blocks = nn.Sequential(
              nn.BatchNorm2d(128),
              nn.Upsample(scale_factor=2),
              nn.Conv2d(128, 128, 3, stride=1, padding=1),
              nn.BatchNorm2d(128, 0.8),
              nn.LeakyReLU(0.2, inplace=True),
              nn.Upsample(scale_factor=2),
              nn.Conv2d(128, 64, 3, stride=1, padding=1),
              nn.BatchNorm2d(64, 0.8),
              nn.LeakyReLU(0.2, inplace=True),
              nn.Conv2d(64, 3, 3, stride=1, padding=1),
              nn.Tanh(),
          )
  
      def forward(self, z):
          out = self.l1(z)
          out = out.view(out.shape[0], 128, self.init_size, self.init_size)
          img = self.conv_blocks(out)
          return img
  
  
  class Discriminator(nn.Module):
      def __init__(self, img_size=32):
          super(Discriminator, self).__init__()
  
          def discriminator_block(in_filters, out_filters, bn=True):
              block = [nn.Conv2d(in_filters, out_filters, 3, 2, 1), nn.LeakyReLU(0.2, inplace=True), nn.Dropout2d(0.25)]
              if bn:
                  block.append(nn.BatchNorm2d(out_filters, 0.8))
              return block
  
          self.conv_blocks = nn.Sequential(
              *discriminator_block(3, 16, bn=False),
              *discriminator_block(16, 32),
              *discriminator_block(32, 64),
              *discriminator_block(64, 128),
          )
  
          # The height and width of downsampled image
          ds_size = img_size // 2 ** 4
          self.adv_layer = nn.Sequential(nn.Linear(128 * ds_size ** 2, 1), nn.Sigmoid())
  
      def forward(self, img):
          out = self.conv_blocks(img)
          out = torch.flatten(out, 1)
          validity = self.adv_layer(out)
  
          return validity
  
  
  def test():
      n_class, nz = 10, 100
      netG = Generator(n_class)
      netD = Discriminator()
      noise = torch.randn([32, nz])
      label = torch.randint(0, n_class, [32])
      img = netG(noise, label)
      valid, output = netD(img)
      pass
  
  # test()
  
apis: torch.nn.BatchNorm2d torch.nn.Linear torch.randint torch.nn.init.constant_ torch.nn.Dropout2d torch.randn torch.flatten torch.nn.init.normal_ torch.nn.Tanh torch.nn.Upsample torch.nn.Conv2d torch.nn.Sigmoid torch.nn.LeakyReLU