<jupyter_start><jupyter_text>Conditional GAN (C-GAN)Originally proposed by [<NAME> al.](https://arxiv.org/pdf/1411.1784.pdf) is their work titled Conditional Generative Adversarial Nets. This network uses a basic implementation where generator and discriminator models are MLPs with additional inputs for conditioning with class labels.This notebook trains both networks using ADAM optimizer to play the minimax game. We showcase the effectiveness using MNIST digit generation [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/PacktPublishing/Hands-On-Generative-AI-with-Python-and-TensorFlow-2/blob/master/Chapter_6/conditional_gan.ipynb)  Load Libraries<jupyter_code>from tensorflow.keras import Model
from tensorflow.keras.layers import Input
from tensorflow.keras.optimizers import Adam
from tensorflow.keras import datasets
import numpy as np<jupyter_output><empty_output><jupyter_text>Load Utility Functions<jupyter_code>from gan_utils import build_conditional_discriminator
from gan_utils import build_conditional_generator
from gan_utils import sample_images<jupyter_output><empty_output><jupyter_text>Conditional GAN Training Loop- As proposed in the original paper- Randomly sample class labels as additional input for both discriminator and generator models- Calculate Discriminator loss- Fix the discriminator and calculate GAN/generator loss_Note : This is same as Vanilla GAN training_<jupyter_code>def train(generator=None,discriminator=None,gan_model=None,
          epochs=1000, batch_size=128, sample_interval=50,
          z_dim=100):
    # Load MNIST train samples
    (X_train, y_train), (_, _) = datasets.mnist.load_data()

    # Rescale -1 to 1
    X_train = X_train / 127.5 - 1
    X_train = np.expand_dims(X_train, axis=3)
    y_train = y_train.reshape(-1, 1)

    # Prepare GAN output labels
    real_y = np.ones((batch_size, 1))
    fake_y = np.zeros((batch_size, 1))

    for epoch in range(epochs):
        # train disriminator
        # pick random real samples from X_train
        idx = np.random.randint(0, X_train.shape[0], batch_size)
        real_imgs, labels = X_train[idx], y_train[idx]

        # pick random noise samples (z) from a normal distribution
        noise = np.random.normal(0, 1, (batch_size, z_dim))
        # use generator model to generate output samples
        fake_imgs = generator.predict([noise, labels])

        # calculate discriminator loss on real samples
        disc_loss_real = discriminator.train_on_batch([real_imgs, labels], real_y)
        
        # calculate discriminator loss on fake samples
        disc_loss_fake = discriminator.train_on_batch([fake_imgs, labels], fake_y)
        
        # overall discriminator loss
        discriminator_loss = 0.5 * np.add(disc_loss_real, disc_loss_fake)
        
        # train generator
        # pick random noise samples (z) from a normal distribution
        noise = np.random.normal(0, 1, (batch_size, z_dim))
        
        # pick random labels for conditioning
        sampled_labels = np.random.randint(0, 10, batch_size).reshape(-1, 1)

        # use trained discriminator to improve generator
        gen_loss = gan_model.train_on_batch([noise, sampled_labels], real_y)

        # training updates
        print ("%d [Discriminator loss: %f, acc.: %.2f%%] [Generator loss: %f]" % (epoch, 
                                                                                   discriminator_loss[0], 
                                                                                   100*discriminator_loss[1], 
                                                                                   gen_loss))

        # If at save interval => save generated image samples
        if epoch % sample_interval == 0:
            sample_images(epoch,generator)<jupyter_output><empty_output><jupyter_text>Prepare Discriminator Model<jupyter_code>discriminator = build_conditional_discriminator()
discriminator.compile(loss='binary_crossentropy',
                      optimizer=Adam(0.0002, 0.5),
                      metrics=['accuracy'])<jupyter_output>Model: "model"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_2 (InputLayer)            [(None, 1)]          0                                            
__________________________________________________________________________________________________
input_1 (InputLayer)            [(None, 28, 28, 1)]  0                                            
__________________________________________________________________________________________________
embedding (Embedding)           (None, 1, 784)       7840        input_2[0][0]                    
__________________________________________________________________________________________________
flatten (Flatten)               (None, 784)          0           input_1[0][0]                [...]<jupyter_text>Prepare Generator Model<jupyter_code>generator=build_conditional_generator()<jupyter_output>Model: "model_1"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_4 (InputLayer)            [(None, 1)]          0                                            
__________________________________________________________________________________________________
embedding_1 (Embedding)         (None, 1, 100)       1000        input_4[0][0]                    
__________________________________________________________________________________________________
input_3 (InputLayer)            [(None, 100)]        0                                            
__________________________________________________________________________________________________
flatten_2 (Flatten)             (None, 100)          0           embedding_1[0][0]          [...]<jupyter_text>Prepare GAN Model<jupyter_code># Noise for generator
z_dim = 100
z = Input(shape=(z_dim,))
label = Input(shape=(1,))
img = generator([z, label])

# Fix the discriminator
discriminator.trainable = False

# Get discriminator output
validity = discriminator([img, label])

# Stack discriminator on top of generator
gan_model = Model([z, label], validity)
gan_model.compile(loss='binary_crossentropy', optimizer=Adam(0.0002, 0.5))
gan_model.summary()<jupyter_output>Model: "model_2"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_5 (InputLayer)            [(None, 100)]        0                                            
__________________________________________________________________________________________________
input_6 (InputLayer)            [(None, 1)]          0                                            
__________________________________________________________________________________________________
model_1 (Model)                 (None, 28, 28, 1)    1492472     input_5[0][0]                    
                                                                 input_6[0][0]                    
____________________________________________________________________________________________[...]<jupyter_text>Train Conditional GAN<jupyter_code>train(generator,discriminator,gan_model,epochs=20000, batch_size=32, sample_interval=100)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10752688172043011, 'fraction_numerical': 0.021125869702719798, 'mean_word_length': 2.830426356589147, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 28, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 23, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '77570', 'license': 'MIT', 'n_tokens_mistral': 1938, 'n_tokens_neox': 1770, 'n_words': 450, 'path': 'Chapter_6/conditional_gan.ipynb', 'repo_name': 'PacktPublishing/Hands-On-Generative-AI-with-Python-and-TensorFlow-2', 'size': '7907'}