Part XIII — Generative Models: VAEs, Flow Matching, Score Models & Diffusion Transformers · Chapter 4

Normalizing flows & invertible transformations

Hook

Part IV's GAN — short for Generative Adversarial Network — and Part X's VAE — short for Variational Autoencoder — both generate samples from a simple noise source, but neither one tells you the exact probability of any particular output — a VAE only bounds it, a GAN doesn't define one at all. What if the generator were built so that density stayed exactly computable, every step of the way?

Intuition
z = 0.50 → x = 0.250, stretch |df/dz| = 1.00, density = 1.000

Drag zz. The point traces out the density curve for x=z2x=z^2 — not because it's been fit to data, but because it's derived, exactly, from how much ff stretches space at that zz.

Formalize

A normalizing flow builds pXp_X from a trivial base density pZp_Z by pushing it through an invertible, differentiable function x=f(z)x = f(z). In one dimension, the change-of-variables formula says exactly how the density transforms:

pX(x)=pZ(f1(x))df/dz,evaluated at z=f1(x)p_X(x) = \frac{p_Z\big(f^{-1}(x)\big)}{\left|\, df/dz \,\right|}, \qquad \text{evaluated at } z = f^{-1}(x)
  • pX(x)p_X(x) — the density of the generated data xx, computed exactly rather than merely bounded or left undefined.
  • pZ(z)p_Z(z) — the trivial base density (e.g. uniform) that the flow starts from.
  • ff — the invertible, differentiable function (the flow) that maps a base-space point zz to a data-space point xx.
  • f1(x)f^{-1}(x) — the flow's inverse, recovering the base-space point zz that produced a given xx.
  • df/dzdf/dz — the derivative of ff at zz (in higher dimensions, the Jacobian determinant), measuring how much the flow stretches or compresses space there.
  • xx, zz — a point in data space and its corresponding point in the simple base (latent) space.
  1. Stretching lowers density

    Wherever ff stretches space (df/dz>1|df/dz|>1), the same probability mass spreads over a wider region, so density there goes down.

  2. Compressing raises density

    Wherever ff compresses space (df/dz<1|df/dz|<1), density goes up — the same mass is packed into a narrower region.

  3. Total probability is conserved

    Mass is only ever redistributed, never created or destroyed — which is exactly what makes the density exactly computable instead of merely bounded.

Play
dashed: Z ~ Uniform(0,1), flat everywhere. Bold: X = Z², concentrated near 0 — same probability mass, redistributed by the flow

ZUniform(0,1)Z\sim\text{Uniform}(0,1) starts perfectly flat. Squaring it compresses space near z=0z=0 (small numbers get squeezed together even harder by squaring) and stretches space near z=1z=1 — so density piles up near x=0x=0 and thins out near x=1x=1, with no information lost anywhere in between.

Worked example

The flow x=z2x = z^2, evaluated at two points:

  1. x = 0.25

    z=f1(0.25)=0.25=0.5z = f^{-1}(0.25) = \sqrt{0.25} = 0.5. df/dz=2(0.5)=1df/dz = 2(0.5) = 1 — no stretching or compressing at all here. pX(0.25)=1/1=1p_X(0.25) = 1/1 = 1, identical to the base density.

  2. x = 0.04

    z=0.04=0.2z = \sqrt{0.04} = 0.2. df/dz=2(0.2)=0.4df/dz = 2(0.2) = 0.4 — space is compressed to less than half its width here. pX(0.04)=1/0.4=2.5p_X(0.04) = 1/0.4 = 2.5, two and a half times denser than the flat base.

Checkpoint

Find the value of x, among the four candidates, with the highest transformed density.

Pick a value of x to try it
Summary
pX(x)=pZ(f1(x))df/dzp_X(x) = \frac{p_Z(f^{-1}(x))}{|df/dz|}

This chapter's flow was one fixed function on one variable, invertible by inspection. Real normalizing flows chain many learned, carefully-designed invertible layers (each engineered so its Jacobian determinant stays cheap to compute even in hundreds of dimensions) to turn a simple base distribution into something that can match real image or audio data — trading the VAE's approximate likelihood and the GAN's absent one for an exact number, at the cost of every layer having to stay invertible. The next chapter drops the invertibility requirement entirely and asks a different question: instead of an exact formula for the density, what if a model just learned which direction increases it?