Bird
Raised Fist0
TensorFlowml~5 mins

Simple GAN implementation in TensorFlow

Choose your learning style10 modes available
Introduction

A GAN helps a computer learn to create new data like images by playing a game between two models.

When you want to create new images similar to a set of photos you have.
When you want to learn how two models can improve by competing with each other.
When you want to generate fake but realistic data for testing.
When you want to understand how creative AI can be.
When you want to explore how computers can learn patterns without labels.
Syntax
TensorFlow
1. Define a generator model that creates fake data from random noise.
2. Define a discriminator model that tells real data from fake data.
3. Train the discriminator on real and fake data.
4. Train the generator to fool the discriminator.
5. Repeat steps 3 and 4 many times.

The generator tries to make data that looks real.

The discriminator tries to tell real from fake data.

Examples
This creates a generator that turns random noise into 28x28 images.
TensorFlow
def make_generator_model():
    model = tf.keras.Sequential([
        tf.keras.layers.Dense(7*7*256, use_bias=False, input_shape=(100,)),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.LeakyReLU(),
        tf.keras.layers.Reshape((7, 7, 256)),
        tf.keras.layers.Conv2DTranspose(128, (5, 5), strides=(1, 1), padding='same', use_bias=False),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.LeakyReLU(),
        tf.keras.layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', use_bias=False),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.LeakyReLU(),
        tf.keras.layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', use_bias=False, activation='tanh')
    ])
    return model
This creates a discriminator that decides if an image is real or fake.
TensorFlow
def make_discriminator_model():
    model = tf.keras.Sequential([
        tf.keras.layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same', input_shape=[28, 28, 1]),
        tf.keras.layers.LeakyReLU(),
        tf.keras.layers.Dropout(0.3),
        tf.keras.layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'),
        tf.keras.layers.LeakyReLU(),
        tf.keras.layers.Dropout(0.3),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(1)
    ])
    return model
Sample Model

This code trains a simple GAN on the MNIST dataset for 1 epoch. It prints the generator and discriminator losses after the epoch and shows the shape of generated images.

TensorFlow
import tensorflow as tf
import numpy as np

# Load and prepare the dataset
(train_images, _), (_, _) = tf.keras.datasets.mnist.load_data()
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32')
train_images = (train_images - 127.5) / 127.5  # Normalize to [-1, 1]

BUFFER_SIZE = 60000
BATCH_SIZE = 256

train_dataset = tf.data.Dataset.from_tensor_slices(train_images).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)

# Generator model

def make_generator_model():
    model = tf.keras.Sequential([
        tf.keras.layers.Dense(7*7*256, use_bias=False, input_shape=(100,)),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.LeakyReLU(),
        tf.keras.layers.Reshape((7, 7, 256)),
        tf.keras.layers.Conv2DTranspose(128, (5, 5), strides=(1, 1), padding='same', use_bias=False),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.LeakyReLU(),
        tf.keras.layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', use_bias=False),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.LeakyReLU(),
        tf.keras.layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', use_bias=False, activation='tanh')
    ])
    return model

# Discriminator model

def make_discriminator_model():
    model = tf.keras.Sequential([
        tf.keras.layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same', input_shape=[28, 28, 1]),
        tf.keras.layers.LeakyReLU(),
        tf.keras.layers.Dropout(0.3),
        tf.keras.layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'),
        tf.keras.layers.LeakyReLU(),
        tf.keras.layers.Dropout(0.3),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(1)
    ])
    return model

# Loss functions

cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)

def discriminator_loss(real_output, fake_output):
    real_loss = cross_entropy(tf.ones_like(real_output), real_output)
    fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output)
    total_loss = real_loss + fake_loss
    return total_loss

def generator_loss(fake_output):
    return cross_entropy(tf.ones_like(fake_output), fake_output)

# Create models

generator = make_generator_model()
discriminator = make_discriminator_model()

# Optimizers

generator_optimizer = tf.keras.optimizers.Adam(1e-4)
discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)

# Training loop

EPOCHS = 1
noise_dim = 100
num_examples_to_generate = 16

seed = tf.random.normal([num_examples_to_generate, noise_dim])

@tf.function
def train_step(images):
    noise = tf.random.normal([BATCH_SIZE, noise_dim])

    with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
        generated_images = generator(noise, training=True)

        real_output = discriminator(images, training=True)
        fake_output = discriminator(generated_images, training=True)

        gen_loss = generator_loss(fake_output)
        disc_loss = discriminator_loss(real_output, fake_output)

    gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)
    gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables)

    generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))
    discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables))

    return gen_loss, disc_loss

for epoch in range(EPOCHS):
    for image_batch in train_dataset:
        gen_loss, disc_loss = train_step(image_batch)
    print(f'Epoch {epoch+1}, Generator loss: {gen_loss.numpy():.4f}, Discriminator loss: {disc_loss.numpy():.4f}')

# Generate some images after training

generated_images = generator(seed, training=False)
print(f'Generated images shape: {generated_images.shape}')
OutputSuccess
Important Notes

Training GANs can be tricky; losses may not always decrease smoothly.

Normalization of input images to [-1, 1] helps the generator output match the data range.

Use small batch sizes and learning rates to stabilize training.

Summary

A GAN has two parts: generator and discriminator.

The generator tries to create fake data to fool the discriminator.

Training alternates between improving the generator and discriminator.

Practice

(1/5)
1. In a simple GAN, what is the main role of the generator?
easy
A. To classify data as real or fake
B. To create fake data that looks real
C. To optimize the loss function of the discriminator
D. To preprocess the input data

Solution

  1. Step 1: Understand the generator's purpose

    The generator's job is to produce fake data samples that resemble real data.
  2. Step 2: Differentiate from discriminator's role

    The discriminator's role is to distinguish real from fake data, not the generator's.
  3. Final Answer:

    To create fake data that looks real -> Option B
  4. Quick Check:

    Generator = create fake data [OK]
Hint: Generator makes fake data to fool discriminator [OK]
Common Mistakes:
  • Confusing generator with discriminator
  • Thinking generator classifies data
  • Assuming generator preprocesses data
2. Which of the following is the correct way to define the input noise vector for the generator in TensorFlow?
easy
A. noise = tf.random.normal([batch_size, noise_dim])
B. noise = tf.zeros([batch_size, noise_dim])
C. noise = tf.ones([batch_size, noise_dim])
D. noise = tf.random.uniform([noise_dim])

Solution

  1. Step 1: Identify typical noise input shape

    The noise vector usually has shape [batch_size, noise_dim] to generate a batch of samples.
  2. Step 2: Check correct TensorFlow function

    tf.random.normal generates random normal noise, commonly used for GAN input.
  3. Final Answer:

    noise = tf.random.normal([batch_size, noise_dim]) -> Option A
  4. Quick Check:

    Use tf.random.normal with batch size and noise dim [OK]
Hint: Use tf.random.normal with batch and noise dims [OK]
Common Mistakes:
  • Using tf.zeros or tf.ones which produce constant noise
  • Missing batch dimension in noise shape
  • Using tf.random.uniform without batch dimension
3. Given this TensorFlow code snippet for a GAN training step, what will be the shape of fake_output?
noise = tf.random.normal([32, 100])
fake_images = generator(noise)
fake_output = discriminator(fake_images)
medium
A. [32, 1]
B. [100, 32]
C. [32, 100]
D. [1, 32]

Solution

  1. Step 1: Analyze input batch size

    The noise input has batch size 32, so generator outputs 32 fake images.
  2. Step 2: Understand discriminator output shape

    The discriminator outputs a prediction per image, usually shape [batch_size, 1].
  3. Final Answer:

    [32, 1] -> Option A
  4. Quick Check:

    Discriminator output shape = [batch_size, 1] [OK]
Hint: Discriminator outputs one score per input image [OK]
Common Mistakes:
  • Confusing noise dimension with output shape
  • Swapping batch size and feature dimensions
  • Assuming discriminator outputs full image shape
4. You have this error during GAN training: ValueError: Shapes (32, 1) and (64, 1) are incompatible. What is the most likely cause?
medium
A. Discriminator model is missing an output layer
B. Generator output shape is incorrect
C. Mismatch between batch sizes of real and fake data during training
D. Noise vector dimension is too large

Solution

  1. Step 1: Understand the error message

    The error shows two tensors with batch sizes 32 and 64 being compared or combined.
  2. Step 2: Identify cause in GAN training

    Real and fake batches must have the same batch size when computing loss or concatenating.
  3. Final Answer:

    Mismatch between batch sizes of real and fake data during training -> Option C
  4. Quick Check:

    Batch size mismatch causes shape errors [OK]
Hint: Ensure real and fake batches have same size [OK]
Common Mistakes:
  • Ignoring batch size mismatch
  • Blaming generator output shape without checking batch
  • Assuming model layers missing cause shape error
5. You want to improve your simple GAN's training stability. Which change is best to try first?
hard
A. Train discriminator twice as often as generator
B. Increase noise vector dimension to 1000
C. Remove batch normalization layers from generator
D. Use label smoothing on discriminator labels

Solution

  1. Step 1: Understand training stability issues

    GANs often suffer from unstable training causing oscillations or mode collapse.
  2. Step 2: Evaluate common techniques

    Label smoothing (e.g., using 0.9 instead of 1 for real labels) helps discriminator not be too confident, improving stability.
  3. Final Answer:

    Use label smoothing on discriminator labels -> Option D
  4. Quick Check:

    Label smoothing improves GAN training stability [OK]
Hint: Try label smoothing first to stabilize GAN training [OK]
Common Mistakes:
  • Increasing noise dimension too much adds complexity
  • Removing batch norm can hurt generator learning
  • Training discriminator more often can cause imbalance
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard