Logo elodees  elodees

A caring AI for a better world













Only alphabetic characters accented or not as well as the space are accepted

Logo IA




Auxiliary Classifier Generative Adversarial Networks (ACGAN)





No account yet ?

Sign up to access all content




Generative adversarial networks, or GANs, are an architecture for training generative models, such as deep convolutional neural networks to generate images.

The GAN Auxiliary Classifier, or AC-GAN is an extension of the Conditional GAN that modifies the discriminator to predict the class label of a given image rather than receiving it as input.

The auxiliary classifier GAN has the effect of stabilizing the learning process and allowing the generation of large, high-quality images while learning a representation in latent space independent of the class label.



A PyTorch implementation of Auxiliary Classifier GAN to generate CIFAR10 images



Tested in Anaconda and Python 3.7

import torch
import torch.nn as nn
from torchvision.utils import make_grid
import torch.optim as optim
import numpy as np
import torchvision
import torch.nn.functional as F
import matplotlib.pyplot as plt
import torchvision.transforms as transforms
 
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(device)
 
 
tf = transforms.Compose([transforms.Resize(64),
                         transforms.ToTensor(),
                         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
                        ])
 
trainset = torchvision.datasets.CIFAR10(root = './data', train = True, download = True,
                                     transform = tf)
 
 
testset = torchvision.datasets.CIFAR10(root = './data', train = False, download = True,
                                    transform = tf)
 
dataset = torch.utils.data.ConcatDataset([trainset, testset])
 
 
trainloader = torch.utils.data.DataLoader(dataset, batch_size = 100, 
                                         num_workers = 2, shuffle = True)
 
print(len(dataset))
print(dataset[0][0].size())
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck', 'fake')
 
def showImage(images,epoch=-99, idx = -99):
    images = images.cpu().numpy()
    images = images/2 + 0.5
    plt.imshow(np.transpose(images,axes = (1,2,0)))
    plt.axis('off')
    if epoch!=-99:
        plt.savefig("e" + str(epoch) + "i" + str(idx) + ".png")
 
dataiter = iter(trainloader)
images,labels = dataiter.next()
print(images.size())
showImage(make_grid(images[0:64]))
 
class Generator(nn.Module):
 
    def __init__(self):
        super(Generator,self).__init__()
 
        #input 100*1*1
        self.layer1 = nn.Sequential(nn.ConvTranspose2d(100,512,4,1,0,bias = False),
                                   nn.ReLU(True))
 
        #input 512*4*4
        self.layer2 = nn.Sequential(nn.ConvTranspose2d(512,256,4,2,1,bias = False),
                                   nn.BatchNorm2d(256),
                                   nn.ReLU(True))
        #input 256*8*8
        self.layer3 = nn.Sequential(nn.ConvTranspose2d(256,128,4,2,1,bias = False),
                                   nn.BatchNorm2d(128),
                                   nn.ReLU(True))
        #input 128*16*16
        self.layer4 = nn.Sequential(nn.ConvTranspose2d(128,64,4,2,1,bias = False),
                                   nn.BatchNorm2d(64),
                                   nn.ReLU(True))
        #input 64*32*32
        self.layer5 = nn.Sequential(nn.ConvTranspose2d(64,3,4,2,1,bias = False),
                                   nn.Tanh())
        #output 3*64*64
 
        self.embedding = nn.Embedding(10,100)
 
 
    def forward(self,noise,label):
 
        label_embedding = self.embedding(label)
        x = torch.mul(noise,label_embedding)
        x = x.view(-1,100,1,1)
 
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = self.layer5(x)
        return x
 
 
class Discriminator(nn.Module):
 
    def __init__(self):
        super(Discriminator,self).__init__()        
 
        #input 3*64*64
        self.layer1 = nn.Sequential(nn.Conv2d(3,64,4,2,1,bias = False),
                                    nn.BatchNorm2d(64),
                                   nn.LeakyReLU(0.2,True),
                                   nn.Dropout2d(0.5))
 
        #input 64*32*32
        self.layer2 = nn.Sequential(nn.Conv2d(64,128,4,2,1,bias = False),
                                    nn.BatchNorm2d(128),
                                   nn.LeakyReLU(0.2,True),
                                   nn.Dropout2d(0.5))
        #input 128*16*16
        self.layer3 = nn.Sequential(nn.Conv2d(128,256,4,2,1,bias = False),
                                    nn.BatchNorm2d(256),
                                   nn.LeakyReLU(0.2,True),
                                   nn.Dropout2d(0.5))
        #input 256*8*8
        self.layer4 = nn.Sequential(nn.Conv2d(256,512,4,2,1,bias = False),
                                    nn.BatchNorm2d(512),
                                   nn.LeakyReLU(0.2,True))
        #input 512*4*4
        self.validity_layer = nn.Sequential(nn.Conv2d(512,1,4,1,0,bias = False),
                                   nn.Sigmoid())
 
        self.label_layer = nn.Sequential(nn.Conv2d(512,11,4,1,0,bias = False),
                                   nn.LogSoftmax(dim = 1))
 
    def forward(self,x):
 
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        validity = self.validity_layer(x)
        plabel = self.label_layer(x)
 
        validity = validity.view(-1)
        plabel = plabel.view(-1,11)
 
        return validity,plabel
 
 
# custom weights initialization called on netG and netD
def weights_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)
 
gen = Generator().to(device)
gen.apply(weights_init)
 
disc = Discriminator().to(device)
disc.apply(weights_init)
 
paramsG = list(gen.parameters())
print(len(paramsG))
 
paramsD = list(disc.parameters())
print(len(paramsD))        
 
optimG = optim.Adam(gen.parameters(), 0.0002, betas = (0.5,0.999))
optimD = optim.Adam(disc.parameters(), 0.0002, betas = (0.5,0.999))
 
validity_loss = nn.BCELoss()
 
real_labels = 0.7 + 0.5 * torch.rand(10, device = device)
fake_labels = 0.3 * torch.rand(10, device = device)
epochs = 10
 
for epoch in range(1,epochs+1):
 
    for idx, (images,labels) in enumerate(trainloader,0):
 
        batch_size = images.size(0)
        labels= labels.to(device)
        images = images.to(device)
 
        real_label = real_labels[idx % 10]
        fake_label = fake_labels[idx % 10]
 
        fake_class_labels = 10*torch.ones((batch_size,),dtype = torch.long,device = device)
 
        if idx % 25 == 0:
            real_label, fake_label = fake_label, real_label
 
        # ---------------------
        #         disc
        # ---------------------
 
        optimD.zero_grad()       
 
        # real
        validity_label = torch.full((batch_size,),real_label , device = device)
 
        pvalidity, plabels = disc(images)       
 
        errD_real_val = validity_loss(pvalidity, validity_label)            
        errD_real_label = F.nll_loss(plabels,labels)
 
        errD_real = errD_real_val + errD_real_label
        errD_real.backward()
 
        D_x = pvalidity.mean().item()        
 
        #fake 
        noise = torch.randn(batch_size,100,device = device)  
        sample_labels = torch.randint(0,10,(batch_size,),device = device, dtype = torch.long)
 
        fakes = gen(noise,sample_labels)
 
        validity_label.fill_(fake_label)
 
        pvalidity, plabels = disc(fakes.detach())       
 
        errD_fake_val = validity_loss(pvalidity, validity_label)
        errD_fake_label = F.nll_loss(plabels, fake_class_labels)
 
        errD_fake = errD_fake_val + errD_fake_label
        errD_fake.backward()
 
        D_G_z1 = pvalidity.mean().item()
 
        #finally update the params!
        errD = errD_real + errD_fake
 
        optimD.step()
 
 
        # ------------------------
        #      gen
        # ------------------------
 
 
        optimG.zero_grad()
 
        noise = torch.randn(batch_size,100,device = device)  
        sample_labels = torch.randint(0,10,(batch_size,),device = device, dtype = torch.long)
 
        validity_label.fill_(1)
 
        fakes = gen(noise,sample_labels)
        pvalidity,plabels = disc(fakes)
 
        errG_val = validity_loss(pvalidity, validity_label)        
        errG_label = F.nll_loss(plabels, sample_labels)
 
        errG = errG_val + errG_label
        errG.backward()
 
        D_G_z2 = pvalidity.mean().item()
 
        optimG.step()
 
 
        print("[{}/{}] [{}/{}] D_x: [{:.4f}] D_G: [{:.4f}/{:.4f}] G_loss: [{:.4f}] D_loss: [{:.4f}] D_label: [{:.4f}] "
              .format(epoch,epochs, idx, len(trainloader),D_x, D_G_z1,D_G_z2,errG,errD,
                      errD_real_label + errD_fake_label + errG_label))
 
 
        if idx % 100 == 0:
            noise = torch.randn(10,100,device = device)  
            labels = torch.arange(0,10,dtype = torch.long,device = device)
 
            gen_images = gen(noise,labels).detach()
 
            showImage(make_grid(gen_images),epoch,idx)
 
 
torch.save(gen.state_dict(),'gen.pth')
torch.save(disc.state_dict(),'disc.pth')
 


ACGAN_cifar10 - GitHub



Tensorflow playground




Neural network


Data engineering


Deep learning

Machine learning












Welcome, my name is Eric Soupet and I am the administrator of the site elodees.com. elodees.com is a state of the art of Artificial Intelligence and aims to be collaborative, you can now offer content such as articles, events, tutorials, ... so don't hesitate !

Platform images credit : Pixabay - Pixabay License | Pexels - Pexels License