Generative Adversarial Networks
- Goodfellow et al. (2014) introduced GANs as a minimax two-player game between generator and discriminator
- Produced the first photorealistic synthetic face images (ProGAN 2018, StyleGAN 2019)
- Training instability (mode collapse, vanishing gradients) drove years of research in GAN stabilization
A GAN trains two networks in opposition: the generator creates fake samples trying to fool a discriminator; the discriminator tries to distinguish real from fake. The generator improves as the discriminator improves, reaching a Nash equilibrium where fakes are indistinguishable from real samples.
- Diffusion models have largely replaced GANs for image generation due to more stable training
- The adversarial training idea lives on in adversarial robustness, domain adaptation, and RLHF (discriminator = reward model)
- Progressive growing (ProGAN) connects to curriculum learning in neural network training
- State the original GAN minimax objective and explain why it is a two-player zero-sum game with no monotone Lyapunov function.
- Derive the optimal discriminator D*(x) = p_data(x) / (p_data(x) + p_g(x)) from the value function and substitute back to recover 2 * JSD(p_data || p_g) - log 4.
- Explain why Jensen-Shannon divergence has zero gradient when the supports of p_data and p_g do not overlap, motivating the move to Wasserstein distance.
- State the Kantorovich-Rubinstein duality for the Earth Mover distance and explain how it turns W into a sup over 1-Lipschitz critics.
- Compare weight clipping (WGAN) with the gradient penalty (WGAN-GP), and write the gradient-penalty regularizer.
- Sketch the architectural progression DCGAN -> Progressive GAN -> StyleGAN/StyleGAN2 -> BigGAN, and name the key trick at each step.
- Explain mode collapse, how to detect it, and why FID is the standard evaluation metric (Heusel 2017).
- Explain why diffusion displaced GANs as the state of the art for image generation around 2020-2022.
TL;DR
A GAN trains two networks against each other: a generator that maps noise to a sample, and a discriminator that classifies real vs. fake. The original objective is the minimax game [1]
With fixed, the optimal discriminator is , and substituting it back gives , so the global optimum is at . Training is unstable because Jensen-Shannon goes flat (zero gradient) when the supports of and do not overlap. WGAN [4] swaps JSD for the Earth Mover (Wasserstein) distance, which has well-defined gradients almost everywhere; WGAN-GP [5] replaces weight clipping with a gradient penalty. DCGAN [3], Progressive GAN [6], and StyleGAN/StyleGAN2 [7][8] drove image quality from 64x64 toys to photorealistic 1024x1024 faces. Conditional GAN [2] conditions both networks on a label, and CycleGAN [10] handles unpaired domain translation. GANs were SOTA for image generation 2015-2020 and were largely displaced by diffusion [12] after 2020 because diffusion has a stable, single-network training objective.
Intuition
Think of a GAN as a counterfeiter and a detective. The counterfeiter (generator) prints fake money; the detective (discriminator) sees a stack of bills, half real and half fake, and tries to label each. Each round, the detective gets a little better at spotting fakes, and the counterfeiter gets a little better at making fakes that the detective cannot distinguish from real. At equilibrium, the detective is reduced to a coin flip and the counterfeiter is producing bills indistinguishable from the central bank’s.
The math says exactly this. Define the value function
The discriminator wants to maximize (high on real samples, low on fakes). The generator wants to minimize (push up). The training procedure alternates a few discriminator gradient ascent steps with one generator gradient descent step. Unlike an autoencoder there is no reconstruction target; the only signal the generator ever sees is the discriminator’s gradient.
In supervised learning the loss is a fixed function of the parameters, so the gradient field is a vector field on parameter space, and gradient descent monotonically decreases the loss. In a GAN the discriminator’s loss surface depends on the generator and vice versa: both networks are climbing a moving target. There is no scalar Lyapunov function whose value monotonically decreases over training, so loss curves are not interpretable in the usual way. The training is a saddle-point optimization, and convergence is only guaranteed in restrictive theoretical settings.
The practical consequence is that GAN training requires careful tricks (learning-rate schedules, alternating step counts, batch normalization choices, gradient clipping, spectral normalization). Loss curves look noisy and oscillating even on a converging run; the only reliable health signal is sample quality and FID [11].
The optimal discriminator and the JSD interpretation
Deriving D*(x) and the JSD form (interview gold)
Setup
Fix the generator , so is the implied distribution of for . Treat the value function as a functional of alone:
Apply the change-of-variables to the second integral so both are integrals over :
Step 1: maximize pointwise
For each fixed , the integrand is with , , and . Differentiate with respect to and set to zero:
Therefore the optimal discriminator at any point where is
This is intuitive: the Bayes-optimal classifier for “real vs. fake” mixed in a 50/50 prior is the posterior probability of the “real” class, which is exactly the ratio above.
Step 2: substitute back into
Plug into :
Add and subtract in each term to massage the integrand:
Let be the mid-distribution. Then
The Jensen-Shannon divergence is by definition
so
Step 3: read off the global optimum
JSD is non-negative, with iff almost everywhere. Therefore the generator’s objective is minimized at , where . In words: at the global optimum, has matched the data distribution exactly, and outputs everywhere, the random-guess baseline.
Step 4: why this fails in practice
The trouble is that is constant (equal to ) whenever the supports of and do not overlap on a set of positive measure. For early training, is concentrated on a low-dimensional manifold disjoint from the data manifold, so JSD is at the ceiling and its gradient with respect to is zero. The discriminator is too good, and the generator gets no learning signal: the loss is high, the gradient is zero, training stalls. This is the vanishing-gradient failure mode that motivated Wasserstein GAN [4].
Goodfellow’s original paper proposed a practical fix even before WGAN: instead of the generator minimizing , have it maximize . The two are equivalent at the saddle point but the non-saturating form has much larger gradients when is small (early training), so the generator is not stuck. Most production code uses this non-saturating loss, even though textbooks present the original minimax form for the JSD derivation [1][13].
Mode collapse
A GAN can find a degenerate equilibrium where the generator outputs a small set of points (in the worst case, one point) that fools the current discriminator. The discriminator then adapts, the generator jumps to a different small set, and so on. The samples are sharp and pass the discriminator but the diversity of the data is lost.
Mode collapse is hard to detect from training loss alone (loss can look fine). Standard tooling:
- Inception Score (IS): use a fixed pretrained classifier and compute . Higher means each sample is confidently classified and the marginal label distribution is uniform. Mode-collapsed generators have low IS because the marginal collapses.
- FID (Frechet Inception Distance) [11]: extract features from a pretrained Inception-v3, fit a Gaussian to real and fake feature distributions, and compute . Lower is better. FID is the standard metric for GAN evaluation since 2017 and tracks both quality and diversity.
- Visual diversity audit: sample a large batch, cluster, and check that the cluster count and per-cluster spread match the data. A 10-mode mixture should give roughly 10 generator modes.
Wasserstein GAN: from JSD to Earth Mover
Wasserstein distance and Kantorovich-Rubinstein duality
The Earth Mover distance
The Wasserstein-1 (Earth Mover) distance between two distributions on is
where is the set of all joint distributions with marginals and . Intuitively, is a transport plan that moves probability mass from to , and is the minimum total work (mass times distance) needed to morph into .
Unlike JSD, is well-defined and continuous even when the supports do not overlap. If is a delta at and is a delta at , then for any (a constant cliff), but (a smooth slope). The smooth slope is exactly the gradient signal that GAN training needs.
Kantorovich-Rubinstein duality
The infimum over transport plans is hard to compute directly. The KR duality theorem rewrites it as a supremum over 1-Lipschitz functions :
Here is the Lipschitz constant of , i.e. for all . The 1-Lipschitz constraint is what couples the two expectations: an unconstrained could just diverge.
From duality to the WGAN objective
Replace the JSD-style discriminator with a critic (a neural net with parameters ) that we constrain to be 1-Lipschitz. The training objective becomes
The critic does not output a probability; it outputs a real-valued score. The generator gets a clean gradient as long as is approximately 1-Lipschitz, even when the supports of and are disjoint.
Enforcing the Lipschitz constraint: clipping vs. gradient penalty
Original WGAN [4] enforces the constraint by weight clipping: after each critic update, project all weights into a box with a small constant (e.g. 0.01). This is crude. The clipping value has to be tuned, the clipped weights tend to saturate at the boundary (so the critic lives in a narrow function class), and the resulting Lipschitz constant is implicit and not exactly 1.
WGAN-GP [5] replaces clipping with a gradient penalty: add a soft penalty that pushes the critic’s gradient norm toward 1 on points sampled along straight lines between real and fake samples. The full objective is
with for and typical . The penalty is a two-sided penalty toward unit gradient norm: an exact 1-Lipschitz function has unit gradient norm a.e., and the squared term penalizes deviations on either side of , making that the network’s preferred operating point. Empirically WGAN-GP trains more stably than WGAN clipping across many architectures, and it scales to larger models without retuning .
What the critic actually estimates
By KR duality the critic’s value approaches from below as the critic’s capacity grows, so the critic loss curve does correlate with . This is unlike the original GAN where the discriminator’s loss is uninformative as a quality metric. WGAN gives a useful health signal during training.
Architectural progression
A short history of the empirical breakthroughs.
- 2014Original GAN (Goodfellow et al.)breakthrough
Two MLPs, minimax JSD objective, MNIST and CIFAR. Showed the idea works at all; samples were small and noisy.
- 2014Conditional GAN (Mirza & Osindero)method
Concatenate a label y to both G and D inputs. The same objective, but now G samples class-conditional images.
- 2015DCGAN (Radford, Metz, Chintala)architecture
Replace MLPs with strided / fractionally-strided convs, add BatchNorm, drop pooling. First recipe for stable image GAN training. 64x64 bedrooms, faces.
- 2017WGAN / WGAN-GP (Arjovsky 2017, Gulrajani 2017)method
Earth Mover loss with weight clipping or a gradient penalty. Stable training across many architectures, useful loss curves.
- 2017Progressive GAN (Karras et al.)architecture
Grow generator and discriminator from 4x4 to 1024x1024 by adding layers during training. First photorealistic GAN faces (CelebA-HQ).
- 2017CycleGAN (Zhu et al.)application
Two GANs and a cycle-consistency loss let G learn an unpaired domain translation: horses to zebras, summer to winter, photo to Monet.
- 2018BigGAN (Brock, Donahue, Simonyan)architecture
Scale up class-conditional GANs on ImageNet with truncation, orthogonal regularization, and large batches. State-of-the-art FID at scale.
- 2019StyleGAN / StyleGAN2 (Karras et al.)architecture
Style-based generator: a learned mapping network produces per-layer style codes via AdaIN. StyleGAN2 fixes blob artifacts with weight demodulation. Photorealistic 1024x1024 faces, the high-water mark of GAN image quality.
- 2020DDPM (Ho, Jain, Abbeel)displaced
Denoising Diffusion Probabilistic Models: a single network, stable likelihood-based training, mode-covering. Within a year, diffusion overtakes GANs on ImageNet FID and never gives the lead back.
StyleGAN in one paragraph
StyleGAN [7] redesigns the generator: instead of feeding into the first layer, a fully-connected mapping network transforms into an intermediate latent , and at each resolution a learned affine projects to per-channel that modulate the activations via Adaptive Instance Normalization. The first layer takes a learned constant tensor, not noise. Stochastic per-layer noise is added separately for fine details. The result is a hierarchy where coarse layers control pose, middle layers control hair/face shape, and fine layers control texture and color. StyleGAN2 [8] replaces AdaIN with weight demodulation (rescaling conv weights instead of activations), eliminating the characteristic “droplet” artifacts. StyleGAN2 on FFHQ-1024 was the visual benchmark the field chased for years.
Conditional GAN and CycleGAN
Conditional GAN [2] simply concatenates a one-hot label (or any conditioning signal) to both ‘s input and ‘s input. The objective is unchanged; only the inputs grow. This is how class-conditional sampling and text-conditional GANs work.
CycleGAN [10] tackles unpaired domain translation: you have a stack of horse photos and a stack of zebra photos, but no aligned pairs. Train two generators and along with two discriminators, plus a cycle-consistency loss that says you should be able to round-trip through both translators back to the original. This forces and to be approximate inverses, which in turn prevents either from collapsing onto a degenerate mapping.
Comparison
| Variant | Objective | D / critic constraint | Training stability | Image quality (FID, lower is better) | Year |
|---|---|---|---|---|---|
| Original GAN | minimax JSD (2 * JSD - log 4) | D outputs prob. in [0, 1] via sigmoid | unstable; mode collapse common; loss uninformative | ~50+ on small datasets | 2014 |
| DCGAN | same as GAN, non-saturating G loss | sigmoid + BatchNorm, strided convs | much better than vanilla; still tricky on hard data | ~30 on LSUN bedrooms 64x64 | 2015 |
| WGAN (clip) | Earth Mover via KR duality | 1-Lipschitz via weight clipping | stable; loss correlates with W; slow critic convergence | similar to DCGAN, more reliable | 2017 |
| WGAN-GP | Earth Mover with gradient penalty | 1-Lipschitz via grad-norm penalty (lambda ~ 10) | most stable across architectures | beats WGAN clip; standard GAN baseline | 2017 |
| Progressive GAN | WGAN-GP loss | gradient penalty | stable up to 1024x1024 via progressive growing | photorealistic CelebA-HQ; FID under 10 | 2017 |
| StyleGAN2 | non-saturating GAN with R1 regularizer | R1 grad penalty on real samples | stable, the empirical state of the art for GANs | FID ~3 on FFHQ-1024; visual peak of GANs | 2020 |
Implementations
A canonical DCGAN sketch in PyTorch and the Keras equivalent. The architecture is small enough to read in one screen but large enough to actually train on 64x64 images.
import torch
import torch.nn as nn
import torch.nn.functional as F
NZ = 100 # latent dim
NGF = 64 # generator feature multiplier
NDF = 64 # discriminator feature multiplier
NC = 3 # output channels (RGB)
class Generator(nn.Module):
"""DCGAN generator: noise -> 64x64 RGB image via fractionally-strided convs."""
def __init__(self) -> None:
super().__init__()
self.net = nn.Sequential(
# 1x1 -> 4x4
nn.ConvTranspose2d(NZ, NGF * 8, 4, 1, 0, bias=False),
nn.BatchNorm2d(NGF * 8),
nn.ReLU(True),
# 4x4 -> 8x8
nn.ConvTranspose2d(NGF * 8, NGF * 4, 4, 2, 1, bias=False),
nn.BatchNorm2d(NGF * 4),
nn.ReLU(True),
# 8x8 -> 16x16
nn.ConvTranspose2d(NGF * 4, NGF * 2, 4, 2, 1, bias=False),
nn.BatchNorm2d(NGF * 2),
nn.ReLU(True),
# 16x16 -> 32x32
nn.ConvTranspose2d(NGF * 2, NGF, 4, 2, 1, bias=False),
nn.BatchNorm2d(NGF),
nn.ReLU(True),
# 32x32 -> 64x64
nn.ConvTranspose2d(NGF, NC, 4, 2, 1, bias=False),
nn.Tanh() # outputs in [-1, 1]
)
def forward(self, z):
return self.net(z.view(z.size(0), NZ, 1, 1))
class Discriminator(nn.Module):
"""DCGAN discriminator: 64x64 RGB -> scalar prob via strided convs."""
def __init__(self) -> None:
super().__init__()
self.net = nn.Sequential(
nn.Conv2d(NC, NDF, 4, 2, 1, bias=False),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(NDF, NDF * 2, 4, 2, 1, bias=False),
nn.BatchNorm2d(NDF * 2),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(NDF * 2, NDF * 4, 4, 2, 1, bias=False),
nn.BatchNorm2d(NDF * 4),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(NDF * 4, NDF * 8, 4, 2, 1, bias=False),
nn.BatchNorm2d(NDF * 8),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(NDF * 8, 1, 4, 1, 0, bias=False),
nn.Sigmoid()
)
def forward(self, x):
return self.net(x).view(-1)
# Training loop sketch (non-saturating G loss).
# G, D = Generator().to(dev), Discriminator().to(dev)
# optG = torch.optim.Adam(G.parameters(), lr=2e-4, betas=(0.5, 0.999))
# optD = torch.optim.Adam(D.parameters(), lr=2e-4, betas=(0.5, 0.999))
# bce = nn.BCELoss()
# for x, _ in loader:
# x = x.to(dev)
# bs = x.size(0)
# # ---- D step ----
# z = torch.randn(bs, NZ, device=dev)
# fake = G(z).detach()
# loss_d = bce(D(x), torch.ones(bs, device=dev)) + bce(D(fake), torch.zeros(bs, device=dev))
# optD.zero_grad(); loss_d.backward(); optD.step()
# # ---- G step (non-saturating: maximize log D(G(z)) ) ----
# z = torch.randn(bs, NZ, device=dev)
# loss_g = bce(D(G(z)), torch.ones(bs, device=dev))
# optG.zero_grad(); loss_g.backward(); optG.step()Illustrative training curves
GAN training is too heavy for the in-browser Pyodide runner used elsewhere in this site (a real DCGAN run is on the order of GPU-hours, far beyond a WebAssembly Python interpreter). The plot below shows illustrative generator and critic loss curves from a typical WGAN-GP training run on CIFAR-10. The numbers are hard-coded for visualization; treat them as a sketch of what the loss curves look like, not as data from an actual run.
A real GAN training log shows the discriminator loss bouncing around a small range while the generator loss slowly trends down, with occasional excursions when the two networks “trade” advantage. The critic loss in WGAN-GP correlates monotonically with the Wasserstein distance, which is one of the reasons WGAN-GP is easier to debug than vanilla GAN. The numbers in the plot are picked to illustrate this qualitative shape.
Real-world uses
| Domain | Use | Notes |
|---|---|---|
| Image generation | unconditional sample synthesis (faces, scenes, art) | StyleGAN2 / StyleGAN3 was the visual peak; on FFHQ-1024 GANs still produce sharper textures than equally-sized diffusion models, though diffusion has caught up. |
| Super-resolution | SRGAN, ESRGAN: 4x upscaling with perceptual + adversarial loss | Adversarial loss pushes outputs toward the manifold of real high-resolution images, fixing the over-smooth artifact of pure L2. |
| Image-to-image translation | pix2pix (paired), CycleGAN (unpaired): style transfer, season swap, photo-to-sketch | Conditional GAN with U-Net generator and PatchGAN discriminator; CycleGAN extends to unpaired data via cycle consistency. |
| Data augmentation | synthesize labeled training data for downstream classifiers | Works well in narrow domains (medical X-rays, faces) where collecting real data is expensive; gains on broad benchmarks are mixed. |
| Inpainting / editing | fill in masked regions of an image; latent-space editing of StyleGAN faces | StyleGAN`s W and W+ spaces support semantic edits (age, smile, gender) by linear directions found via supervised attribute classifiers. |
Why diffusion replaced GANs
By 2022 most state-of-the-art image generation systems were diffusion-based, not GAN-based. The reasons are structural, not just incremental:
- Single-network training. Diffusion trains one network with a stable per-step regression objective (), with no adversary to balance. Loss curves are interpretable and debuggable like ordinary supervised learning.
- Mode coverage by construction. A diffusion model is trained to denoise samples from the full data distribution, so it cannot collapse to a small subset of modes. GANs need explicit regularization (mini-batch discrimination, spectral norm) to avoid collapse, and even then it is a recurring problem.
- Likelihood-based training. Diffusion has a tractable variational lower bound on log-likelihood and a clean theoretical grounding in stochastic differential equations. GANs do not have a likelihood; FID is the only widely-trusted metric.
- Easier conditioning. Classifier-free guidance gives clean knobs for text-to-image and class-conditional generation; cGANs need re-architecting to support new conditioning modalities.
- Trade-off: diffusion is slow at sample time (10-50+ network passes per sample). GANs sample in one forward pass. For latency-sensitive applications, distillation of diffusion into one-step models or returning to a GAN backbone is still the right call.
GANs are not dead. They are still the right choice when you need fast sampling, when training compute is severely constrained, or when you need the precise control over latent space that StyleGAN’s W+ provides. They are no longer the default for high-quality image generation.
Pitfalls
The discriminator loss can oscillate or plateau at any value while training is going fine, and the generator loss can rise even as samples improve. The only reliable health signals for vanilla GANs are visual sample quality and FID. WGAN-GP’s critic loss correlates with and is more useful, but still not a single number to watch.
A mode-collapsed generator produces a small number of distinct outputs, each individually sharp and convincing. Loss can look fine. Always sample a large batch, cluster, and audit per-cluster diversity; FID catches it because the marginal distribution is wrong.
Adam with (not 0.9) at learning rate is the DCGAN default. BigGAN [9] showed that scaling batch size from 256 to 2048 dropped FID dramatically, and that the same model at small batch could be unstable. Tune these before changing the architecture.
When writing GAN math in prose (e.g. “the gradient norm is at most 1”), use words rather than the literal less-than-or-equal sequence. The MDX parser interprets the angle bracket as the start of a JSX tag and crashes the build. Inside $...$ math or fenced code blocks the symbol is fine.
Pop quiz
- 1. Fixing the generator G, the optimal discriminator D*(x) is:
- 2. Substituting D*(x) back into V(D, G) yields:
- 3. Why is the JSD problematic when supports of p_data and p_g do not overlap?
- 4. WGAN-GP enforces the 1-Lipschitz constraint on the critic by:
- 5. What does Frechet Inception Distance measure?
Interview Q&A
Why is the original GAN objective a minimax game and not a single loss?onsite
The objective is
The two networks have opposing goals: wants large (correctly classify real and fake), wants small (push up). There is no single scalar loss whose gradient minimizes both, because making better automatically makes the data-vs-fake classification harder for .
The optimization is a saddle-point search: at equilibrium, neither player can improve unilaterally. Unlike supervised learning, there is no Lyapunov function (a scalar that monotonically decreases), so loss curves do not directly indicate progress and convergence is not guaranteed by gradient descent. Practical recipes, alternating step counts, learning-rate decay, spectral normalization, gradient penalties, exist precisely because the saddle-point is fragile.
This shape, two networks playing against each other, is what makes GANs both powerful (no need for a likelihood; you only need to be able to discriminate) and unstable (everything in the loss landscape is moving simultaneously).
Derive the optimal discriminator D*(x) = p_data(x) / (p_data(x) + p_g(x)).research
Treat as a functional of for fixed , and use a change of variables on the second term so both expectations are over :
For each fixed where , maximize the integrand over with :
Therefore
The interpretation is the Bayes-optimal “real vs. fake” classifier for an equal-prior mixture, i.e. the posterior probability of the real class. Substituting back into and adding/subtracting in each integrand gives
which equals by the definition of Jensen-Shannon divergence. The global optimum is at where JSD = 0, , and (the random-guess baseline) [1].
Why does the JSD interpretation become problematic, and how does Wasserstein GAN fix it?onsite
When and have disjoint supports (which is the typical situation early in training, since lives on a low-dimensional generator manifold), for all such configurations. The function is constant on a large open set of generator parameters, so and the generator has no gradient signal even though we are far from the optimum. Empirically, this manifests as the discriminator becoming “too good” early in training and the generator gradients vanishing.
The Earth Mover (Wasserstein-1) distance fixes this:
If is a delta at and is a delta at , then even when (smooth slope), whereas (constant cliff). The smooth slope is exactly the gradient signal the generator needs.
The Kantorovich-Rubinstein dual rewrites as a sup over 1-Lipschitz functions:
so we can train a critic to estimate and use its gradient to update . Original WGAN [4] enforces the Lipschitz constraint by weight clipping; WGAN-GP [5] uses a gradient penalty , which trains more stably and gives a critic loss that is monotonically related to .
Derive the WGAN-GP gradient penalty and explain why it works.research
The Kantorovich-Rubinstein dual of the Earth Mover distance is
We want to optimize over parameterized as a neural net, but neural nets are not naturally Lipschitz. Original WGAN enforces the constraint by clipping all weights into , which is crude (it shrinks the function class severely and saturates at the boundary).
WGAN-GP [5] observes that an exact 1-Lipschitz function on has almost everywhere along the optimal transport plan. So instead of constraining weights, penalize departures from unit gradient norm:
The penalty is evaluated at for and a real paired with a generated . This samples points along straight lines between real and fake batches, which is where the gradient norm constraint matters most for the dual problem (the transport plan moves mass along these lines).
Why this works:
- Soft constraint preserves capacity. Unlike clipping, the network can use its full weight space; the penalty just pushes the gradient norm toward 1.
- Two-sided penalty hits unit norm. The squared form penalizes both larger-than-1 (Lipschitz violation) and smaller-than-1 (under-utilization) gradient norms. An exact 1-Lipschitz function has unit gradient norm a.e.
- Empirically stable across architectures. The original WGAN clipping was sensitive to the clip value and to architecture choices (BatchNorm interacted badly). The gradient penalty needs no per-architecture tuning; works essentially everywhere.
- Critic loss correlates with . Because the network approximates a 1-Lipschitz function, the inner expectation is a tight estimate of , so the critic loss curve is a useful debugging signal.
A subtle point: because BatchNorm makes the loss dependent on other examples in the batch, WGAN-GP disables BatchNorm in the critic and uses LayerNorm or no normalization there.
What is Frechet Inception Distance, and why is it the standard GAN metric?onsite
FID [11] compares the distribution of real images to the distribution of generated images in the feature space of a fixed pretrained Inception-v3 network. Concretely:
- Run a large batch of real images and a large batch of generated images through the Inception-v3 pool-3 layer to get 2048-dim feature vectors.
- Fit a Gaussian to each set of features: for real, for generated.
- Report the closed-form 2-Wasserstein distance (also called Frechet distance) between the two Gaussians:
Lower is better; FID = 0 means the feature distributions are identical Gaussians.
Why it is the standard:
- Captures quality and diversity. A mode-collapsed generator has the wrong (typically degenerate or compressed), so FID rises even if individual samples look sharp. Inception Score, by contrast, can be high for a few cherry-picked classes and miss collapse.
- Stable across model checkpoints. A few thousand samples are enough to estimate FID well; the pretrained Inception is fixed across all experiments so numbers are comparable.
- Strongly correlated with human judgments of quality on natural images.
Caveats:
- FID depends on the pretrained Inception, which was trained on ImageNet. On out-of-distribution domains (medical images, art, faces) the comparison is biased; FID is most meaningful when both real and fake look like ImageNet content.
- FID is biased downward as the sample size grows; you need to use the same large sample size (typically 50k) when comparing across papers.
- For text-conditional generation, FID against the conditioned subset (CLIP-FID, FID-CLIP) is more meaningful than overall FID.
In practice, FID is reported alongside Inception Score and (for class-conditional models) per-class FID, and it has been the headline metric for GAN comparisons since 2017.
A 2-3 day project that takes a GAN from textbook to working samples:
- Implement the DCGAN above on CIFAR-10 at 32x32 (drop the last upsampling layer in and the first downsampling layer in ). Train for 50k generator steps with Adam(lr=2e-4, betas=(0.5, 0.999)). Save sample grids every 1000 steps. Expect FID around 35-50.
- Switch the loss to WGAN-GP. Disable BatchNorm in the critic (keep it in ), set , do 5 critic steps per generator step. Expect FID to drop and training stability to improve.
- Add conditional generation: concatenate a one-hot class label to the noise input for and to the input feature map for (replicated spatially). Sample class-conditioned grids and check that horses look like horses.
- Write an FID evaluation script using a pretrained Inception-v3. Report FID after every 5000 steps; this is your training health signal.
- Stretch: implement spectral normalization in the critic and compare against gradient penalty on training stability and FID.
- Stretch: set up StyleGAN2 (use the official NVIDIA reference repo) on FFHQ-256. Reproduce one of the truncation-tradeoff plots from the paper.
References
- Goodfellow, I., Pouget-Abadie, J., Mirza, M., Xu, B., Warde-Farley, D., Ozair, S., Courville, A., and Bengio, Y. (2014). Generative Adversarial Nets. NeurIPS 2014 (arXiv preprint 2014). arXiv:1406.2661
- Mirza, M. and Osindero, S. (2014). Conditional Generative Adversarial Nets. arXiv preprint. arXiv:1411.1784
- Radford, A., Metz, L., and Chintala, S. (2015). Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks. ICLR 2016 (arXiv preprint 2015). arXiv:1511.06434
- Arjovsky, M., Chintala, S., and Bottou, L. (2017). Wasserstein GAN. ICML 2017. arXiv:1701.07875
- Gulrajani, I., Ahmed, F., Arjovsky, M., Dumoulin, V., and Courville, A. (2017). Improved Training of Wasserstein GANs. NeurIPS 2017. arXiv:1704.00028
- Karras, T., Aila, T., Laine, S., and Lehtinen, J. (2017). Progressive Growing of GANs for Improved Quality, Stability, and Variation. ICLR 2018 (arXiv preprint 2017). arXiv:1710.10196
- Karras, T., Laine, S., and Aila, T. (2019). A Style-Based Generator Architecture for Generative Adversarial Networks. CVPR 2019. arXiv:1812.04948
- Karras, T., Laine, S., Aittala, M., Hellsten, J., Lehtinen, J., and Aila, T. (2020). Analyzing and Improving the Image Quality of StyleGAN. CVPR 2020. arXiv:1912.04958
- Brock, A., Donahue, J., and Simonyan, K. (2018). Large Scale GAN Training for High Fidelity Natural Image Synthesis. ICLR 2019 (arXiv preprint 2018). arXiv:1809.11096
- Zhu, J.-Y., Park, T., Isola, P., and Efros, A. A. (2017). Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks. ICCV 2017. arXiv:1703.10593
- Heusel, M., Ramsauer, H., Unterthiner, T., Nessler, B., and Hochreiter, S. (2017). GANs Trained by a Two Time-Scale Update Rule Converge to a Local Nash Equilibrium. NeurIPS 2017. arXiv:1706.08500
- Ho, J., Jain, A., and Abbeel, P. (2020). Denoising Diffusion Probabilistic Models. NeurIPS 2020. arXiv:2006.11239
- Goodfellow, I., Bengio, Y., and Courville, A. (2016). Deep Learning. MIT Press. https://www.deeplearningbook.org
Interactive Demo
Tip: Click Run 100 Epochs and watch the generated distribution converge toward the real distribution