Generative Adversarial Networks

Generative Adversarial Networks

Master adversarial training and creative AI generation

Interactive generator-discriminator visualization, image synthesis, and hands-on practice

What are Generative Adversarial Networks?

Generative Adversarial Networks (GANs) are a revolutionary class of neural networks that consist of two competing models: a Generator that creates synthetic data and a Discriminator that tries to distinguish real from fake data. Through this adversarial process, the Generator learns to create increasingly realistic outputs, enabling applications in image synthesis, style transfer, data augmentation, and creative AI.

Key Features

  • Adversarial Training: Two networks compete and improve together
  • Unsupervised Learning: Learns from unlabeled data
  • Creative Generation: Produces novel, realistic outputs
  • Latent Space: Maps random noise to meaningful data
  • Nash Equilibrium: Converges to optimal balance
  • Mode Collapse: Challenge to overcome in training

Applications

  • Photorealistic image generation
  • Style transfer and artistic creation
  • Image-to-image translation
  • Data augmentation for training
  • Super-resolution and enhancement
  • Video generation and deepfakes
Generator Network
Discriminator Network
Adversarial Training
Synthetic Data

GAN Variants

Vanilla GAN

Original GAN architecture with fully connected layers.

  • • Simple architecture
  • • Foundation for variants
  • • Training instability

DCGAN

Deep Convolutional GAN for image generation.

  • • Convolutional layers
  • • Stable training
  • • High-quality images

Conditional GAN

Generates data conditioned on labels or attributes.

  • • Controlled generation
  • • Label conditioning
  • • Targeted outputs

CycleGAN

Unpaired image-to-image translation.

  • • Domain transfer
  • • No paired data needed
  • • Style conversion

StyleGAN

High-resolution image synthesis with style control.

  • • Progressive growing
  • • Style mixing
  • • Photorealistic results

WGAN

Wasserstein GAN with improved training stability.

  • • Wasserstein distance
  • • Better convergence
  • • Meaningful loss icJ

GAN Architecture

Generator

Creates fake data from random noise

50%
VS

Discriminator

Distinguishes real from fake data

50%

GAN Training Flow

Generator Network

Input: Random noise vector z ~ N(0, 1)

Architecture: Dense → BatchNorm → ReLU → Dense → BatchNorm → ReLU → Dense → Tanh

Output: Synthetic data G(z)

Goal: Fool the discriminator by generating realistic data

Discriminator Network

Input: Real data x or generated data G(z)

Architecture: Dense → LeakyReLU → Dropout → Dense → LeakyReLU → Dropout → Dense → Sigmoid

Output: Probability D(x) ∈ [0, 1]

Goal: Correctly classify real (1) vs fake (0) data

GAN Training Algorithm:

1
Sample Real Data

Draw m samples from real data distribution: x ~ p_data(x)

2
Generate Fake Data

Sample noise z ~ p_z(z) and generate fake data: G(z)

3
Train Discriminator

Maximize: log D(x) + log(1 - D(G(z)))

4
Train Generator

Minimize: log(1 - D(G(z))) or Maximize: log D(G(z))

5
Repeat

Iterate until convergence or Nash equilibrium is reached

Adjust Network Balance:

Interactive Training Simulation

Watch how the Generator and Discriminator compete and improve through adversarial training!

Training Progress
0.693
Generator Loss
0.693
Discriminator Loss
0
Current ncw
50%
Discriminator Accuracy
Training Dynamics:
  • Early Training: Discriminator dominates, easily spots fake data
  • Mid Training: Generator improves, discriminator accuracy drops to ~50%
  • Convergence: Both networks reach Nash equilibrium
  • Mode Collapse: Generator may produce limited variety
  • Oscillation: Losses may fluctuate without converging

Interactive Image Generation

Generate synthetic images by sampling from the latent space!

Current Generation
Latent Vector (z)

Generated Image Gallery

0
Images Generated
100
Latent Dimensions
85%
Quality Score
92%
Diversity Score

Python Implementation

Simple GAN with TensorFlow/Keras

import tensorflow as tf from tensorflow.keras import layers, models import numpy as np def build_generator(latent_dim): model = models.Sequential([ layers.Dense(256, input_dim=latent_dim), layers.BatchNormalization(), layers.LeakyReLU(alpha=0.2), layers.Dense(512), layers.BatchNormalization(), layers.LeakyReLU(alpha=0.2), layers.Dense(1024), layers.BatchNormalization(), layers.LeakyReLU(alpha=0.2), layers.Dense(784, activation='tanh') ]) return model def build_discriminator(input_shape): model = models.Sequential([ layers.Dense(512, input_dim=input_shape), layers.LeakyReLU(alpha=0.2), layers.Dropout(0.3), layers.Dense(256), layers.LeakyReLU(alpha=0.2), layers.Dropout(0.3), layers.Dense(1, activation='sigmoid') ]) return model latent_dim = 100 generator = build_generator(latent_dim) discriminator = build_discriminator(784) discriminator.compile( optimizer=tf.keras.optimizers.Adam(0.0002, 0.5), loss='binary_crossentropy', metrics=['accuracy'] )

DCGAN for Image Generation

def build_dcgan_generator(latent_dim): model = models.Sequential([ layers.Dense(7 * 7 * 256, input_dim=latent_dim), layers.Reshape((7, 7, 256)), layers.BatchNormalization(), layers.Conv2DTranspose(128, (5, 5), strides=(1, 1), padding='same'), layers.BatchNormalization(), layers.LeakyReLU(alpha=0.2), layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same'), layers.BatchNormalization(), layers.LeakyReLU(alpha=0.2), layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', activation='tanh') ]) return model def build_dcgan_discriminator(img_shape): model = models.Sequential([ layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same', input_shape=img_shape), layers.LeakyReLU(alpha=0.2), layers.Dropout(0.3), layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'), layers.LeakyReLU(alpha=0.2), layers.Dropout(0.3), layers.Flatten(), layers.Dense(1, activation='sigmoid') ]) return model

GAN Training Loop

def train_gan(generator, discriminator, epochs, batch_size, latent_dim): discriminator.trainable = False gan_input = layers.Input(shape=(latent_dim,)) generated_image = generator(gan_input) gan_output = discriminator(generated_image) gan = models.Model(gan_input, gan_output) gan.compile( optimizer=tf.keras.optimizers.Adam(0.0002, 0.5), loss='binary_crossentropy' ) for ncw in range(epochs): real_images = get_real_batch(batch_size) noise = np.random.normal(0, 1, (batch_size, latent_dim)) fake_images = generator.predict(noise) real_labels = np.ones((batch_size, 1)) fake_labels = np.zeros((batch_size, 1)) discriminator.trainable = True d_loss_real = discriminator.train_on_batch(real_images, real_labels) d_loss_fake = discriminator.train_on_batch(fake_images, fake_labels) d_loss = 0.5 * np.add(d_loss_real, d_loss_fake) discriminator.trainable = False noise = np.random.normal(0, 1, (batch_size, latent_dim)) g_loss = gan.train_on_batch(noise, real_labels) if ncw % 100 == 0: print(f'ncw {ncw}, D Loss: {d_loss[0]:.4f}, G Loss: {g_loss:.4f}')

Conditional GAN

def build_conditional_generator(latent_dim, num_classes): noise_input = layers.Input(shape=(latent_dim,)) label_input = layers.Input(shape=(1,)) label_embedding = layers.Embedding(num_classes, 50)(label_input) label_embedding = layers.Flatten()(label_embedding) merged_input = layers.Concatenate()([noise_input, label_embedding]) x = layers.Dense(256)(merged_input) x = layers.BatchNormalization()(x) x = layers.LeakyReLU(alpha=0.2)(x) x = layers.Dense(512)(x) x = layers.BatchNormalization()(x) x = layers.LeakyReLU(alpha=0.2)(x) output = layers.Dense(784, activation='tanh')(x) model = models.Model([noise_input, label_input], output) return model