← All posts

Foundations

Post 13 of 15

GANs: a generator and a judge training each other

Posts in this series · 15

In the last post a variational autoencoder learned to make new data by rebuilding its input and keeping its code space tidy. Its score was a hand-written formula: squared error plus a KL term. The trouble is that “squared error is small” and “looks real” are not the same thing. Averaging two plausible faces gives a blurry face with a small squared error. Averaging two plausible sound waves gives a muffled one.

A generative adversarial network (GAN) gets around this by not writing the score down at all. It trains a second network to be the score. Goodfellow and colleagues introduced the idea in 2014, and for about six years it produced the sharpest images and the most natural vocoder audio of any method. It is also the reason the codecs in my speech posts have “discriminators” in their training recipe.

The whole model at a glance

Here is one whole round of GAN training with every number shown, in the same one-number setting as the live trainer later in this post: real data around 3, a generator that is just a straight line, and a detective with three weights. Step through it once now. The detective’s loss, the forger’s loss and the turn-taking each get their own section below.

A GAN: noise into the generator, real and fake samples into the detective, and both updates
Figure 1. One GAN training round, from noise to updated weights. The detective learns first while the generator is frozen, then the generator learns through the frozen detective. After one round the same noise makes a fake that sits closer to the real data. At the end only the generator is kept.

The forger and the detective

Picture a forger who paints fake banknotes and a detective who inspects notes and says “real” or “fake”. At first the forger is terrible and the detective wins easily. But every time the detective explains (through gradients) what gave a fake away, the forger fixes exactly that. The detective then has to look harder. If both keep improving, the forger ends up making notes the detective cannot tell apart from real ones.

The two networks are:

The generator never sees real data. Everything it learns comes through DD‘s gradient. That is the key difference from the autoencoder, whose decoder was compared directly against the input.

The minimax objective

In one sentence: the detective wants to give real samples high scores and fakes low scores, and the forger wants the same quantity the detective is maximising to be as small as possible. Goodfellow et al. (2014) wrote it as

min⁡Gmax⁡D  V(D,G)=Ex∼pdata[log⁡D(x)]+Ez∼pz[log⁡(1−D(G(z)))]\min_G \max_D \; V(D, G) = \mathbb{E}_{x \sim p_{\text{data}}}\big[\log D(x)\big] + \mathbb{E}_{z \sim p_z}\big[\log\big(1 - D(G(z))\big)\big]

Every symbol:

Everyday picture: the detective earns points for every correct call; the forger loses exactly those points.

If you have read the loss post, the two log terms should look familiar. They are cross-entropy in disguise.

The detective’s loss is binary cross-entropy

Flip the sign of VV and the discriminator’s job becomes minimising an ordinary loss. Give every real sample the label y=1y = 1 and every fake the label y=0y = 0. Then

LD=−12m[∑i=1mlog⁡D(xi)+∑i=1mlog⁡(1−D(G(zi)))]L_D = -\frac{1}{2m}\left[\sum_{i=1}^{m} \log D(x_i) + \sum_{i=1}^{m} \log\big(1 - D(G(z_i))\big)\right]

In words: for each real sample, the surprise at calling it real; for each fake, the surprise at calling it fake; average them all.

This is exactly binary cross-entropy (BCE): the two-class version of the cross-entropy from post 2. So the detective is just a classifier with a label it can always trust, because we know which samples we made.

Worked by hand on six scores

Three real notes get scores D=0.9,0.8,0.6D = 0.9, 0.8, 0.6. Three fakes get D=0.3,0.2,0.5D = 0.3, 0.2, 0.5. (Natural logs throughout.)

Real terms, −log⁡D-\log D:

Fake terms, −log⁡(1−D)-\log(1 - D):

Sum: 0.1054+0.2231+0.5108+0.3567+0.2231+0.6931=2.11230.1054 + 0.2231 + 0.5108 + 0.3567 + 0.2231 + 0.6931 = 2.1123. Divide by 6: LD=L_D = 0.352.

What changes if a number changes: the worst term is the fake scored 0.50.5 (a shrug). Pushing that fake’s score down to 0.10.1 makes its term −log⁡0.9=0.1054-\log 0.9 = 0.1054, and the loss drops to (2.1122−0.6931+0.1054)/6=0.254(2.1122 - 0.6931 + 0.1054)/6 = 0.254. A perfectly confident correct detective would score 0.

Six notes with the detective's scores, and the losses computed from them
Figure 2. The detective’s scorecard. Step through the six scores: each step shows one cross-entropy term, then the average 0.352, then the forger’s two possible losses on the same three fakes. The slider changes the third fake’s score; every number updates.

The forger’s loss: saturating and non-saturating

The forger only affects the second term, so the minimax rule says: minimise log⁡(1−D(G(z)))\log(1 - D(G(z))). This is called the saturating generator loss. On our three fakes it is (log⁡0.7+log⁡0.8+log⁡0.5)/3=(−0.3567−0.2231−0.6931)/3=(\log 0.7 + \log 0.8 + \log 0.5)/3 = (-0.3567 - 0.2231 - 0.6931)/3 = −0.4243.

Goodfellow et al. noticed a problem in the same paper. Early in training the forger is bad, so the detective scores its fakes near 0. And near D=0D = 0, the curve log⁡(1−D)\log(1 - D) is almost flat. A flat loss means a tiny gradient: the forger is told “you are losing” but not “which way to go”.

Their fix: instead of minimising “the detective is right about my fakes”, maximise “the detective is wrong about my fakes”. The non-saturating loss is

LG=−1m∑i=1mlog⁡D(G(zi))L_G = -\frac{1}{m}\sum_{i=1}^{m} \log D(G(z_i))

In words: the forger’s surprise that its fake was called real. Both losses want D(G(z))D(G(z)) to rise; they just push with very different strength. On our three fakes: (−log⁡0.3−log⁡0.2−log⁡0.5)/3=(1.2040+1.6094+0.6931)/3=(-\log 0.3 - \log 0.2 - \log 0.5)/3 = (1.2040 + 1.6094 + 0.6931)/3 = 1.1689.

Why the non-saturating gradient is bigger early

Write the detective’s output as D=σ(s)D = \sigma(s), where ss is its raw score (the logit) and σ\sigma is the sigmoid from the first post. The sigmoid has the handy slope σ′(s)=D(1−D)\sigma'(s) = D(1 - D). Then, by the chain rule:

Both are negative, so both say “raise ss”. Now plug in numbers:

D(G(z))D(G(z))saturating pushnon-saturating push
0.01 (forger hopeless)0.010.99
0.10.10.9
0.5 (even match)0.50.5
0.9 (forger winning)0.90.1

When the forger is hopeless, the saturating loss pushes 99 times more weakly. The non-saturating loss is strongest exactly when the forger most needs help. Almost every GAN since uses it, or one of the alternatives further down.

Two generator loss curves, one flat where the forger is losing, one steep
Figure 3. Two ways to tell the forger it lost. Slide D(G(z)). At 0.01 the saturating curve is nearly flat (push 0.01) while the non-saturating curve is steep (push 0.99). They cross at 0.5.

The best possible detective

Suppose we freeze the forger and let the detective train forever. What does it end up saying? For any one point xx, real samples land there with density pdata(x)p_{\text{data}}(x) and fakes with density pg(x)p_g(x). The detective’s best answer is the fraction of samples at xx that are real:

D∗(x)=pdata(x)pdata(x)+pg(x)D^*(x) = \frac{p_{\text{data}}(x)}{p_{\text{data}}(x) + p_g(x)}

Everyday picture: at a market stall where 8 of every 10 notes are real, the best you can say about any note is “80 percent real”.

A one-dimensional example

Let real data be a bell curve centred at 0 with spread 1, and the forger’s output a bell curve centred at 2 with spread 1. The bell-curve height at distance dd from the centre is 12πe−d2/2\frac{1}{\sqrt{2\pi}}e^{-d^2/2}: 0.39890.3989 at d=0d = 0, 0.24200.2420 at d=1d = 1, 0.05400.0540 at d=2d = 2, 0.00440.0044 at d=3d = 3.

If the forger slid its curve onto 0, the two densities would be equal everywhere and D∗(x)=0.5D^*(x) = 0.5 for every xx. A perfect forger leaves the best detective shrugging.

Real and generated bell curves with the best possible detective between them
Figure 4. The best detective for a frozen forger. At the default (forger centred at 2) the judge reads 0.881 at x = 0, 0.5 at x = 1 and 0.119 at x = 2. Slide the forger to 0 and the judge flattens to 0.5 everywhere.

What the forger is really minimising

Plug D∗D^* back into VV. Goodfellow et al. showed the result is

V(D∗,G)=2 JSD(pdata ∥ pg)−log⁡4V(D^*, G) = 2\,\mathrm{JSD}(p_{\text{data}} \,\|\, p_g) - \log 4

So against a perfect detective, the forger is pushing the Jensen-Shannon distance to zero, and the best value of the game is −log⁡4=−1.386-\log 4 = -1.386, reached only when pg=pdatap_g = p_{\text{data}}. For our two bell curves, computed numerically:

forger centreJSDV(D∗,G)V(D^*, G)
00−1.386
10.111−1.163
20.337−0.713
40.633−0.121
80.693−0.000

Look at the bottom two rows. Once the curves stop overlapping, JSD sits at its ceiling and barely changes: moving from 8 to 7 gives the forger almost no signal. That observation is where Wasserstein GANs start.

Training: take turns

Nobody trains the detective to perfection between forger moves; it is too expensive. Instead the two take turns, one mini-batch each:

  1. Draw mm real samples and mm noise vectors; make mm fakes.
  2. Detective step: compute LDL_D on the 2m2m samples and take one gradient step on DD‘s weights only.
  3. Draw fresh noise, make fresh fakes.
  4. Forger step: compute LGL_G (non-saturating) and take one gradient step on GG‘s weights only. The gradient flows backward through DD into GG, but DD‘s weights are not changed.
  5. Repeat.

Goodfellow et al. allowed kk detective steps per forger step and used k=1k = 1 in their experiments. Any optimiser from the optimisers post works; Adam with a low momentum setting is the classic choice for image GANs (Radford, Metz and Chintala’s DCGAN, 2016, used Adam with β₁ = 0.5 instead of the usual 0.9).

A one-number GAN, trained live

Small enough to follow every weight:

Measured on a fixed set of 2000 noise draws:

stepaabbsample meansample spread
01.0000.0000.0110.999
1001.4421.1491.1651.441
3000.4763.0123.0170.475
10000.5052.9432.9490.505
30000.5233.0263.0310.522

Notice step 100: the spread grows to 1.44 before it shrinks. The detective first learns “real is to the right”, the forger runs right and briefly widens, then the x2x^2 feature catches the overshoot and squeezes it back. The ending is not perfectly still: the two keep nudging each other, and the numbers wobble around the target.

A slow detective is worse. With the detective learning rate cut to 0.05 (same seed), the forger arrives at mean 3.07 but its spread keeps shrinking to 0.001: every fake is nearly the same number. The detective never learns fast enough to complain that “everything identical” is suspicious. That is a first taste of mode collapse.

A histogram of generated numbers sliding onto the real data as the GAN trains
Training
Detective learning rate
Figure 5. A GAN you can watch. Seeded toy, one forger step per detective step. The red histogram moves from mean 0.01 to 3.03 with spread 0.52, on top of the green data (mean 3, spread 0.5). Pause at any point; choose the slow detective rate 0.05 to see the spread collapse to 0.001.

When the game goes wrong

Mode collapse

Now make the real data two peaks: half the samples near −2-2, half near +2+2, each with spread 0.3. Give the detective seven bump features (bell curves of width 0.5 centred at −3, −2, …, 3) so it can tell the two peaks apart. Keep the affine forger.

Start the forger narrow and to the right (a=0.3a = 0.3, b=1b = 1). Within 200 steps the spread aa drops to 0.0002 and the centre sits at 2.06. For the remaining 4000 steps, every single sample is positive (100 percent), and the centre wanders between about 1.5 and 2.5 while the detective keeps chasing it. The peak at −2-2 is never visited.

That is mode collapse: the forger finds one kind of output the detective accepts and makes only that. The detective then learns “things near 2 are fake”, the forger shuffles a little, the detective follows, and nobody’s gradient points toward the far peak, which sits behind a valley where the detective has no opinion.

Started wide instead (a=1a = 1, b=0b = 0), the same forger covers both sides (about 50 percent positive) but, being a single bell curve, it smears across the gap with spread about 2.6. An affine forger cannot make two peaks at all; real GANs have flexible forgers and still collapse, because collapse comes from the game, not only from capacity.

Two-peak real data and a forger that either collapses onto one peak or smears across both
Forger starts
Training
Figure 6. Stuck on one peak. Narrow start: by step 200 the spread is 0.0002 and 100 percent of samples are positive, for all 4000 steps. Wide start: about half the samples on each side, but spread across the empty gap.

Oscillation: a game is not a hill

Gradient descent on one loss rolls downhill. Two players each rolling down their own hill can circle forever. The smallest example is the bilinear game: player xx wants to minimise f(x,y)=xyf(x, y) = x y and player yy wants to maximise it. The answer is x=y=0x = y = 0.

Gradients: ∂f∂x=y\frac{\partial f}{\partial x} = y and ∂f∂y=x\frac{\partial f}{\partial y} = x. With step size η=0.5\eta = 0.5:

Simultaneous steps (both use the old values): x←x−ηyx \leftarrow x - \eta y, y←y+ηxy \leftarrow y + \eta x. Start at (1,1)(1, 1):

stepxxyydistance from 0
0111.414
11 − 0.5 × 1 = 0.51 + 0.5 × 1 = 1.51.581
20.5 − 0.75 = −0.251.5 + 0.25 = 1.751.768
3−1.1251.6251.976
4−1.93751.06252.210
5−2.46880.09382.471

The distance grows by a factor of 1+η2=1.118\sqrt{1 + \eta^2} = 1.118 every step: an outward spiral. Each player does the locally sensible thing, and together they fly apart.

Alternating steps (yy uses the new xx): x←x−ηyx \leftarrow x - \eta y, then y←y+ηxy \leftarrow y + \eta x.

stepxxyydistance
0111.414
10.51 + 0.5 × 0.5 = 1.251.346
2−0.1251.18751.194
3−0.71880.82811.097
4−1.13280.26171.163
5−1.2637−0.37011.317

It no longer escapes, but it does not settle either: it orbits the answer. Mescheder, Geiger and Nowozin (2018) studied a GAN version of this (a one-parameter forger against a linear detective, which they call the Dirac-GAN) and showed that unregularised GAN training need not converge, while adding a gradient penalty on the detective makes it converge.

Two players updating at once spiral away from the answer; taking turns, they circle it
Updates
Figure 7. Two players, no hill. From (1, 1) with step 0.5: simultaneous updates spiral out (distance 1.414, 1.581, 1.768, …); alternating ones loop around without arriving.

Vanishing detective gradients

The opposite of a slow detective is one that wins too completely. If real and fake samples do not overlap, a detective can score every real sample near 1 and every fake near 0. With the saturating loss the forger’s push is then about D(G(z))D(G(z)), close to zero. With any loss, the detective’s curve is flat in the region where the fakes live, because it is confidently 0 everywhere there. The forger is told it is losing and given no direction. Arjovsky and colleagues argued that this is common for images, where real data occupies a thin sliver of all possible pixel arrays.

Fixes in brief

GANs in speech

Speech is where I meet GANs most. A vocoder turns a spectrogram into a waveform, and squared error on waveforms gives muffled, buzzy audio for the same blurring reason as at the top of this post. A detective that has heard real speech catches that buzz.

Why diffusion took over

Around 2021, diffusion models overtook GANs for image generation, and diffusion and flow-matching models now do much of what GANs did in speech too. The reasons follow from this post: their training is one ordinary loss rolling downhill, not a two-player chase, so it does not spiral or collapse, and they cover every mode of the data. The price is speed, since they generate in many small steps rather than one. GANs survive where one fast step matters and a strong reference signal exists to anchor them, which is exactly the codec decoder. The next post, diffusion and flow models, picks up from there.

Counting the parameters

A GAN is two networks, and you count each one’s layers the usual way (dense layers, convolutions). The one-number GAN of this post is as small as it gets: the generator x=az+bx = a z + b has 2 parameters, and the detective σ(w1x2+w2x+c)\sigma(w_1 x^2 + w_2 x + c) has 3.

import torch.nn as nn

count = lambda m: sum(p.numel() for p in m.parameters())
generator = nn.Linear(1, 1)  # x = a z + b
detective = nn.Linear(2, 1)  # scores the features (x², x)
print("generator", count(generator), "detective", count(detective))

It prints:

generator 2 detective 3

Only the generator is kept after training. The detective’s parameters exist only to train it, so a GAN’s training cost includes a whole second network that is thrown away.

What to remember

Try it yourself

Sources