liveBook · Manning

Conditional GAN

As explained in Inside Deep Learning: Math, Algorithms, Models

A GAN variant that conditions generation on additional information such as class labels.

A conditional GAN generates realistic data for a requested label instead of generating any plausible example. The generator G receives latent noise z and label y; the discriminator D receives the example and the same label. This turns an unconstrained GAN into a supervised, one-to-many mapping. section 9.5

The implementation adds conditioning with a small wrapper:

  • Embed each class label into a vector with the same shape as z. section 9.5.1
  • Concatenate the embedded label and z, then pass the result through a small combiner network. section 9.5.1
  • Wrap G and D independently, preserving the original networks while giving both access to y. section 9.5.1
  • Add class_label to every generator and discriminator call during training. section 9.5.2

Generating controlled digits

Reuse one latent vector across labels 0 through 9 and compute G(z | y) for each label. Each row can preserve style—such as line thickness or slant—while changing the digit class, because the label controls content and z carries variation. section 9.5.3

class ConditionalWrapper(nn.Module): 
    def __init__(self, input_shape, neurons, classes, main_network, 
     leak=0.2): 
        """ 
        input_shape: the shape that the latent variable z 
         should take. 
        neurons: neurons to use in hidden layers 
        classes: number of classes in labels y 
        main_network: either the generator G or discriminator D 
        """ 
        super().__init__() self.input_shape = input_shape 
        self.classes = classes 
        input_size = abs(np.prod(input_shape))                   #1 

        self.label_embedding = nn.Embedding(classes, input_size) #2

        self.combiner = nn.Sequential(                           #3 
            nn.Flatten(), 


            fcLayer(input_size*2, input_size, leak=leak),        #4 
            nn.Linear(input_size, input_size),                   #5 
            nn.LeakyReLU(leak), 

            View(input_shape),                                   #6
            nn.LayerNorm(input_shape[1:]), 
        ) 
        self.net = main_network

    def forward(self, x, condition=None):                        #7 
        if condition is None:                                    #8
            condition = torch.randint(0, self.classes, size=(x.size(0),), 
             device=x.get_device())

        embd = self.label_embedding(condition)                   #9 
        embd = embd.view(self.input_shape)                       #10 
        x = x.view(self.input_shape) 
        x_comb = torch.cat([x, embd], dim=1)                     #11 
        return self.net(self.combiner(x_comb))                   #12
#1 Figures out the number of latent parameters from the latent shape
#2 Creates an embedding layer to convert labels to vectors
#3 In the forward function, we concatenate the label and original date into one vector. Then this combiner takes that extra-large tensor and creates a new tensor the size of just the original input_shape. This does the work of merging the conditional information (from label_embedding) into the latent vector.
#4 One FC layer
#5 A second FC layer, but first the linear layer and activation are applied
#6 So we can reshape the output and apply normalizing based on the target output shape. This makes the conditional wrapper useful for linear and convolutional models.
#7 The forward function takes an input and produces an output.
#8 If no label was given, let’s pick one at random.
#9 Embeds the label and reshapes it as desired
#10 Makes sure the label embd and data x have the same shape so we can concatenate them
#11 Concatenates the latent input with the embedded label
#12 Returns the result of the network on the combined inputs

Inspect the ConditionalWrapper listing to connect label embedding, concatenation, and the combiner network to PyTorch module code. section 9.5.1

with torch.no_grad(): 
    noise = torch.randn(10, latent_d, device=device). #1 
     repeat((1,10)).view(-1, latent_d) labels =
    torch.fmod(torch.arange(0, noise.size(0),         #2 
     device=device), classes) 
    fake_digits = G(noise, labels)                    #3 
    scores = D(fake_digits, labels) 
    fake_digits = fake_digits.cpu() 
    scores = scores.cpu().numpy().flatten() 
plot_gen_imgs(fake_digits)                            #4
#1 Generates 10 latent noise vectors, and repeats them 10 times. We reuse the same latent codes.
#2 Counts from 0 to 9 and then wraps back around to 0. This is done 10 times.
#3 The same latent in noise is used to generate 10 images, but we change the label each time.
#4 When we plot the results, we should see a grid of digits from 0 to 9, where each row uses the same latent vector and shares similar visual properties.

Inspect the generation listing to see repeated latent vectors paired with labels and passed to G and D. section 9.5.3

How Inside Deep Learning: Math, Algorithms, Models covers it

How deep it goes
Explains the one-to-many mapping, wrapper architecture, training-call changes, and shared-latent sampling, while deferring deeper conditioning methods.
Examples
Demonstrates ten-class digit generation, shared latent vectors, preserved handwriting style, and PyTorch ConditionalWrapper listings.
What it assumes
Assumes familiarity with ordinary GANs, latent vectors, generators, discriminators, and labels while introducing conditional supervision directly.
What you can do after
Build it from scratch by wrapping PyTorch generator and discriminator networks, training with labels, and sampling selected classes.
How it connects
Connects GANs, generators, discriminators, latent space, class labels, supervised learning, and Wasserstein GAN training.

Also explained in

Compare how 2 books explain conditional GAN →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Inside Deep Learning: Math, Algorithms, Models. The section links point to the parts of the book it draws on.