GANs for Computer Vision: Generator, Discriminator, DCGAN, CGAN, WGAN, CycleGAN
784 words
4 min read
Visual companion
Python
Type and operator map
Python Week 1: the first filter for runtime behavior
View
Revision summary
What this note is really saying
Short form
# GANs for Computer Vision: Generator, Discriminator, DCGAN, CGAN, WGAN, CycleGAN ## 🎯 Learning Objectives - Understand the GAN framework for image generation - Implement DCGAN with convolutional layers - Generate conditional images with CGAN - Stabilize training with Wasserstein GAN (WGAN) - Apply CycleGAN for unp...

GANs for Computer Vision: Generator, Discriminator, DCGAN, CGAN, WGAN, CycleGAN
🎯 Learning Objectives
- Understand the GAN framework for image generation
- Implement DCGAN with convolutional layers
- Generate conditional images with CGAN
- Stabilize training with Wasserstein GAN (WGAN)
- Apply CycleGAN for unpaired image-to-image translation
📋 Prerequisites
- CNN Fundamentals (Week 1): Convolution, transposed convolution
- Transfer Learning (Week 3): Feature extraction concepts
- Object Detection (Week 4): Feature map understanding
1. 📖 Core Content
1.1 GAN Framework for Images
GANs pit two networks against each other:
- Generator: Creates fake images from random noise
- Discriminator: Distinguishes real from fake images (Diagram)
1.2 DCGAN Architecture
DCGAN (Radford et al., 2016) was the first to make GANs work consistently with CNNs:
Generator (noise → 64×64 image):
python# runnable import torch.nn as nn class DCGANGenerator(nn.Module): def __init__(self, latent_dim=100, feature_dim=64, img_channels=3): super().__init__() self.main = nn.Sequential( # Input: latent_dim x 1 x 1 nn.ConvTranspose2d(latent_dim, feature_dim*8, 4, 1, 0, bias=False), nn.BatchNorm2d(feature_dim*8), nn.ReLU(True), # 4x4 nn.ConvTranspose2d(feature_dim*8, feature_dim*4, 4, 2, 1, bias=False), nn.BatchNorm2d(feature_dim*4), nn.ReLU(True), # 8x8 nn.ConvTranspose2d(feature_dim*4, feature_dim*2, 4, 2, 1, bias=False), nn.BatchNorm2d(feature_dim*2), nn.ReLU(True), # 16x16 nn.ConvTranspose2d(feature_dim*2, feature_dim, 4, 2, 1, bias=False), nn.BatchNorm2d(feature_dim), nn.ReLU(True), # 32x32 nn.ConvTranspose2d(feature_dim, img_channels, 4, 2, 1, bias=False), nn.Tanh() # 64x64 ) def forward(self, z): return self.main(z.view(z.size(0), -1, 1, 1))
Discriminator (64×64 image → real/fake):
python# runnable class DCGANDiscriminator(nn.Module): def __init__(self, feature_dim=64, img_channels=3): super().__init__() self.main = nn.Sequential( nn.Conv2d(img_channels, feature_dim, 4, 2, 1, bias=False), nn.LeakyReLU(0.2, inplace=True), nn.Conv2d(feature_dim, feature_dim*2, 4, 2, 1, bias=False), nn.BatchNorm2d(feature_dim*2), nn.LeakyReLU(0.2, inplace=True), nn.Conv2d(feature_dim*2, feature_dim*4, 4, 2, 1, bias=False), nn.BatchNorm2d(feature_dim*4), nn.LeakyReLU(0.2, inplace=True), nn.Conv2d(feature_dim*4, feature_dim*8, 4, 2, 1, bias=False), nn.BatchNorm2d(feature_dim*8), nn.LeakyReLU(0.2, inplace=True), nn.Conv2d(feature_dim*8, 1, 4, 1, 0, bias=False), nn.Sigmoid() ) def forward(self, x): return self.main(x).view(-1)
1.3 Training Tips for GANs
| Problem | Symptom | Fix |
|---|---|---|
| Mode collapse | Generator produces same image | Label smoothing, minibatch discrimination |
| Non-convergence | Loss oscillates | WGAN loss, gradient penalty |
| Blurry images | Low quality | Increase capacity, feature matching |
| Discriminator too strong | D loss ≈ 0 always | Reduce D capacity, add dropout |
1.4 WGAN-GP (Wasserstein GAN with Gradient Penalty)
WGAN replaces the binary discriminator with a critic that outputs a score, and uses the Wasserstein distance:
python# runnable def gradient_penalty(critic, real, fake, device): """WGAN-GP gradient penalty.""" batch_size = real.size(0) # Random interpolation epsilon = torch.rand(batch_size, 1, 1, 1, device=device) interpolated = epsilon * real + (1 - epsilon) * fake interpolated.requires_grad_(True) # Critic score for interpolated images d_interpolated = critic(interpolated) # Gradients gradients = torch.autograd.grad( outputs=d_interpolated, inputs=interpolated, grad_outputs=torch.ones_like(d_interpolated), create_graph=True, retain_graph=True )[0] # GP loss: (||grad|| - 1)^2 gradients = gradients.view(batch_size, -1) grad_norm = gradients.norm(2, dim=1) gp = ((grad_norm - 1) ** 2).mean() return gp
1.5 Why This Matters
GANs revolutionized computer vision: image generation (StyleGAN), super-resolution (SRGAN), image-to-image translation (Pix2Pix), and data augmentation for training other models.
2. 📐 Key Formulas / Concepts
| Variant | Loss Function | Stability | Quality |
|---|---|---|---|
| Vanilla GAN | min_G max_D E[log D] + E[log(1-D(G))] | Low | Moderate |
| DCGAN | Same + architectural constraints | Medium | Good |
| WGAN | min_G max_D E[D(x)] - E[D(G(z))], Lipschitz | High | Good |
| WGAN-GP | WGAN + gradient penalty | Very high | Excellent |
| LSGAN | min E[(D-1)²] + E[D(G)²] | High | Good |
3. ⚠️ Common Pitfalls
Pitfall 1: Using Sigmoid at the End of the Generator
Mistake: Using Sigmoid activation at generator output for all image types.
Why: Sigmoid bounds outputs to [0, 1]. If your image data isn't normalized to [0, 1], this limits expressiveness.
Fix: Use Tanh ([-1, 1]) for the generator and normalize images to [-1, 1]. Tanh produces sharper images because gradients don't saturate as easily as Sigmoid.
Pitfall 2: Balancing Generator and Discriminator
Mistake: Using identical learning rates for both networks.
Why: The two-player game requires careful balancing. A stronger discriminator kills gradient flow; a stronger generator fools too easily.
Fix: Use different LR (2e-4 for G, 1e-4 for D), update G more frequently (5 G steps per D step), or use different optimizer betas.
4. 📝 Practice Questions
Q1: Your GAN generates the same cherry-red sports car for every noise input. What's wrong and how do you fix it?Problem: Mode collapse — the generator found one plausible image that fools the discriminator and sticks to it.Fixes:
- Minibatch discrimination: Add feature statistics across the batch so the discriminator can detect when the generator produces uniform outputs.
- Label smoothing: Use soft labels (0.9/0.1 instead of 1/0) to prevent the discriminator from being overconfident.
- WGAN loss: Wasserstein loss doesn't saturate like binary cross-entropy, making mode collapse less likely.
- Increase latent dimension: More noise dimensions give the generator more room to diversify.
- Add noise to discriminator inputs: Inject Gaussian noise to force the discriminator to tolerate variation.
5. 🔗 Cross-References
- Previous: Segmentation (Week 5)
- Next: Vision Transformers (Week 7)
- Related: GenAI GAN notes
- External: Radford et al., "Unsupervised Representation Learning with DCGAN" (2016) Join Discord PreviousSegmentationNextData Augmentation