Type at least 2 letters. Enter opens the first result, Esc closes.

    Generative Models · Lesson 5 · Adversarial and energy-based models

    GANs and Wasserstein GANs: the optimal discriminator, training dynamics and W1W_1

    Advanced 95 min 5 interactive figures 3 videos Colab notebook

    Before this lesson: lesson 01 (maximum likelihood as a KL divergence) and lesson 04 (models with an exact likelihood; a GAN gives that up). From other tracks: the KL divergence and f-divergences, the convex conjugate and critics (information theory), duality and stochastic gradient descent (optimization), and the spectral norm (linear algebra). Time: about 95 minutes, plus the notebook.


    Why this matters #

    A GAN learns to sample without a density. This made GANs the leading image generators from 2014 to about 2021 (DCGAN, StyleGAN, BigGAN). They are still in use. The autoencoder of latent diffusion models (Stable Diffusion) is trained with an adversarial loss, so the latent space of lesson 13 is shaped by a GAN. Few-step diffusion samplers use discriminators (lesson 12). In science, GANs were used for precipitation nowcasting and for seismic ground-motion synthesis before diffusion models.

    The ideas of this lesson also go far beyond GANs. "Train a classifier and read off the density ratio" is the basis of neural ratio estimation in physics. The Wasserstein distance and Lipschitz critics come back in optimal transport and flow matching (lesson 10). The questions "what does the discriminator learn?", "why does the gradient vanish?" and "why does WGAN help?" are standard interview questions.

    1. Predict first #

    2. The picture #

    The simplest case: three outcomes. A sample can take three values. The data distribution is pdata=(0.6,0.4,0)p_{\text{data}} = (0.6, 0.4, 0). The generator currently produces pg=(0.2,0.4,0.4)p_g = (0.2, 0.4, 0.4). Real and fake samples come in equal numbers. A discriminator sees one sample xx and must say "real" or "fake". The best it can do is to compare the two probabilities of xx:

    • outcome 1 is three times more likely under the data, so it says "real" with probability 0.6/(0.6+0.2)=0.750.6/(0.6 + 0.2) = 0.75;
    • outcome 2 is equally likely under both, so it says 0.4/(0.4+0.4)=0.50.4/(0.4 + 0.4) = 0.5;
    • outcome 3 never occurs in the data, so it says 00.

    In odds, D/(1−D)=(3,1,0)=pdata/pgD/(1 - D) = (3, 1, 0) = p_{\text{data}}/p_g. A perfect discriminator is a density-ratio estimator. The generator reads this ratio and moves probability from outcome 3 (ratio 0) toward outcome 1 (ratio 3).

    The same in 1D. In the figure, the data are the track's two Gaussians and the generator is one Gaussian. The lower panel shows the best discriminator at every point.

    Interactive figure: loading…

    Drag the orange peak (or use the sliders) to move and widen the generator density pgp_g. The data density pdatap_{\text{data}} is fixed. The black curve is the optimal discriminator D∗(x)D^*(x): it is 12\tfrac12 where the two densities are equal, close to 1 where only the data have mass, and close to 0 where only the generator has mass. Move the yellow probe and compare D∗/(1−D∗)D^*/(1 - D^*) with pdata/pgp_{\text{data}}/p_g. Choose "far generator": JSD gets close to log⁡2≈0.693\log 2 \approx 0.693 and D∗D^* is flat near the generator.

    The generator only sees the slope of DD at its own samples. A sample is x=Gθ(z)x = G_\theta(z). The generator changes θ\theta to raise DD at xx. By the chain rule,

    ∇θ D(Gθ(z))=JG⊤ ∇xD(x),JG=∂Gθ(z)∂θ.\nabla_\theta\, D(G_\theta(z)) = J_G^\top\, \nabla_x D(x), \qquad J_G = \frac{\partial G_\theta(z)}{\partial \theta}.

    JGJ_G is the Jacobian of the sample with respect to the generator weights. So each sample moves in the direction where DD increases. If DD is flat at the sample, ∇xD=0\nabla_x D = 0 and the generator learns nothing from it.

    When the supports do not overlap. Real images lie near a thin, low-dimensional set in pixel space. A generator with a low-dimensional input zz produces another thin set. Two thin sets in a high-dimensional space almost never overlap. Then a discriminator can separate them perfectly: D≈1D \approx 1 on the data, D≈0D \approx 0 on the fakes, and DD is flat near both. No gradient.

    A distance that sees how far apart. Think of PP and QQ as two piles of sand. The Wasserstein-1 distance W1W_1 is the least total work (mass times distance moved) needed to turn one pile into the other. If the generator's pile is 0.1 away, W1=0.1W_1 = 0.1; if it is 1 away, W1=1W_1 = 1. The Jensen–Shannon divergence is log⁡2\log 2 in both cases, because it only asks whether the piles overlap.

    Quick check

    The data are pdata=(0.5,0.5,0)p_{\text{data}} = (0.5, 0.5, 0) and the generator gives pg=(0.5,0,0.5)p_g = (0.5, 0, 0.5). What is the optimal discriminator D∗D^* on the three outcomes?

    3. Definitions and main results #

    The GAN game #

    Notation. Noise z∼pzz \sim p_z (for example N(0,Ik)\mathcal N(0, I_k)) goes through the generator Gθ:Rk→RdG_\theta: \R^k \to \R^d. The distribution of Gθ(z)G_\theta(z) is pgp_g. We can sample from it, but we cannot evaluate it (for k<dk < d it has no density at all). The discriminator outputs a logit lϕ(x)∈Rl_\phi(x) \in \R and Dϕ(x)=σ(lϕ(x))∈(0,1)D_\phi(x) = \sigma(l_\phi(x)) \in (0, 1), the probability that xx is real, where σ(u)=1/(1+e−u)\sigma(u) = 1/(1 + e^{-u}) is the logistic sigmoid. The value function is

    V(D,G)=Ex∼pdata[log⁡D(x)]+Ez∼pz[log⁡(1−D(G(z)))].V(D, G) = \mathbb E_{x \sim p_{\text{data}}}[\log D(x)] + \mathbb E_{z \sim p_z}[\log(1 - D(G(z)))].

    The game is min⁡Gmax⁡DV(D,G)\min_G \max_D V(D, G).

    −V-V is the binary cross-entropy of a classifier with label 1 for real and 0 for fake, so the DD step is logistic regression. Because Ez[h(G(z))]=Ex∼pg[h(x)]\mathbb E_z[h(G(z))] = \mathbb E_{x \sim p_g}[h(x)] for any function hh, the second term is Epg[log⁡(1−D(x))]\mathbb E_{p_g}[\log(1 - D(x))].

    The Jensen–Shannon divergence (JSD) of pp and qq uses their average m=12(p+q)m = \tfrac12(p + q):

    JSD(p ∥ q)=12KL(p ∥ m)+12KL(q ∥ m).\mathrm{JSD}(p \,\|\, q) = \tfrac12 \mathrm{KL}(p \,\|\, m) + \tfrac12 \mathrm{KL}(q \,\|\, m).

    It is symmetric, always finite, between 00 and log⁡2\log 2, and 00 only when p=qp = q.

    Theorem (optimal discriminator; Goodfellow et al. 2014). For a fixed GG,

    D∗(x)=pdata(x)pdata(x)+pg(x),D^*(x) = \frac{p_{\text{data}}(x)}{p_{\text{data}}(x) + p_g(x)},
    C(G)=max⁡DV(D,G)=−log⁡4+2 JSD(pdata ∥ pg).C(G) = \max_D V(D, G) = -\log 4 + 2\,\mathrm{JSD}(p_{\text{data}} \,\|\, p_g).

    The global minimum of CC is −log⁡4-\log 4, reached only at pg=pdatap_g = p_{\text{data}}.

    Why this is true, in one sentence. The discriminator can choose its answer separately at every point, and at each point the best answer is the share of real samples there; putting that answer back into VV gives two KL divergences to the average density.

    Proof.

    1. Write VV as one integral. D(x)D(x) can be chosen separately at every xx, so we maximize the integrand point by point:
    V=∫[ pdata(x)log⁡D(x)+pg(x)log⁡(1−D(x)) ] dx.V = \int \big[\,p_{\text{data}}(x)\log D(x) + p_g(x)\log(1 - D(x))\,\big]\,dx.
    1. For a,b≥0a, b \ge 0, not both 0, the function y↦alog⁡y+blog⁡(1−y)y \mapsto a\log y + b\log(1 - y) is concave on [0,1][0, 1] (with log⁡0=−∞\log 0 = -\infty). For a,b>0a, b > 0 its derivative a/y−b/(1−y)a/y - b/(1 - y) is zero at y∗=a/(a+b)y^* = a/(a + b). For b=0b = 0 the maximum is at y∗=1y^* = 1, for a=0a = 0 at y∗=0y^* = 0; the same formula. With a=pdata(x)a = p_{\text{data}}(x) and b=pg(x)b = p_g(x) this is D∗D^*.
    2. Let m=(pdata+pg)/2m = (p_{\text{data}} + p_g)/2. Then D∗=pdata/(2m)D^* = p_{\text{data}}/(2m) and 1−D∗=pg/(2m)1 - D^* = p_g/(2m). Substitute:
    C(G)=Epdata[log⁡pdatam]−log⁡2+Epg[log⁡pgm]−log⁡2=KL(pdata ∥ m)+KL(pg ∥ m)−log⁡4.\begin{aligned} C(G) &= \mathbb E_{p_{\text{data}}}\Big[\log\frac{p_{\text{data}}}{m}\Big] - \log 2 + \mathbb E_{p_g}\Big[\log\frac{p_g}{m}\Big] - \log 2 \\ &= \mathrm{KL}(p_{\text{data}} \,\|\, m) + \mathrm{KL}(p_g \,\|\, m) - \log 4. \end{aligned}
    1. By the definition of JSD, C(G)=−log⁡4+2 JSD(pdata ∥ pg)C(G) = -\log 4 + 2\,\mathrm{JSD}(p_{\text{data}} \,\|\, p_g).
    2. JSD≥0\mathrm{JSD} \ge 0, with equality only if pg=pdatap_g = p_{\text{data}}. There D∗=12D^* = \tfrac12 everywhere and C=−log⁡4C = -\log 4. ■\blacksquare

    Assumptions. DD can be any function (infinite capacity), both distributions have densities, and the inner maximization is solved for each GG. In practice none of these holds exactly: DD is a network trained for a few steps per generator step. So the theorem describes the target of the game, not what each training step does.

    Saturating and non-saturating generator losses #

    Write l=lϕ(G(z))l = l_\phi(G(z)) for the logit of a fake sample. Use the softplus function softplus⁡(u)=log⁡(1+eu)\operatorname{softplus}(u) = \log(1 + e^u) and the identities log⁡σ(l)=−softplus⁡(−l)\log\sigma(l) = -\operatorname{softplus}(-l) and log⁡(1−σ(l))=−softplus⁡(l)\log(1 - \sigma(l)) = -\operatorname{softplus}(l). These forms stay finite for any ll.

    Generator minimizes As a function of ll Derivative in ll At l=−8l = -8
    saturating (minimax): log⁡(1−D(G(z)))\log(1 - D(G(z))) −softplus⁡(l)-\operatorname{softplus}(l) −σ(l)-\sigma(l) −3.4×10−4-3.4 \times 10^{-4}
    non-saturating: −log⁡D(G(z))-\log D(G(z)) softplus⁡(−l)\operatorname{softplus}(-l) −σ(−l)-\sigma(-l) −0.99966-0.99966

    Both derivatives are negative, so both losses push ll up. But when DD confidently rejects the fakes (l≪0l \ll 0), the saturating gradient is about ele^{l}: it vanishes exactly when the generator is worst. The non-saturating loss "flips the label instead of the sign" and keeps a gradient near −1-1. The ratio of the two gradients is σ(−l)/σ(l)=e−l\sigma(-l)/\sigma(l) = e^{-l}, which is e8≈2981e^8 \approx 2981 at l=−8l = -8.

    Interactive figure: loading…

    Move the logit ll of a fake sample. Top: the saturating and the non-saturating generator losses. Bottom: the size of their gradients on a log scale. At l=−8l = -8 (the discriminator is sure the sample is fake) the saturating gradient is 3.4×10−43.4 \times 10^{-4} and the non-saturating one is almost 1. At l=0l = 0 the two are equal.

    The non-saturating game is no longer zero-sum, but it has the same fixed point (pg=pdatap_g = p_{\text{data}}, D=12D = \tfrac12). With the optimal D∗D^*, its expected generator gradient equals ∇θ[KL(pg ∥ pdata)−2 JSD(pg ∥ pdata)]\nabla_\theta\big[\mathrm{KL}(p_g \,\|\, p_{\text{data}}) - 2\,\mathrm{JSD}(p_g \,\|\, p_{\text{data}})\big] (Arjovsky and Bottou 2017, Theorem 2.5). The reverse KL KL(pg ∥ pdata)\mathrm{KL}(p_g \,\|\, p_{\text{data}}) in it is mode-seeking: it punishes fakes where there are no data, but it barely punishes a missing mode (see forward and reverse KL).

    Quick check

    The discriminator gives a fake sample D(G(z))=0.01D(G(z)) = 0.01. What is the ratio of the non-saturating gradient to the saturating gradient, both with respect to the logit?

    Disjoint supports: why JSD gives no gradient #

    If pdatap_{\text{data}} and pgp_g live on disjoint sets, then on the data's set m=pdata/2m = p_{\text{data}}/2, so KL(pdata ∥ m)=Epdata[log⁡2]=log⁡2\mathrm{KL}(p_{\text{data}} \,\|\, m) = \mathbb E_{p_{\text{data}}}[\log 2] = \log 2. The same holds for pgp_g. Hence JSD=log⁡2\mathrm{JSD} = \log 2 for every such pgp_g: the loss is constant, and its gradient is zero.

    This is the normal case, not a corner case. pgp_g lives on G(Rk)G(\R^k), a set of dimension at most kk. If both sets have lower dimension than Rd\R^d and do not line up exactly, their intersection has probability zero under both distributions. Then a perfect discriminator exists that is smooth and constant near both sets (Arjovsky and Bottou 2017, Theorems 2.1–2.2). As DD approaches it, the saturating gradient goes to zero, and the non-saturating gradient becomes unstable.

    Training dynamics: the Dirac-GAN #

    Even when the gradients do not vanish, gradient play on a game is not gradient descent on one function. The cleanest example is the Dirac-GAN (Mescheder, Geiger and Nowozin 2018):

    • the data are a point mass at 00;
    • the generator is a point mass at θ\theta (one number);
    • the discriminator is linear, with logit l(x)=ψxl(x) = \psi x (one number).

    The value function is V(θ,ψ)=log⁡σ(0)+log⁡(1−σ(ψθ))V(\theta, \psi) = \log\sigma(0) + \log(1 - \sigma(\psi\theta)). The unique equilibrium is θ=0\theta = 0 (the generator matches the data), ψ=0\psi = 0 (the discriminator cannot tell). The generator descends in θ\theta, the discriminator ascends in ψ\psi. The game vector field is

    θ˙=−∂θV=ψ σ(ψθ),ψ˙=∂ψV=−θ σ(ψθ).\dot\theta = -\partial_\theta V = \psi\,\sigma(\psi\theta), \qquad \dot\psi = \partial_\psi V = -\theta\,\sigma(\psi\theta).

    Step 1: linearize at the equilibrium. At (0,0)(0, 0), σ(0)=12\sigma(0) = \tfrac12, so the Jacobian of the field is

    J=(012−120),eigenvalues ±i2.J = \begin{pmatrix} 0 & \tfrac12 \\ -\tfrac12 & 0 \end{pmatrix}, \qquad \text{eigenvalues } \pm \tfrac{i}{2}.

    Purely imaginary eigenvalues mean rotation: the continuous field circles the equilibrium and never comes closer.

    Step 2: simultaneous steps. Both players step from the old point: (θ,ψ)←(θ,ψ)+η (θ˙,ψ˙)(\theta, \psi) \leftarrow (\theta, \psi) + \eta\,(\dot\theta, \dot\psi). Near (0,0)(0, 0) the step matrix is I+ηJI + \eta J, with eigenvalues 1±iη/21 \pm i\eta/2 and modulus 1+η2/4>1\sqrt{1 + \eta^2/4} > 1. Every step makes the distance to the equilibrium a little larger: the iterates spiral out, for every step size.

    Step 3: alternating steps. The generator steps first, and the discriminator then uses the new θ\theta. The linearized step matrix is (1η/2−η/21−η2/4)\begin{pmatrix} 1 & \eta/2 \\ -\eta/2 & 1 - \eta^2/4 \end{pmatrix}. Its determinant is exactly 1, and for η<4\eta < 4 its eigenvalues lie on the unit circle. The iterates go around a closed curve: they do not diverge, but they never converge.

    Step 4: a gradient penalty. The R1 penalty (Mescheder et al. 2018) adds γ2 Epdata∥∇xl(x)∥2\tfrac{\gamma}{2}\,\mathbb E_{p_{\text{data}}}\|\nabla_x l(x)\|^2 to the discriminator loss. Here ∇xl=ψ\nabla_x l = \psi, so the discriminator now maximizes V−γ2ψ2V - \tfrac{\gamma}{2}\psi^2 and ψ˙=−θσ(ψθ)−γψ\dot\psi = -\theta\sigma(\psi\theta) - \gamma\psi. The Jacobian becomes (01/2−1/2−γ)\begin{pmatrix} 0 & 1/2 \\ -1/2 & -\gamma \end{pmatrix}, with eigenvalues (−γ±γ2−1)/2\big(-\gamma \pm \sqrt{\gamma^2 - 1}\big)/2. Their real part is negative, so small enough steps converge.

    Numbers (checked in section 5): from (θ,ψ)=(1,0)(\theta, \psi) = (1, 0) with η=0.1\eta = 0.1, after 2000 steps the distance to (0,0)(0, 0) is 3.053.05 for simultaneous steps, stays near 11 for alternating steps, and is below 10−1010^{-10} with R1 and γ=1\gamma = 1.

    Interactive figure: loading…

    Press "Run 1000 steps" and watch the iterates spiral out from the start point along the game vector field. Then switch to "alternating": the path closes on itself. Then choose "simultaneous + R1": the path spirals in. The readouts give the eigenvalues of JJ and the growth factor per step near (0,0)(0, 0); the chart below shows the distance to (0,0)(0, 0) on a log scale. Drag the start point to try other starts.

    Quick check

    In the Dirac-GAN without a penalty, you halve the step size η\eta of simultaneous gradient steps. What happens?

    Mode collapse #

    Mode collapse means that the generator maps many values of zz to one or a few modes of the data: samples look good, but they have low diversity. Partial collapse (the same texture or the same pose again and again) is common.

    Why it happens: fix DD. The generator's best response is to send every zz to arg⁡max⁡xD(x)\arg\max_x D(x), a point mass. The discriminator then learns to reject that point, and the generator jumps to the next maximum: mode hopping. Gradient steps on both players do not clearly solve min⁡Gmax⁡D\min_G \max_D; they often behave like max⁡Dmin⁡G\max_D \min_G, whose inner problem is exactly this point mass (Goodfellow 2016, §5.1.1). The Dirac-GAN shows the same kind of cycling in one dimension.

    Interactive figure: loading…

    Press Play. The real data are the track's 8 Gaussians. Each generator sample moves along ∇x\nabla_x of the discriminator logit, the only signal a generator gets. The background shows where DD says "real" (blue) or "fake" (orange). Then choose the "Gaussian" generator G(z)=μ+AzG(z) = \mu + Az, which is too simple for 8 modes: it collapses to a small blob that travels around the ring. "Freeze D" lets the generator answer a fixed discriminator: the samples pile up at a few maxima of DD.

    Remedies: let DD see batch statistics (minibatch discrimination, the minibatch standard-deviation feature), unrolled GANs, smoother critics (WGAN-GP, spectral normalization, the R1 penalty), two time-scale learning rates, and class conditioning. Measure coverage with recall (lesson 14), not with the loss.

    f-GAN: a variational bound for any f-divergence #

    For a convex function ff with f(1)=0f(1) = 0, the f-divergence is Df(P ∥ Q)=EQ[f(p/q)]D_f(P \,\|\, Q) = \mathbb E_Q[f(p/q)] (KL is f(u)=ulog⁡uf(u) = u\log u). The convex conjugate of ff is f∗(t)=sup⁡u [ tu−f(u) ]f^*(t) = \sup_u\,[\,tu - f(u)\,].

    Theorem (f-GAN bound; Nguyen, Wainwright and Jordan 2010; Nowozin et al. 2016). Assume q>0q > 0 wherever p>0p > 0. For every function TT,

    Df(P ∥ Q)≥EP[T(x)]−EQ[f∗(T(x))].D_f(P \,\|\, Q) \ge \mathbb E_P[T(x)] - \mathbb E_Q[f^*(T(x))].

    For differentiable ff, equality holds at T∗(x)=f′(p(x)/q(x))T^*(x) = f'\big(p(x)/q(x)\big).

    Proof.

    1. From the definition of f∗f^*: f∗(t)≥tu−f(u)f^*(t) \ge tu - f(u) for all u,tu, t, so f(u)≥tu−f∗(t)f(u) \ge tu - f^*(t) (the Fenchel–Young inequality). Equality holds when t=f′(u)t = f'(u).
    2. Use it at each xx with u=p(x)/q(x)u = p(x)/q(x) and t=T(x)t = T(x), and multiply by q(x)≥0q(x) \ge 0: qf(p/q)≥p T−q f∗(T)q f(p/q) \ge p\,T - q\,f^*(T).
    3. Integrate over xx: Df(P ∥ Q)≥EP[T]−EQ[f∗(T)]D_f(P \,\|\, Q) \ge \mathbb E_P[T] - \mathbb E_Q[f^*(T)] for every TT. A sup over a critic network gives a lower bound; it is tight if the network can represent T∗T^*.
    4. Step 1 is an equality at every xx when T(x)=f′(p(x)/q(x))T(x) = f'(p(x)/q(x)). ■\blacksquare

    KL. For f(u)=ulog⁡uf(u) = u\log u, setting the derivative of tu−ulog⁡utu - u\log u to zero gives t−1−log⁡u=0t - 1 - \log u = 0, so u=et−1u = e^{t-1} and f∗(t)=et−1f^*(t) = e^{t-1}. The bound is KL(P ∥ Q)≥EP[T]−EQ[eT−1]\mathrm{KL}(P \,\|\, Q) \ge \mathbb E_P[T] - \mathbb E_Q[e^{T-1}], with T∗=1+log⁡(p/q)T^* = 1 + \log(p/q).

    The GAN. With f(u)=ulog⁡u−(u+1)log⁡(u+1)f(u) = u\log u - (u + 1)\log(u + 1) and T=log⁡DT = \log D, the bound becomes V(D,G)V(D, G), and Df=2 JSD−log⁡4D_f = 2\,\mathrm{JSD} - \log 4. This ff has f(1)=−log⁡4f(1) = -\log 4, not 0; the proof above never uses f(1)=0f(1) = 0, so the bound still holds. The message: every such critic estimates a function of the density ratio p/qp/q. The details for all common ff are in information theory, lesson 08.

    Wasserstein-1 and the Kantorovich–Rubinstein dual #

    A coupling π∈Π(P,Q)\pi \in \Pi(P, Q) is a joint distribution of (x,y)(x, y) whose marginals are PP and QQ: a plan that says how much mass moves from each xx to each yy. The Wasserstein-1 distance is the cost of the cheapest plan:

    W1(P,Q)=inf⁡π∈Π(P,Q)E(x,y)∼π ∥x−y∥.W_1(P, Q) = \inf_{\pi \in \Pi(P, Q)} \mathbb E_{(x, y) \sim \pi}\,\|x - y\|.

    In 1D, W1=∫∣FP(t)−FQ(t)∣ dtW_1 = \int |F_P(t) - F_Q(t)|\,dt with the cumulative distribution functions FP,FQF_P, F_Q; for point masses at 0 and θ\theta this is ∣θ∣|\theta|. A function ff is 1-Lipschitz (∥f∥L≤1\|f\|_L \le 1) if ∣f(x)−f(y)∣≤∥x−y∥|f(x) - f(y)| \le \|x - y\| for all x,yx, y.

    Theorem (Kantorovich–Rubinstein duality). For P,QP, Q with finite first moments,

    W1(P,Q)=sup⁡∥f∥L≤1  EP[f(x)]−EQ[f(x)].W_1(P, Q) = \sup_{\|f\|_L \le 1}\; \mathbb E_P[f(x)] - \mathbb E_Q[f(x)].

    Proof of the easy half (sup⁡≤inf⁡\sup \le \inf).

    1. Take any coupling π\pi and any 1-Lipschitz ff. Because π\pi has marginals PP and QQ, EP[f]−EQ[f]=Eπ[f(x)−f(y)]\mathbb E_P[f] - \mathbb E_Q[f] = \mathbb E_\pi[f(x) - f(y)].
    2. The Lipschitz condition gives f(x)−f(y)≤∥x−y∥f(x) - f(y) \le \|x - y\|, so this is at most Eπ∥x−y∥\mathbb E_\pi\|x - y\|.
    3. Take the sup over ff on the left and the inf over π\pi on the right. ■\blacksquare

    Equality is the Kantorovich–Rubinstein theorem: strong duality of the transport linear program (see duality).

    Why 1-Lipschitz. Without a constraint the sup is +∞+\infty for any P≠QP \ne Q: multiply a good ff by 100. The Lipschitz bound says the critic can charge at most ∥x−y∥\|x - y\| for mass moved from yy to xx, which ties its value to the transport cost. A KK-Lipschitz bound gives K⋅W1K \cdot W_1, which is fine for training.

    WGAN (Arjovsky, Chintala and Bottou 2017). The critic fwf_w (no sigmoid, no log) maximizes Edata[fw(x)]−Ez[fw(G(z))]\mathbb E_{\text{data}}[f_w(x)] - \mathbb E_z[f_w(G(z))]; the generator minimizes −Ez[fw(G(z))]-\mathbb E_z[f_w(G(z))]. Under mild conditions, ∇θW1(Pdata,Pθ)=−Ez[∇θfopt(Gθ(z))]\nabla_\theta W_1(P_{\text{data}}, P_\theta) = -\mathbb E_z[\nabla_\theta f_{\text{opt}}(G_\theta(z))] with the optimal critic foptf_{\text{opt}} (their Theorem 3).

    The parallel-lines example #

    Let U∼U[0,1]U \sim \mathcal U[0, 1], let P0P_0 be the law of (0,U)(0, U) and PθP_\theta the law of (θ,U)(\theta, U): two parallel segments at horizontal distance ∣θ∣|\theta|.

    • W1=∣θ∣W_1 = |\theta|. Upper bound: the coupling (0,u)↦(θ,u)(0, u) \mapsto (\theta, u) moves every point by ∣θ∣|\theta|. Lower bound: the 1-Lipschitz critic f(x)=−sign⁡(θ) x1f(x) = -\operatorname{sign}(\theta)\,x_1 gives EP0[f]−EPθ[f]=∣θ∣\mathbb E_{P_0}[f] - \mathbb E_{P_\theta}[f] = |\theta|.
    • For θ≠0\theta \ne 0 the supports are disjoint: JSD=log⁡2\mathrm{JSD} = \log 2, KL=+∞\mathrm{KL} = +\infty (both directions), and the total variation distance is 1. All three are 0 at θ=0\theta = 0.

    Only W1W_1 is continuous in θ\theta. Its derivative sign⁡θ\operatorname{sign}\theta points to the answer. The others are flat (or infinite) and then jump at θ=0\theta = 0.

    Interactive figure: loading…

    Move the shift θ\theta. The data segment P0P_0 stays at x1=0x_1 = 0; the model segment PθP_\theta moves. The magenta arrows are the transport plan. In the chart, JSD stays at log⁡2\log 2 for every θ≠0\theta \ne 0, while W1=∣θ∣W_1 = |\theta| shrinks as the segments get closer. Add instance noise τ\tau: the supports now overlap and JSD becomes smooth too, but it is still almost flat far from θ=0\theta = 0.

    Quick check

    For the parallel segments, what are JSD and W1W_1 at θ=0.1\theta = 0.1?

    Making the critic 1-Lipschitz #

    Method What it does Weak points
    Weight clipping (WGAN: c=0.01c = 0.01, RMSProp, ncritic=5n_{\text{critic}} = 5) clip every weight to [−c,c][-c, c]; a bounded weight set gives some unknown constant KK the critic uses its capacity badly (too simple functions); gradients vanish or explode depending on cc
    Gradient penalty (WGAN-GP) add λ Ex^(∥∇xf(x^)∥2−1)2\lambda\,\mathbb E_{\hat x}(\|\nabla_x f(\hat x)\|_2 - 1)^2 at x^=αx+(1−α)x~\hat x = \alpha x + (1 - \alpha)\tilde x, α∼U[0,1]\alpha \sim \mathcal U[0, 1], xx real, x~\tilde x fake soft and local only; needs double backpropagation; invalid with batch norm in the critic
    Spectral normalization divide each weight matrix by its largest singular value (one power-iteration step per update) the bound ∏l∥Wl∥2\prod_l \|W_l\|_2 is loose, so the critic can be far below 1-Lipschitz
    • Why interpolates. A differentiable ff is 1-Lipschitz exactly when ∥∇f∥≤1\|\nabla f\| \le 1 everywhere, and that cannot be enforced everywhere. The optimal critic has gradient norm 1 along the straight lines between points coupled by the optimal transport plan (Gulrajani et al. 2017, Proposition 1), so the penalty samples points on lines between real and fake samples.
    • WGAN-GP defaults: λ=10\lambda = 10, ncritic=5n_{\text{critic}} = 5, Adam with learning rate 10−410^{-4}, β1=0\beta_1 = 0, β2=0.9\beta_2 = 0.9. The penalty is per sample and batch norm mixes samples, so use layer norm or no normalization in the critic.
    • Double backpropagation. The penalty contains ∇xf\nabla_x f, so its gradient with respect to the critic weights differentiates a gradient (in PyTorch: torch.autograd.grad(..., create_graph=True)).
    • Why spectral normalization works. The spectral norm ∥W∥2\|W\|_2 is the Lipschitz constant of x↦Wxx \mapsto Wx. With 1-Lipschitz activations (ReLU, leaky ReLU), Lip(f)≤∏l∥Wl∥2=1\mathrm{Lip}(f) \le \prod_l \|W_l\|_2 = 1. It is cheap, and it also stabilizes ordinary discriminators.
    Why the R1 penalty and WGAN-GP are different

    R1 penalizes ∥∇xl∥2\|\nabla_x l\|^2 on real data only and pushes it toward 0. Near the equilibrium, where the generator matches the data, a discriminator with zero slope on the data is exactly what we want, so R1 does not move the equilibrium; it only damps the rotation of the game (the −γ-\gamma in the Jacobian above). WGAN-GP pushes the gradient norm toward 1 on interpolates, because the optimal Wasserstein critic has slope 1 along transport lines. StyleGAN2 and many modern GANs use the non-saturating loss with R1.

    Answers to section 1. (1) The gradient is −σ(−8)≈−3.4×10−4-\sigma(-8) \approx -3.4 \times 10^{-4}: almost zero. This is why the non-saturating loss is used. (2) JSD=log⁡2≈0.693\mathrm{JSD} = \log 2 \approx 0.693 for both θ=1\theta = 1 and θ=0.1\theta = 0.1; W1=1W_1 = 1 and 0.10.1. Only W1W_1 tells the generator that it got closer. (3) They move away: simultaneous steps multiply the distance by 1+η2/4>1\sqrt{1 + \eta^2/4} > 1 per step near the equilibrium. Alternating steps circle, and only a penalty such as R1 makes them converge.

    4. Worked example #

    (a) Optimal discriminator. pdata=(0.6,0.4,0)p_{\text{data}} = (0.6, 0.4, 0) and pg=(0.2,0.4,0.4)p_g = (0.2, 0.4, 0.4).

    1. D∗=pdata/(pdata+pg)D^* = p_{\text{data}}/(p_{\text{data}} + p_g) on each outcome: 0.6/0.8=0.750.6/0.8 = 0.75, 0.4/0.8=0.50.4/0.8 = 0.5 and 0/0.4=00/0.4 = 0.
    2. V(D∗,G)V(D^*, G) is ∑pdatalog⁡D∗\sum p_{\text{data}}\log D^* plus ∑pglog⁡(1−D∗)\sum p_g \log(1 - D^*). The term 0⋅log⁡00 \cdot \log 0 counts as 0:
    V=0.6log⁡0.75+0.4log⁡0.5+0.2log⁡0.25+0.4log⁡0.5+0.4log⁡1=−1.004386.\begin{aligned} V &= 0.6\log 0.75 + 0.4\log 0.5 \\ &\quad + 0.2\log 0.25 + 0.4\log 0.5 + 0.4\log 1 \\ &= -1.004386. \end{aligned}
    1. The average is m=(0.4,0.4,0.2)m = (0.4, 0.4, 0.2). Then KL(pdata ∥ m)=0.6log⁡1.5=0.243279\mathrm{KL}(p_{\text{data}} \,\|\, m) = 0.6\log 1.5 = 0.243279 and KL(pg ∥ m)=0.2log⁡0.5+0.4log⁡2=0.138629\mathrm{KL}(p_g \,\|\, m) = 0.2\log 0.5 + 0.4\log 2 = 0.138629 (the terms with ratio 1 are 0).
    2. JSD is the mean of the two KL values: JSD=0.190954\mathrm{JSD} = 0.190954.
    3. Check: −log⁡4=−1.386294-\log 4 = -1.386294 and 2⋅0.190954=0.3819082 \cdot 0.190954 = 0.381908. The sum is −1.004386-1.004386. ✓

    (b) f-GAN bound for KL on the same pair (P=pdataP = p_{\text{data}}, Q=pgQ = p_g).

    1. KL(P ∥ Q)=0.6log⁡3=0.659167\mathrm{KL}(P \,\|\, Q) = 0.6\log 3 = 0.659167 (the second term is 0.4log⁡1=00.4\log 1 = 0).
    2. The optimal critic is T∗=1+log⁡(p/q)T^* = 1 + \log(p/q). On the three outcomes: 1+log⁡31 + \log 3, 11 and −∞-\infty. On outcome 3 it must be −∞-\infty, because PP never visits it.
    3. A real network outputs a finite value there. Take T=(1+log⁡3, 1, 0)T = (1 + \log 3,\ 1,\ 0). Then EP[T]=0.6⋅2.098612+0.4⋅1=1.659167\mathbb E_P[T] = 0.6 \cdot 2.098612 + 0.4 \cdot 1 = 1.659167.
    4. EQ[eT−1]=0.2⋅3+0.4⋅1+0.4 e−1\mathbb E_Q[e^{T-1}] = 0.2 \cdot 3 + 0.4 \cdot 1 + 0.4\,e^{-1}, which is 1.1471521.147152.
    5. The bound is 1.659167−1.147152=0.5120161.659167 - 1.147152 = 0.512016. It is below KL. The gap is exactly the term q3 eT3−1=0.4 e−1=0.147152q_3\,e^{T_3 - 1} = 0.4\,e^{-1} = 0.147152 that the finite value T3=0T_3 = 0 adds.

    (c) A Wasserstein critic for two Gaussians. P=N(μ1,Σ)P = \mathcal N(\mu_1, \Sigma) and Q=N(μ2,Σ)Q = \mathcal N(\mu_2, \Sigma) with μ1=(1,2)\mu_1 = (1, 2) and μ2=(4,6)\mu_2 = (4, 6).

    1. Translation by μ1−μ2\mu_1 - \mu_2 is a coupling that moves every point by ∥μ1−μ2∥=∥(−3,−4)∥=5\|\mu_1 - \mu_2\| = \|(-3, -4)\| = 5, so W1≤5W_1 \le 5.
    2. The linear critic f(x)=w⊤xf(x) = w^\top x with ∥w∥=1\|w\| = 1 is 1-Lipschitz and has value w⊤(μ1−μ2)≤5w^\top(\mu_1 - \mu_2) \le 5 (Cauchy–Schwarz), with equality at w=(−0.6,−0.8)w = (-0.6, -0.8). So W1=5W_1 = 5.
    3. Now use the gradient penalty with λ=10\lambda = 10 instead of the hard constraint, and let the critic be w=r (−0.6,−0.8)w = r\,(-0.6, -0.8). Its gradient norm is rr everywhere, so the penalized objective is 5r−10(r−1)25r - 10(r - 1)^2.
    4. Set the derivative to zero: 5−20(r−1)=05 - 20(r - 1) = 0, so r=1.25r = 1.25, and the value is 6.25−10⋅0.0625=5.6256.25 - 10 \cdot 0.0625 = 5.625.
    5. In general, for a linear critic and two distributions that differ by a shift of length WW, r∗=1+W/(2λ)r^* = 1 + W/(2\lambda) and the value is W+W2/(4λ)W + W^2/(4\lambda). A soft penalty lets the gradient norm go above 1 and overestimates W1W_1 a little. An unconstrained w=(−3,−4)w = (-3, -4) would pay the penalty 10(5−1)2=16010(5 - 1)^2 = 160.
    Quick check

    In example (c), the shift has length W=5W = 5 and you use λ=100\lambda = 100 instead of 10. What is the penalized value at the best rr?

    5. In code #

    NumPy and SciPy check the numbers of sections 3 and 4: the optimal discriminator, the logit gradients (against finite differences), the Dirac-GAN, and the exact W1W_1 of the parallel segments (an optimal assignment between equal-size samples is an optimal transport plan).

    import numpy as np
    from scipy.special import expit as sigmoid, rel_entr
    from scipy.spatial.distance import jensenshannon
    from scipy.optimize import linear_sum_assignment
    
    # (a) optimal discriminator, V(D*) and JSD for the three-outcome example
    p = np.array([0.6, 0.4, 0.0])                       # p_data
    q = np.array([0.2, 0.4, 0.4])                       # p_g
    D = p / (p + q)
    V = rel_entr(p, p + q).sum() + rel_entr(q, p + q).sum()   # sum p log D* + sum q log(1 - D*)
    jsd = jensenshannon(p, q) ** 2                      # SciPy returns the square root of JSD
    print(D, round(V, 6), round(-np.log(4) + 2 * jsd, 6))
    # [0.75 0.5  0.  ] -1.004386 -1.004386
    
    # (b) generator-loss gradients with respect to the logit l, checked by finite differences
    softplus = lambda u: np.logaddexp(0.0, u)
    sat = lambda l: -softplus(l)                        # log(1 - sigmoid(l))
    ns = lambda l: softplus(-l)                         # -log sigmoid(l)
    l, h = -8.0, 1e-6
    for f, exact in [(sat, -sigmoid(l)), (ns, -sigmoid(-l))]:
        print(f"{exact:.6f} {(f(l + h) - f(l - h)) / (2 * h):.6f}")
    # -0.000335 -0.000335
    # -0.999665 -0.999665
    
    # (c) Dirac-GAN: simultaneous vs alternating gradient steps from (theta, psi) = (1, 0)
    def dirac(eta=0.1, n=2000, alternating=False, gamma=0.0):
        th, ps = 1.0, 0.0
        for _ in range(n):
            g_th = ps * sigmoid(ps * th)                # -dV/dtheta (generator descends V)
            if alternating:
                th = th + eta * g_th
            g_ps = -th * sigmoid(ps * th) - gamma * ps  # dV/dpsi minus the R1 term (discriminator ascends)
            if not alternating:
                th = th + eta * g_th
            ps = ps + eta * g_ps
        return np.hypot(th, ps)
    print(round(dirac(), 2), round(dirac(alternating=True), 2), dirac(gamma=1.0) < 1e-10)
    # 3.05 0.99 True
    
    # (d) parallel lines: exact W1 between 200 + 200 samples (optimal assignment)
    u = (np.arange(200) + 0.5) / 200
    for theta in [1.0, 0.1]:
        a = np.stack([np.zeros(200), u], 1)
        b = np.stack([np.full(200, theta), u], 1)
        C = np.linalg.norm(a[:, None] - b[None], axis=2)
        r, c = linear_sum_assignment(C)
        print(theta, round(C[r, c].mean(), 4))
    # 1.0 1.0
    # 0.1 0.1
    

    The notebook adds the continuous version of (a) by quadrature, W1W_1 of 1D samples by sorting, a WGAN-GP critic trained by gradient ascent, and an optional tiny GAN on the 8 Gaussians in PyTorch.

    6. Where it shows up #

    • Adversarial losses inside other generators. The autoencoder of latent diffusion is trained with a perceptual loss plus a patch-based adversarial loss (Rombach et al. 2022, §3.1), so the latent space of lesson 13 was shaped by a GAN loss. Adversarial diffusion distillation uses a discriminator to get samplers with 1–4 steps (lesson 12). StyleGAN-type models use the non-saturating loss with the R1 penalty.
    • Super-resolution and image-to-image translation. SRGAN, pix2pix and CycleGAN add an adversarial loss to a reconstruction loss. The adversarial part makes the output sharp; the reconstruction part keeps it faithful to the input.
    • Weather and climate. DGMR (Ravuri et al., Nature 2021) nowcasts precipitation with a conditional GAN that has a spatial and a temporal discriminator. In an ensemble, mode collapse means an under-dispersed ensemble: the spread is too small, and the CRPS and the rank histogram show it (lesson 14). This is one reason recent ensemble weather models use diffusion.
    • Seismology. Florez et al. (BSSA 2022) generate three-component accelerograms with a conditional Wasserstein GAN, conditioned on magnitude, distance and VS30V_{S30}. The same task is now also done with (latent) diffusion and flow models.
    • Density ratios in science. "Train a classifier, read off p/qp/q" also drives neural ratio estimation for likelihood-free inference in particle physics and cosmology.

    7. Common mistakes #

    • log(sigmoid(l)) in code. It gives −∞-\infty or NaN for large ∣l∣|l|. Use the softplus forms or a fused "binary cross-entropy with logits" function.
    • Not detaching the fakes in the discriminator step. Then the DD loss also sends gradients into GG: wasted compute, and wrong GG updates if those gradients are not zeroed before the GG step.
    • Reading C(G)=−log⁡4+2 JSDC(G) = -\log 4 + 2\,\mathrm{JSD} as what training minimizes. It holds only for the optimal DD, and the non-saturating loss is a different game with the same fixed point.
    • Expecting gradient play to converge like gradient descent. A game has a vector field, not a loss surface. Its Jacobian can have imaginary eigenvalues (the Dirac-GAN), and then plain gradient steps rotate or spiral out. A smaller learning rate does not fix this.
    • A sigmoid or a log on the WGAN critic. The critic outputs unbounded scores; the losses are plain means.
    • Gradient-penalty slips. The penalty uses ∇xf(x^)\nabla_x f(\hat x) (with respect to the inputs, not the weights), and batch norm in the critic breaks the per-sample penalty.
    • Using the GAN loss as a quality metric. Discriminator and generator losses oscillate and say little about sample quality or coverage. Use FID, precision and recall (lesson 14).
    • Blaming mode collapse only on JSD. GANs that approximate KL(pdata ∥ pg)\mathrm{KL}(p_{\text{data}} \,\|\, p_g) collapse too (Goodfellow 2016, §5.1.1); the game dynamics matter as much as the divergence.

    8. Check yourself #

    1. pdatap_{\text{data}} and pgp_g have disjoint supports. Give D∗D^*, C(G)C(G), and the generator gradient of the saturating loss near the samples.
      AnswerD∗=1D^* = 1 on the data support and 00 on the generator support. JSD=log⁡2\mathrm{JSD} = \log 2, so C(G)=−log⁡4+2log⁡2=0C(G) = -\log 4 + 2\log 2 = 0, the same for every disjoint pgp_g. DD is constant near the samples, so ∇xD=0\nabla_x D = 0 and the generator gets no gradient.
    2. The data are three equal modes, pdata=(13,13,13)p_{\text{data}} = (\tfrac13, \tfrac13, \tfrac13), and the generator collapses to the first: pg=(1,0,0)p_g = (1, 0, 0). Compute JSD, KL(pg ∥ pdata)\mathrm{KL}(p_g \,\|\, p_{\text{data}}) and KL(pdata ∥ pg)\mathrm{KL}(p_{\text{data}} \,\|\, p_g). Which one punishes the collapse most?
      Answerm=(23,16,16)m = (\tfrac23, \tfrac16, \tfrac16); KL(pdata ∥ m)=13log⁡12+23log⁡2\mathrm{KL}(p_{\text{data}} \,\|\, m) = \tfrac13\log\tfrac12 + \tfrac23\log 2, which is 13log⁡2=0.2310\tfrac13\log 2 = 0.2310, KL(pg ∥ m)=log⁡1.5=0.4055\mathrm{KL}(p_g \,\|\, m) = \log 1.5 = 0.4055, so JSD=0.3183\mathrm{JSD} = 0.3183. Reverse KL: log⁡3=1.0986\log 3 = 1.0986 (finite). Forward KL: +∞+\infty, because pg=0p_g = 0 where the data have mass. Forward KL (maximum likelihood) punishes the collapse most; reverse KL and JSD give finite penalties (JSD is at most log⁡2\log 2).
    3. In the Dirac-GAN with simultaneous steps, compute the growth factor per step near (0,0)(0, 0) for η=0.1\eta = 0.1, and estimate the distance after 100 steps from a start at distance 0.010.01.
      Answer1+0.01/4=1.0025=1.00125\sqrt{1 + 0.01/4} = \sqrt{1.0025} = 1.00125. Near (0,0)(0, 0) the linearization is accurate, so after 100 steps the distance is about 0.01⋅1.00125100=0.01⋅1.133=0.01130.01 \cdot 1.00125^{100} = 0.01 \cdot 1.133 = 0.0113. Far from (0,0)(0, 0) the sigmoid factor changes and the growth slows down (the full nonlinear run from distance 1 reaches only 3.05 after 2000 steps).
    4. In the KL bound, use the critic T=T∗+cT = T^* + c for a constant cc. Show that the bound equals KL+1+c−ec\mathrm{KL} + 1 + c - e^{c}, and conclude where it is tight.
      AnswerEP[T∗+c]=1+KL+c\mathbb E_P[T^* + c] = 1 + \mathrm{KL} + c, because EP[log⁡(p/q)]=KL\mathbb E_P[\log(p/q)] = \mathrm{KL}. And EQ[eT∗+c−1]=ec EQ[p/q]=ec\mathbb E_Q[e^{T^* + c - 1}] = e^{c}\,\mathbb E_Q[p/q] = e^{c}. So the bound is KL+1+c−ec\mathrm{KL} + 1 + c - e^{c}. Since ec≥1+ce^{c} \ge 1 + c, it is at most KL, with equality only at c=0c = 0.
    5. A ReLU critic has three layers with spectral norms 2, 0.5 and 3. Give a Lipschitz bound before and after spectral normalization. Can the true constant be smaller?
      AnswerBefore: 2⋅0.5⋅3=32 \cdot 0.5 \cdot 3 = 3. After: 11. Yes: the bound is tight only if the top singular directions of consecutive layers line up and the ReLUs pass them unchanged. Usually neither holds, so the true constant is often much smaller than the product.
    6. Why is the WGAN-GP penalty evaluated on random interpolates between real and fake samples, and not only on real data or on a fixed grid?
      AnswerThe optimal critic has unit gradient norm along the straight lines between optimally coupled real and fake points (Gulrajani et al., Proposition 1). Enforcing ∥∇f∥≤1\|\nabla f\| \le 1 everywhere is impossible in high dimension. Lines between real and fake samples are a cheap proxy for the region where the constraint is active (the pairs are random, not optimally coupled), and they move with the generator during training. Real data alone would leave the region between the two distributions unconstrained.
    Recall cardsAnswer in your head first, then reveal. Add the cards to your review deck to see them again just before you would forget.
    1. What is the optimal discriminator D∗(x)D^*(x) of the original GAN game for a fixed generator?

    2. What is C(G)=max⁡DV(D,G)C(G) = \max_D V(D, G) in terms of a divergence, and its minimum?

    3. What are the gradients of the saturating and the non-saturating generator loss with respect to the logit ll of a fake?

    4. Why does JSD give no gradient when the data and the generator have disjoint supports?

    5. What is mode collapse?

    6. Why do simultaneous gradient steps not converge in the Dirac-GAN?

    7. State the f-GAN lower bound and its optimal critic.

    8. State the Kantorovich–Rubinstein dual of W1W_1.

    9. What is the WGAN-GP penalty, and where is it evaluated?

    10. For two parallel segments at distance θ≠0\theta \ne 0, what are JSD and W1W_1?

    Open the review →

    9. Interview angle #

    • "What does the discriminator learn at the optimum?" D∗=pdata/(pdata+pg)D^* = p_{\text{data}}/(p_{\text{data}} + p_g), so D∗/(1−D∗)D^*/(1 - D^*) is the density ratio. The game then minimizes 2 JSD−log⁡42\,\mathrm{JSD} - \log 4.
    • "Why the non-saturating loss?" The minimax gradient with respect to the logit is −σ(l)≈0-\sigma(l) \approx 0 when DD rejects fakes; the non-saturating one is −σ(−l)≈−1-\sigma(-l) \approx -1. Same fixed point.
    • "Why is GAN training unstable?" Three reasons: the divergence can be flat (disjoint supports), the game dynamics rotate (imaginary eigenvalues; the Dirac-GAN), and the best response to a fixed DD is a point mass (mode collapse).
    • "Why does WGAN help?" W1W_1 is continuous in the generator parameters even for disjoint supports (parallel lines), so the critic gives a useful gradient and a loss that tracks progress.
    • "How do you enforce the Lipschitz constraint?" Clipping (crude), a gradient penalty on interpolates (λ=10\lambda = 10, no batch norm), spectral normalization (cheap, loose bound).
    • "GAN or diffusion for an ensemble forecast?" A GAN needs one network pass per sample, but it can collapse modes and give an under-dispersed ensemble. Diffusion trains by stable regression and covers modes better, at the cost of many network evaluations per sample.
    • "How do you detect mode collapse?" Recall or coverage metrics, nearest training neighbors, counting modes on a toy mixture, class histograms with a pretrained classifier.

    10. Practice #

    The notebook for this lesson has five exercises, each with a check cell and a folded solution, and an optional PyTorch demonstration:

    1. D∗D^*, the value V(D∗)V(D^*) and JSD for discrete distributions; then the same identity for two 1D densities by quadrature.
    2. Saturating and non-saturating losses and their gradients in the logit, written in a stable form.
    3. The Dirac-GAN: simultaneous, alternating and R1 steps; plot the three trajectories.
    4. The f-GAN bound for KL: write the bound for a critic vector and find the critic that makes it equal to KL.
    5. W1W_1 of two 1D samples by sorting, and the WGAN-GP optimum of a linear critic, r∗=1+W/(2λ)r^* = 1 + W/(2\lambda).
    6. Optional (PyTorch): a tiny GAN on the 8 Gaussians; count the covered modes during training.

    11. Watch and read #

    The GAN game, the optimal discriminator and the link to the Jensen–Shannon divergence, derived step by step.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    A full lecture on GANs: the original game, training problems, and the main fixes and architectures.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    The second GAN lecture: f-GAN, Wasserstein GAN, the gradient penalty and spectral normalization.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play