4.5.6Generative Models

Generative Adversarial Networks (GAN) framework

3,381 words15 min readdifficulty · medium2 backlinks

Overview

Generative Adversarial Networks (GANs) are a framework for training generative models through an adversarial process between two neural networks: a Generator that creates fake samples and a Discriminator that distinguishes real from fake. This competitive training regime produces highly realistic synthetic data.

Figure — Generative Adversarial Networks (GAN) framework

The key insight: we don't need to explicitly specify what "realistic" means. The discriminator learns this implicitly from data, and competition forces the generator to match it.

The Two-Player Game Framework

  1. Generator G(z;θg)G(z; \theta_g): Maps random noise zpz(z)z \sim p_z(z) to data space, producing fake samples G(z)G(z)
  2. Discriminator D(x;θd)D(x; \theta_d): Maps input xx to probability [0,1][0,1] that xx is real (not generated)

The game: GG tries to maximize DD's error rate, while DD tries to minimize it.

The Objective Function: Deriving From First Principles

Starting Point: What do we want?

  • DD should output 1 for real data, 0 for fake data
  • GG should fool DD into outputing 1 for fake data

Step 1: Express DD's goal using probabilities

For real data xpdata(x)x \sim p_{data}(x), we want D(x)1D(x) \approx 1. Using log probability (maximizes when D(x)=1D(x) = 1): Expdata[logD(x)]\mathbb{E}_{x \sim p_{data}}[\log D(x)]

Why log? Logarithm converts probabilities to log-likelihoods, standard in maximum likelihood estimation. It also provides numerical stability and treats0.99→1.0 as less important than 0.01→0.1.

Step 2: Express DD's goal for fake data

For fake data G(z)G(z) where zpz(z)z \sim p_z(z), we want D(G(z))0D(G(z)) \approx 0, equivalently 1D(G(z))11 - D(G(z)) \approx 1: Ezpz[log(1D(G(z)))]\mathbb{E}_{z \sim p_z}[\log(1 - D(G(z)))]

Step 3: Combine both objectives

DD wants to maximize both, so: maxD[Expdata[logD(x)]+Ezpz[log(1D(G(z)))]]\max_D \left[\mathbb{E}_{x \sim p_{data}}[\log D(x)] + \mathbb{E}_{z \sim p_z}[\log(1 - D(G(z)))]\right]

Step 4: What does GG want?

GG wants to minimize DD's success, i.e., minimize the objective that DD maximizes: minGmaxD[Expdata[logD(x)]+Ezpz[log(1D(G(z)))]]\min_G \max_D \left[\mathbb{E}_{x \sim p_{data}}[\log D(x)] + \mathbb{E}_{z \sim p_z}[\log(1 - D(G(z)))]\right]

The training objective is: minGmaxDV(G,D)\min_G \max_D V(G,D)

This is a minimax two-player game. At equilibrium, GG generates samples indistinguishable from real data, and DD outputs 0.50.5 everywhere (maximum uncertainty).

Training Algorithm: Alternating Optimization

Since we cannot solve the minimax problem directly, we use alternating gradient descent:

Why alternating? If we trained both simultaneously with joint gradient descent, the objectives conflict—improving one worsens the other's gradient signal. Alternating allows each network to adapt to the other's current state.

For Discriminator (kk steps):

Maximize V(G,D)V(G,D) w.r.t. θd\theta_d: θdV(G,D)=Expdata[θdlogD(x)]+Ezpz[θdlog(1D(G(z)))]\nabla_{\theta_d} V(G,D) = \mathbb{E}_{x \sim p_{data}}\left[\nabla_{\theta_d} \log D(x)\right] + \mathbb{E}_{z \sim p_z}\left[\nabla_{\theta_d} \log(1 - D(G(z)))\right]

Practical computation:

  1. Sample minibatch {x(1),,x(m)}\{x^{(1)}, \ldots, x^{(m)}\} from real data
  2. Sample minibatch {z(1),,z(m)}\{z^{(1)}, \ldots, z^{(m)}\} from noise pzp_z
  3. Generate fakes: {x~(1),,x~(m)}\{\tilde{x}^{(1)}, \ldots, \tilde{x}^{(m)}\} where x~(i)=G(z(i))\tilde{x}^{(i)} = G(z^{(i)})
  4. Gradient ascent update: θdθd+α1mi=1m[θdlogD(x(i))+θdlog(1D(x~(i)))]\theta_d \leftarrow \theta_d + \alpha \cdot \frac{1}{m}\sum_{i=1}^{m}\left[\nabla_{\theta_d}\log D(x^{(i)}) + \nabla_{\theta_d}\log(1-D(\tilde{x}^{(i)}))\right]

Why multiple kk discriminator steps? Early in training, GG is poor, so DD can easily classify. We want DD near optimal before updating GG, otherwise GG receives weak gradient signal.

For Generator (1 step):

Minimize V(G,D)V(G,D) w.r.t. θg\theta_g — equivalently, maximize V(G,D)-V(G,D): θg(V(G,D))=Ezpz[θglog(1D(G(z)))]\nabla_{\theta_g} (-V(G,D)) = -\mathbb{E}_{z \sim p_z}\left[\nabla_{\theta_g} \log(1-D(G(z)))\right]

Key Issue: When GG is poor, D(G(z))0D(G(z)) \approx 0, so log(1D(G(z)))0\log(1-D(G(z))) \approx 0 → flat gradients (vanishing gradient problem).

Solution: Instead of minimizing log(1D(G(z)))\log(1-D(G(z))), maximize logD(G(z))\log D(G(z)): θgEzpz[logD(G(z)]\nabla_{\theta_g} \mathbb{E}_{z \sim p_z}[\log D(G(z)]

Why does this work? Both objectives have the same optimal point (where D(G(z))=0.5D(G(z)) = 0.5), but logD(G(z))\log D(G(z)) has stronger gradients when D(G(z))D(G(z)) is small. When DD confidently rejects (D0D \approx 0), logD-\log D gives large gradient, providing strong learning signal.

Practical computation:

  1. Sample minibatch {z(1),,z(m)}\{z^{(1)}, \ldots, z^{(m)}\} from pzp_z
  2. Gradient ascent on logD(G(z))\log D(G(z)): θgθg+α1mi=1mθglogD(G(z(i)))\theta_g \leftarrow \theta_g + \alpha \cdot \frac{1}{m}\sum_{i=1}^{m}\nabla_{\theta_g}\log D(G(z^{(i)}))

Iteration t=1000:

  1. Discriminator update (k=5k=5 steps):

    • Batch of64 real MNIST digits: x(1),,x(64)x^{(1)}, \ldots, x^{(64)}
    • Sample z(i)N(0,I100)z^{(i)} \sim \mathcal{N}(0, I_{100}), generate fakes x~(i)=G(z(i))\tilde{x}^{(i)} = G(z^{(i)})
    • Compute D(x(i))D(x^{(i)}) for reals, D(x~(i))D(\tilde{x}^{(i)}) for fakes
    • Loss: LD=164i=164[logD(x(i))+log(1D(x~(i)))]L_D = -\frac{1}{64}\sum_{i=1}^{64}[\log D(x^{(i)}) + \log(1-D(\tilde{x}^{(i)}))]
    • Backprop, update θd\theta_d to minimize LDL_D (maximize VV)
    • Repeat 5 times Why this step? After these updates, DD can better discriminate current GG outputs, providing meaningful feedback.
  2. Generator update (1 step):

    • Sample fresh noise z(1),,z(64)N(0,I100)z^{(1)}, \ldots, z^{(64)} \sim \mathcal{N}(0, I_{100})
    • Generate x~(i)=G(z(i))\tilde{x}^{(i)} = G(z^{(i)})
    • Compute D(x~(i))D(\tilde{x}^{(i)})
    • Loss: LG=164i=164logD(x~(i))L_G = -\frac{1}{64}\sum_{i=1}^{64}\log D(\tilde{x}^{(i)}) (negative because we maximize)
    • Backprop through both GG and DD (but only update θg\theta_g)
    • Update θg\theta_g to minimize LGL_G Why backprop through D? The gradient θgD(G(z))\nabla_{\theta_g} D(G(z)) requires chain rule through DD's forward pass. We compute DG(z)G(z)θg\frac{\partial D}{\partial G(z)} \cdot \frac{\partial G(z)}{\partial \theta_g}.

After many iterations: GG produces realistic digits, D(x)0.5D(x) \approx 0.5 for both real and fake.

Epoch 10:

  • D(xreal)D(x_{real}): 0.91 (confidently real)
  • D(G(z))D(G(z)): 0.12 (confidently fake)
  • Generated images: vague blob shapes

Why these values? DD has learned to discriminate easily because GG is still weak.

Epoch 50:

  • D(xreal)D(x_{real}): 0.78
  • D(G(z))D(G(z)): 0.31
  • Generated images: digit-like structures, but blurry

Why values decreased? GG improved, making DD's job harder. Arms race in action.

Epoch 200 (near convergence):

  • D(xreal)D(x_{real}): 0.58
  • D(G(z))D(G(z)): 0.54
  • Generated images: sharp, realistic digits

Why near 0.5? At equilibrium, pg=pdatap_g = p_{data}, so DD cannot distinguish, outputs maximum entropy (0.5).

Theoretical Properties

For fixed GG, what is the optimal DD^*?

The functional we maximize over DD is: V(G,D)=xpdata(x)logD(x)dx+zpz(z)log(1D(G(z)))dzV(G,D) = \int_x p_{data}(x)\log D(x)\,dx + \int_z p_z(z)\log(1-D(G(z)))\,dz

Change of variables: Let y=G(z)y = G(z), with induced distribution pg(y)p_g(y): V(G,D)=xpdata(x)logD(x)dx+xpg(x)log(1D(x))dxV(G,D) = \int_x p_{data}(x)\log D(x)\,dx + \int_x p_g(x)\log(1-D(x))\,dx

Combine integrals: V(G,D)=x[pdata(x)logD(x)+pg(x)log(1D(x))]dxV(G,D) = \int_x \left[p_{data}(x)\log D(x) + p_g(x)\log(1-D(x))\right]dx

Pointwise optimization: For each xx, maximize: f(Dx))=pdata(x)logD(x)+pg(x)log(1D(x))f(Dx)) = p_{data}(x)\log D(x) + p_g(x)\log(1-D(x))

Take derivative w.r.t. D(x)D(x) and set to zero: fD(x)=pdata(x)D(x)pg(x)1D(x)=0\frac{\partial f}{\partial D(x)} = \frac{p_{data}(x)}{D(x)} - \frac{p_g(x)}{1-D(x)} = 0

Solve for D(x)D(x): pdata(x)(1D(x))=pg(x)D(x)p_{data}(x)(1-D(x)) = p_g(x)D(x) pdata(x)=D(x)[pdata(x)+pg(x)]p_{data}(x) = D(x)[p_{data}(x) + p_g(x)] D(x)=pdata(x)pdata(x)+pg(x)D^*(x) = \frac{p_{data}(x)}{p_{data}(x) + p_g(x)}

Interpretation: Optimal DD outputs the Bayes-optimal probability that xx is real. When pg=pdatap_g = p_{data}, we get D=0.5D^* = 0.5 everywhere.

At the global optimum where pg=pdatap_g = p_{data}: V(G,D)=Expdata[log0.5]+Expdata[log0.5]=2log2V(G^*, D^*) = \mathbb{E}_{x \sim p_{data}}[\log 0.5] + \mathbb{E}_{x \sim p_{data}}[\log 0.5] = -2\log 2

This connects to Jensen-Shannon Divergence: JSD(pdatapg)=12KL(pdatapdata+pg2)+12KL(pgpdata+pg2)JSD(p_{data} \| p_g) = \frac{1}{2}KL(p_{data} \| \frac{p_{data}+p_g}{2}) + \frac{1}{2}KL(p_g \| \frac{p_{data}+p_g}{2})

The GAN objective can be rewritten as: minGV(G,DG)=log4+2JSD(pdatapg)\min_G V(G, D^*_G) = -\log 4+ 2 \cdot JSD(p_{data} \| p_g)

Why JSD? Minimizing the GAN objective is equivalent to minimizing the Jensen-Shannon divergence between real and generated distributions. JSD is symmetric and bounded [0,log2][0, \log 2], reaching 0 only when distributions are identical.

Common Training Challenges

Why it feels right: From GG's perspective, if G(z)G(z) fools DD, that seems like success. Why explore other modes?

The problem: GG maps all noise vectors to a single output (or small subset). Example: when generating faces, all outputs are the same face with slight variations. The generator "colapses" to a few modes of pdatap_{data} instead of covering all modes.

Root cause: The minimax objective only requires GG to fool DD on average, not to cover the full data distribution. If DD is weak in detecting repetition, GG exploits this.

Detection: Monitor diversity of generated samples. Compute metrics like Inception Score or measure if multiple different zz values produce nearly identical G(z)G(z).

Fix strategies:

  • Minibatch discrimination: Let DD see multiple samples simultaneously, detect lack of diversity
  • Unrolled GANs: Update GG considering future DD updates, discouraging exploitation
  • Multiple GANs: Train ensemble, each captures different modes

Why it feels right: In supervised learning, loss typically decreases monotonically. We expect similar behavior.

The problem: GG and DD losses oscillate wildly, never stabilizing. One network's improvement is the other's degradation. The system never reaches equilibrium.

Root cause: GANs don't optimize a single loss function—they're solving a minimax game. Game dynamics can cycle rather than converge. The gradient field has rotational components, not purely conservative.

Analogy: Think of (G,D)(G, D) as coordinates. Standard optimization descends a valley toward a minimum. GAN optimization is like two magnets repelling—trajectories can orbit indefinitely.

Detection: Plot DD loss and GG loss over time. Look for periodic oscillations rather than monotonic trends.

Fix strategies:

  • Careful learning rates: Lower rates reduce oscillation amplitude
  • Gradient penalty (WGAN-GP): Regularize DD to have bounded gradients, stabilizes training
  • Spectral normalization: Constrain DD's Lipschitz constant, smooth gradient flow
  • Two-timescale update rule (TUR): Different learning rates for GG and DD

Why it feels right: More training usually helps in supervised learning.

The problem: When DD becomes too strong quickly, it perfectly separates real from fake (D(xreal)1D(x_{real}) \approx 1, D(G(z))0D(G(z)) \approx 0). Then log(1D(G(z)))0\log(1-D(G(z))) \approx 0, giving GG near-zero gradients. GG stops learning—the arms race stalls.

Why mathematically: θglog(1D(G(z)))\frac{\partial}{\partial \theta_g} \log(1-D(G(z))) involves DG(z)\frac{\partial D}{\partial G(z)}. When D(G(z))0D(G(z)) \approx 0, small changes in G(z)G(z) don't change DD's output (it's saturated at 0), so gradient vanishes.

Fix: Use the non-saturating objective maxGEz[logD(G(z))]\max_G \mathbb{E}_z[\log D(G(z))] instead of minGEz[log(1D(G(z))]\min_G \mathbb{E}_z[\log(1-D(G(z))]. This gives strong gradients even when DD is confident.

Verification: When D(G(z))=0.01D(G(z)) = 0.01:

  • Original: log(10.01)=(0.01005)0.01\nabla \log(1-0.01) = \nabla(-0.01005) \approx -0.01 (tiny)
  • Non-saturating: log(0.01)=(4.605)100×\nabla \log(0.01) = \nabla(-4.605) \approx 100 \times larger gradient

Architectural Considerations

  1. Replace pooling with strided convolutions (in DD) and fractional-strided convolutions (in GG)

    • Why? Pooling loses spatial information deterministically. Strided convs learn downsampling, giving gradients throughout.
  2. Use batch normalization in both GG and DD

    • Why? Normalizes layer inputs, prevents mode collapse by ensuring activations don't saturate
    • Exception: Don't use in GG's output layer or DD's input layer (preserve raw data/generation scale)
  3. Remove fully connected hidden layers for deeper architectures

    • Why? Fully connected layers have huge parameter counts, harder to train. All-convolutional uses spatial structure.
  4. Use ReLU in GG (except output: tanh), LeakyReLU in DD

    • Why? ReLU helps gradients flow in GG. LeakyReLU in DD prevents dead neurons (avoids zero gradient for negative inputs).
  5. Generator output: Use tanh activation

    • Why? Matches normalized input range [1,1][-1, 1] if data is scaled to this range. Bounded output stabilizes training.

Connections to Other Concepts

Related Topics:

Upstream Dependencies:

Downstream Applications:

[!recall- Explain It to a 12-Year-Old Imagine you want to learn to draw realistic butterflies, but you've never seen one—you only have a teacher who's seen tons of butterflies.

Here's what you do: You draw a butterfly (it starts as terrible scribbles). You show it to your teacher, and they say "That's fake, try again." You draw another, they say "Still fake." But you notice what they're looking at—the wings are wrong, the antenna are too thick. So you improve.

Meanwhile, your teacher is also getting better at spoting fakes. At first, your drawings are SO bad that it's easy for them. But as you get better, they have to look closer—"Hmm, the wing pattern isn't quite right..."

This goes back and forth: you (the Generator) get better at drawing, they (the Discriminator) get better at spotting mistakes. Eventually, your butterflies are so good that even your expert teacher can't tell if it's your drawing or a photo. That's when you've succeeded!

The "trick" is that you never actually saw real butterfly. You learned only by trying to fool your teacher. Your teacher's job forced you to learn what real butterflies look like, without anyone directly showing you.

Order matters: Train D first (let it learn current G), then improve G to beat the updated D.

Objective mnemonic: "Real-log-Real, Fake-log-NOT-fake"

  • Real samples: logD(x)\log D(x) — want DD near 1
  • Fake samples: log(1D(G(z)))\log(1-D(G(z))) — want DD near 0 (so 1D1-D near 1)

Flashcards

#flashcards/ai-ml

What are the two neural networks in a GAN and what does each do? :: Generator GG creates fake samples from random noise zz. Discriminator DD classifies inputs as real (from data) or fake (from GG). They compete: GG tries to fool DD, DD tries to detect fakes.

Write the full GAN minimax objective function :: minGmaxDV(G,D)=Expdata[logD(x)]+Ezpz[log(1D(G(z)))]\min_G \max_D V(G,D) = \mathbb{E}_{x \sim p_{data}}[\log D(x)] + \mathbb{E}_{z \sim p_z}[\log(1-D(G(z)))]. Discriminator maximizes (wants high probability on real, low on fake), Generator minimizes (wants to fool discriminator).

Why do we train the discriminator for kk steps before one generator step?
If GG is weak early on, DD easily discriminates. Training DD to near-optimality before updating GG ensures GG receives strong, meaningful gradient signals. Otherwise GG gets weak feedback from a poorly-trained DD.
What is the optimal discriminator D(x)D^*(x) for a fixed generator?
D(x)=pdata(x)pdata(x)+pg(x)D^*(x) = \frac{p_{data}(x)}{p_{data}(x) + p_g(x)}. This is the Bayes-optimal probability that xx comes from real data. When pg=pdatap_g = p_{data}, D=0.5D^* = 0.5 everywhere (cannot distinguish).
Why use maxGlogD(G(z))\max_G \log D(G(z)) instead of minGlog(1D(G(z)))\min_G \log(1-D(G(z))) for generator training?
Both have the same optimal point, but when DD confidently rejects fakes (D(G(z))0D(G(z)) \approx 0), log(1D(G(z)))0\log(1-D(G(z))) \approx 0 gives vanishing gradients. logD(G(z))\log D(G(z)) gives large gradients when DD is confident, providing strong learning signal when GG is weak.
What is mode collapse in GANs?
Generator maps all (or most) noise inputs zz to a small subset of outputs, failing to cover the full diversity of real data. Example: generating only a few types of faces instead of full variety. Happens because GG exploits weaknesses in DD rather than learning full distribution.
What divergence does the GAN objective minimize at optimality?
Jensen-Shannon divergence (JSD) between pdatap_{data} and pgp_g. The objective is log4+2JSD(pdatapg)-\log 4 + 2 \cdot JSD(p_{data} \| p_g). JSD is symmetric, bounded [0,log2][0, \log 2], and reaches 0 only when distributions match exactly.

What is the non-convergence problem in GANs? :: GG and DD losses oscillate without stabilizing. Unlike supervised learning with single loss, GANs solve a minimax game—one's improvement is the other's degradation. Gradient field has rotational components, causing orbiting rather than convergence to fixed point.

In DCGAN architecture, why use strided convolutions instead of pooling?
Pooling (max-pool, avg-pool) loses information deterministically with no learnable parameters. Strided convolutions learn how to downsample, providing gradients throughout and preserving spatial information better during training.
Why does the discriminator use LeakyReLU instead of ReLU?
Standard ReLU zeros out negative inputs, creating dead neurons with zero gradient. LeakyReLU (max(x,αx)\max(x, \alpha x) with α0.01\alpha \approx 0.01) allows small gradient for negative values, keeping all neurons active and ensuring gradient flow throughout discriminator.
What happens at GAN equilibrium (global optimum)?
pg=pdatap_g = p_{data} (generator distribution matches real data), D(x)=0.5D(x) = 0.5 for all xx (discriminator cannot distinguish real from fake), and V(G,D)=2log2V(G^*, D^*) = -2\log 2 (value function at Nash equilibrium).
Why does the generator gradient require backpropagating through the discriminator?
Computing θglogD(G(z))\nabla_{\theta_g} \log D(G(z)) requires chain rule: logDDDG(z)G(z)θg\frac{\partial \log D}{\partial D} \cdot \frac{\partial D}{\partial G(z)} \cdot \frac{\partial G(z)}{\partial \theta_g}. We need DG(z)\frac{\partial D}{\partial G(z)} which comes from DD's forward pass, so we backprop through DD (but only update θg\theta_g).

Concept Map

input to

produces

input to

input to

outputs probability real

tries to fool

maximizes

minimizes

defines

converges to

means

Random noise z

Generator G

Fake samples

Real data pdata

Discriminator D

D x in 0-1

Value function V G,D

Minimax game

Equilibrium D=0.5

Samples indistinguishable

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Chalo, ise ek game ki tarah samajhte hain. GAN framework mein do neural networks aapas mein compete karte hain — ek hai Generator jo fake data banata hai (jaise ek nakli note banane wala counterfeiter), aur doosra hai Discriminator jo real aur fake ko pehchanne ki koshish karta hai (jaise ek detective). Yeh dono ek "adversarial" (matlab virodhi) process mein train hote hain. Jaise-jaise detective fakes pakadne mein tez hota hai, counterfeiter ko apne fakes aur behtar banane padte hain. Isi arms race ki wajah se dono itne acche ho jaate hain ki last mein Generator itna realistic data banane lagta hai ki Discriminator confuse ho jaata hai aur har baar 0.5 probability deta hai — matlab woh guess bhi nahi kar sakta ki real hai ya fake!

Ab core intuition yeh hai ki humein manually define karne ki zaroorat hi nahi ki "realistic" ka matlab kya hai. Discriminator yeh khud data se seekh leta hai, aur competition ki wajah se Generator ko usko match karna padta hai. Mathematically yeh ek minimax game hai: Generator loss ko minimize karta hai jabki Discriminator use maximize karta hai. Value function V(G,D)V(G,D) mein do parts hain — pehla real data ke liye (D(x)D(x) should be 1), doosra fake data ke liye (D(G(z))D(G(z)) should be 0). Training alternating tarike se hoti hai, matlab pehle Discriminator ko thoda train karo, phir Generator ko — kyunki agar dono ko ek saath train karo toh unke objectives conflict kar jaate hain aur gradient signal kharab ho jaata hai.

Yeh important isliye hai kyunki GANs ne generative AI mein revolution la diya — realistic faces, images, art, aur bahut kuch generate karne ki foundation yahi framework hai. Jab tum aaj ke deepfakes, AI art tools ya image generation systems dekhte ho, unke peeche kahin na kahin yahi adversarial idea kaam kar raha hota hai. So yeh concept samajhna tumhare liye modern generative models ka darwaza khol deta hai, aur interviews ya projects mein yeh ek strong foundation banata hai. Bas yaad rakhna — counterfeiter aur detective wala game, aur baaki sab clear ho jaayega!

Go deeper — visual, from zero

Test yourself — Generative Models

Connections