How a chain of invertible maps turns a spherical Gaussian into a model with an exact likelihood, why the Jacobian determinant appears in the change-of-variables formula, and why flows insist on triangular Jacobians.
A GAN produces samples but cannot tell us how likely a given image is. A VAE can, but only through a lower bound. Normalizing flows take a third route (Rezende and Mohamed, 2015; Papamakarios et al., 2021; Kobyzev, Prince and Brubaker, 2021): start from a simple density, push it through an invertible map, and compute the density of the result exactly with the change-of-variables formula. This note builds that formula, stacks it into a flow, compares flows with the other model families, and ends with the trick that makes flows computable: a triangular Jacobian. How to build layers with that property is the subject of the next note, Flow architectures.
Notation. The map f always goes from the latent space to the data space, f:Z→X, so x=f(z) generates data and z=f−1(x) encodes it. pZ is the base (latent) density and pθ(x) the model density of the data. For a map g, Jg(u)=∂g(u)/∂u is its Jacobian matrix at the point u.
Take a continuous random variable z with a simple density, a spherical Gaussian:
z∼pZ(z)=N(z;0,I).
“Spherical” means the covariance is a multiple of the identity (here exactly I): the same spread in every direction and spherical contours. The data are produced by a chain of K maps,
x=fθ(z)=fK∘⋯∘f2∘f1(z),
and each fi is invertible (bijective): every point of the output space is the image of exactly one input point. For the density formula below, each fi must also be differentiable with a differentiable inverse (a diffeomorphism). Then the whole chain is invertible too, with f−1=f1−1∘f2−1∘⋯∘fK−1. A diffeomorphism needs dimz=dimx. The chain rule applied to f−1∘f=id and f∘f−1=id gives Jf−1Jf=I and JfJf−1=I, and a product of an m×n and an n×m matrix has rank at most min(m,n), so both identities can hold only when m=n. Unlike in a VAE, the latent vector is therefore as large as the data.
Figure
Every point of Z has exactly one partner in X
The flow f carries each latent point z to a data point x = f(z) (blue, left to right), and the inverse f⁻¹ carries it back (green, right to left). Because every fᵢ in the chain is a bijection, no two points of Z land on the same x and no x is left without a preimage. The X positions are computed from the same invertible 2-D map that is used later to show the Jacobian as local geometry.
We want pθ(x). The first guess is to map x back and read off the base density, pθ(x)=?pZ(f−1(x)). This is wrong, because the answer depends on how f behaves: on how much it stretches or squeezes space around each point.
A one-line counterexample: in one dimension let z∼N(0,1) and x=f(z)=2z. The naive guess gives pZ(x/2), which integrates to 2 over the real line, so it is not even a density. The true distribution is x∼N(0,4) with density pZ(x/2)/2. At x=1 the naive value is 0.352 and the correct one is 0.176: f spreads the same probability over twice the length, so the density must halve.
Let f:Z→X be invertible, differentiable and with a differentiable inverse, and let pZ(z) be a density defined over z∈Z.
One dimension. Probability mass is conserved. A small interval of width ∣dz∣ around z holds mass pZ(z)∣dz∣, and f sends it to an interval of width ∣dx∣ around x=f(z) that must hold the same mass:
pθ(x)∣dx∣=pZ(z)∣dz∣,
so
pθ(x)=pZ(z)dxdz=∣f′(f−1(x))∣pZ(f−1(x)).
Any dimension. Widths become volumes, and we need the factor by which f changes a small volume. Close to a point z the map is approximately linear, f(z+δ)≈f(z)+Jf(z)δ, with the Jacobian matrix
where f(1),…,f(d) are the output coordinates of f: row k of Jf holds the partial derivatives of output k, column j those with respect to input zj. A tiny cube with side ε at z, spanned by the vectors εe1,…,εed, is therefore sent to a tiny parallelepiped spanned by εJf(z)e1,…,εJf(z)ed, that is, by the columns of Jf(z) scaled by ε. The volume of the parallelepiped spanned by the columns of a matrix A is ∣detA∣, so f multiplies small volumes near z by ∣detJf(z)∣. In two dimensions a small square becomes a small parallelogram whose area is ∣detJf(z)∣ times the area of the square.
Figure
The Jacobian is local geometry
A square grid in Z pushed through an invertible nonlinear map f. Here f(z) = (z₁ + 0.35·sin(1.2·b), b) with b = z₂·e^(0.35·z₁) + 0.2·z₁, so det J_f(z) = e^(0.35·z₁). Each small cell becomes an almost-parallelogram. Its area is multiplied by |det J_f| at that point: the amber cell (z₁ ≈ −1.25) shrinks to 0.65 of its area (det ≈ 0.65), and the red cell (z₁ ≈ 1.25) grows to 1.55 times its area (det ≈ 1.55).
Mass is conserved as in one dimension: a cube of volume εd holds mass pZ(z)εd, and its image of volume ∣detJf(z)∣εd must hold the same mass. Hence, with z=f−1(x),
The two forms say the same thing. The Jacobian of the inverse is evaluated at the data point, while the Jacobian of f is evaluated at the latent point z=f−1(x). They are linked by the inverse function theorem, Jf−1(x)=[Jf(z)]−1, and det(A−1)=1/detA. The factor ∣detJf∣ measures the expansion or contraction of space around the point (Papamakarios et al., 2021, §2.1). Where f expands space, the same probability is spread thinner and the density drops; where f contracts space, the density rises:
∣detJf∣=2: volumes are doubled and the density is halved;
∣detJf∣=0.5: volumes are halved and the density is doubled;
∣detJf∣=1: volumes are preserved (the shape may still change), and so is the density;
detJf=0: the volume is crushed to zero. The linear map Jf(z) is not invertible, and then f has no differentiable inverse at f(z), since a differentiable inverse would give Jf−1Jf=I. The density factor 1/∣detJf∣ is infinite there, and the formula above does not apply. Flow layers are therefore built with detJf=0 everywhere.
Figure
What |det J| does to a small square
The dashed unit square and its image (filled) under four linear maps. |det J| is the factor by which areas, and in d dimensions volumes, are multiplied. A shear can change the shape completely and still have det = 1. When det = 0 the square collapses onto a segment: two dimensions are squeezed into one, the linear map cannot be inverted. A layer with det J = 0 at a point has no differentiable inverse there, so it falls outside the change-of-variables formula, which is why flow layers keep det J ≠ 0 everywhere.
Base density p_Z = N(0, 1) (bottom), the monotone flow x = f(z) = z + 0.8·tanh(2z) (centre) and the resulting model density p_θ(x) = p_Z(f⁻¹(x)) / f′(f⁻¹(x)) (right, drawn sideways). The slab z ∈ [0.1, 0.5] holds probability 0.152; f stretches it to x ∈ [0.258, 1.109], about 2.13 times wider, so the density there must be lower by the same factor. Near the origin f′(0) = 2.6, which turns the single Gaussian bump into two bumps.
Take pZ=N(0,1) and the map in the figure,
f(z)=z+0.8tanh(2z),f′(z)=1+1.6sech2(2z)>0.
The derivative is positive everywhere, so f is strictly increasing and therefore invertible (the inverse has no closed form but is easy to find numerically). Then pθ(x)=pZ(z)/f′(z) with z=f−1(x):
z
x=f(z)
f′(z)
pZ(z)
pθ(x)=pZ(z)/f′(z)
0
0
2.600
0.3989
0.1534
0.5
1.109
1.672
0.3521
0.2106
1
1.771
1.113
0.2420
0.2174
2
2.799
1.002
0.0540
0.0539
Near the origin f stretches space by a factor of 2.6, so the density there falls well below the Gaussian peak; in the tails f′≈1 and the density is almost unchanged. The single bump becomes two bumps with maxima at x≈±1.50 (that is z≈±0.77), pθ≈0.234. Even one smooth invertible map can turn a unimodal base into a bimodal model. In log form, at z=0.5: logpθ(x)=logpZ(z)−logf′(z)=−1.044−0.514=−1.558.
The slab z∈[0.1,0.5] holds probability Φ(0.5)−Φ(0.1)=0.152. Its image is x∈[0.258,1.109], 2.13 times wider, so the average density over it drops from 0.379 to 0.178, by the same factor: same probability mass, different width.
The simplest multivariate case is a linear map x=Jz, whose Jacobian ∂x/∂z=J is the same everywhere. With
J=[2002]
every direction is stretched 2 times, and detJ=2⋅2−0⋅0=4. A unit square of Z becomes a 2×2 square of X, so
pθ(x)=pZ(z)det(∂z∂x)1=4pZ(z).
Check with z∼N(0,I) in two dimensions: x=2z∼N(0,4I), and indeed pθ(0)=2π⋅41=0.0398=41⋅2π1.
Orientation does not matter. For
J=[200−2],detJ=−4,
the square is also mirrored, but its area is still 4. The sign of the determinant records orientation; the change of volume, and hence of density, uses only ∣detJ∣=4. That is why the formula has an absolute value.
Figure
A Jacobian that stretches each direction by a factor of 2
Top: J = diag(2, 2) sends the unit square of Z to a 2 × 2 square in X. The area grows from 1 to det J = 4, so the same probability is spread over four times the area and the density drops to a quarter: p_θ(x) = p_Z(z) / |det J|. Bottom: J = diag(2, −2) also flips the second axis. The amber quarter-turn marker now runs clockwise, det J = −4, but the area and the density factor depend only on |det J| = 4.
Now apply the formula to the whole chain z∼pZ(z), x=fθ(z)=fK∘⋯∘f2∘f1(z). Name the intermediate points
z0=z,zi=fi(zi−1)(i=1,…,K),
so that zK=x. The inverse runs the chain backwards, f−1=f1−1∘⋯∘fK−1, and by the chain rule its Jacobian is a product of the layer Jacobians, each taken at its own intermediate point: Jf−1(x)=Jf1−1(z1)Jf2−1(z2)⋯JfK−1(zK). Since det(AB)=detAdetB,
To evaluate it we push x backwards through the layers, zK=x→zK−1→⋯→z0, and collect one determinant per layer. This construction is a normalizing flow: the density flows through a sequence of invertible maps, and read backwards the chain normalizes the data, turning it (approximately, once the model fits) into a sample of the standard normal base. The name was popularized in machine learning by Rezende and Mohamed (2015), building on earlier work on density estimation by transforming data towards a Gaussian (Tabak and Vanden-Eijnden, 2010). Rezende and Mohamed’s flows were planar and radial maps, whose determinants are cheap for a different reason than the triangular layers below (Flow architectures, part G).
Sampling needs only the forward direction: draw z∼N(0,I) and compute x=fθ(z); evaluating a density needs the inverse. Which of the two is cheap depends on the architecture: masked autoregressive flows (MAF; Papamakarios, Pavlakou and Murray, 2017) evaluate densities fast and sample slowly, inverse autoregressive flows (IAF; Kingma et al., 2016) the reverse, and coupling layers make both cheap (see Flow architectures). Sampling turns a simple z into a sample of a complicated distribution; the density formula is what lets us fitfθ so that this distribution matches the data.
This is an exact log-likelihood evaluation, with no bound and no sampling. Training is plain maximum likelihood, which minimizes the forward KL divergence from the data distribution to the model (why cross-entropy is the loss we minimize). As in the fitting note, the data density is unknown, so we minimize the negative log-likelihood over the dataset x(1),…,x(N), now with a neural model:
where zi(n) are the intermediate points of x(n): zK(n)=x(n) and zi−1(n)=fi−1(zi(n)), so that z0(n)=fθ−1(x(n)).
The two terms pull against each other. The first wants every encoded point near the centre of the Gaussian. The second penalizes the inverse for squeezing space, so the model cannot score well by collapsing all the data to z=0.
Images: dequantization, rescaling and bits per dimension#
Optional depth: the preprocessing that turns a flow’s density on images into a reported number of bits per dimension, with a worked offset check. The rest of the note does not depend on it.
The formula gives a density, so it is exact for continuous data. Images are discrete, for example 8-bit pixel values x∈{0,…,255}d, and a continuous density could put arbitrarily high values on those points: a flow fitted to the raw values can push its likelihood up without bound by squeezing its mass onto them. Flows are therefore trained on dequantized data x~=x+u with uniform noise u∼U[0,1)d. The probability the model gives to the discrete value x is P(x)=∫[0,1)dpθ(x+u)du, and Jensen’s inequality gives Eu[logpθ(x+u)]≤logP(x): the continuous log-likelihood of the dequantized data is a lower bound on the discrete log-likelihood (Theis, van den Oord and Bethge, 2016).
Bits per dimension. Image likelihoods are reported as −log2P(x)/d, the number of bits per coordinate that a lossless code built from the model needs (bits per dimension in the autoregressive note). A model that spreads its probability evenly over the 256 values scores exactly 8. For a flow the reported number is −Eu[log2pθ(x+u)]/d, which by the inequality above is an upper bound on the discrete value.
Rescaling changes the density. Networks are rarely fed pixel values in [0,256). A common choice is x′=x~/127.5−1, which puts the data roughly in [−1,1]. The flow then models the density of x′, and the change of variables relates it to the density of x~: the map x~↦x′ has the constant Jacobian 127.51I, so
The bits per dimension in pixel units are those in model units plus log2127.5≈6.99. In general, if one quantization level has width a after preprocessing, the offset is −log2a bits per dimension (Kingma and Dhariwal, 2018, §2, eq. 2): log2255≈7.99 for x/255, as produced by common image loaders, and exactly 8 for x/256. For example (toy numbers), a flow that reports −3.50 bits/dim on x′ has −3.50+6.99=3.49 bits/dim in pixel units. A negative value in model units is normal, because a density on a narrow range can exceed 1; only the pixel-unit number can be compared with published results such as the likelihood table of the autoregressive note.
The noise must live in the same units. Dequantization noise has to span exactly one level of whatever the network sees. With x′=x/127.5−1 that means adding u/127.5 with u∼U[0,1)d, which is the same as adding u before rescaling. Noise of width 1 in x′ units would smear each value over about 127 levels, and no noise at all brings back the unbounded likelihood. NICE, for instance, dequantizes CIFAR-10 with uniform noise of width 1281 on data rescaled to [−1,1], where one level is 2562=1281 wide (Dinh, Krueger and Bengio, 2015, §5.1).
The logit transform. Pixel values are bounded, while a Gaussian base lives on all of Rd. To reduce boundary effects, RealNVP models the logit of the rescaled pixels (Dinh, Sohl-Dickstein and Bengio, 2017, §4.1):
y=logit(p)=log1−pp,p=α+(1−2α)256x~,α=0.05.
The shift α keeps p inside [0.05,0.95), so y stays within about ±2.94 instead of running to ±∞ at black and white pixels. This is the form of the reference implementation; the paper prints 1−α in place of 1−2α. The derivative of the transform is dy/dx~=(1−2α)/(256p(1−p)) per coordinate, so
Unlike a linear rescaling, the correction depends on the pixel: about 6.15 bits for a mid-grey value (x~=128.5) and 3.80 bits for the darkest and brightest values (x~=0.5 or 255.5). RealNVP includes this term in its bits per dimension. The Glow paper states that it follows RealNVP’s preprocessing (§5); its reference code instead rescales to [−21,21), adds noise of width 2561 and adds the constant −dlog256 to the log-likelihood, which is the linear case above with a=2561. Flows built for images are the subject of Flow architectures, part F.
GAN: a generator maps noise z to a sample x′ and a discriminator only labels inputs as real or fake, so there is neither a likelihood nor a way back from x to z. VAE: a stochastic encoder q_φ(z|x) and decoder p_θ(x|z) give an approximate posterior and a lower bound (ELBO) on log p(x). Flow: a single invertible map; f⁻¹ takes x to z exactly and f takes z back to x, so z has the same dimension as x and the log-likelihood is exact. Arrows follow the note's convention f: z → x.
GAN (Goodfellow et al., 2014; see the GAN note). There is no log-likelihood evaluation: the generator defines its distribution only through samples. There is also no latent-variable inference: nothing maps x back to z, and nothing guarantees that the generator covers the full support of the data, so a real x may have no latent code at all.
VAE (Kingma and Welling, 2014; see the VAE note). It optimizes a lower bound on the log-likelihood (the ELBO) and infers latents through an approximate posteriorqϕ(z∣x).
Everything above hinges on ∣detJ∣: if it can be computed, the density is exact; if it cannot be computed cheaply, the likelihood is impractical to evaluate and to train on at the scale of images. For a general network it is expensive. Computing the determinant of a general d×d matrix costs O(d3) with Gaussian elimination or an LU decomposition (Golub and Van Loan, 2013); naive cofactor expansion is even worse, O(d!). Take d=1000 (a 32×32 grayscale image already has d=1024): that is on the order of 109 operations (about 32d3≈6.7×108 for LU) for every example, every layer and every training step. For a general network even forming J takes d backward passes, one per row.
The trick that makes flows practical is to ensure the Jacobian is triangular. For a (lower-)triangular matrix, expanding the determinant along the first row and repeating on the remaining block leaves only the diagonal:
which costs O(d): about 103 operations instead of about 109, and only the diagonal entries are needed.
A triangular J is also invertible exactly when every diagonal entry is non-zero, which is easy to guarantee by construction. For the map itself the condition does more. If Jf is lower-triangular everywhere, output i depends only on inputs 1,…,i. If each diagonal entry is continuous and non-zero everywhere, it keeps one sign, so each output is strictly monotone in its own input. The map is then injective and can be inverted one coordinate at a time: z1 from x1, then z2 from x2 and the known z1, and so on. It is a bijection of Rd when each of these one-dimensional maps is onto R, as for the affine maps zi↦eszi+t of coupling layers.
Figure
Why a triangular Jacobian is the trick
If every entry above the diagonal is zero, the determinant is the product of the diagonal entries, so log|det A| = Σ log|aᵢᵢ|. For d = 1000, a general determinant (LU decomposition) costs on the order of d³ = 10⁹ operations, for every example and every layer, whereas the triangular one needs d = 10³ multiplications. Bars are on a log₁₀ scale.
The normalizing-flows notebook of the HSE-LAMBDA Deep Generative Models repository (pinned commit; cell numbers count every cell, markdown included, from 1) builds on Andrej Karpathy’s pytorch-normalizing-flows library (Karpathy, 2019), included as nflib. The notebook has no saved outputs, so it documents procedures rather than results.
Cell 2 writes the change of variables from the generative side, logp(zK)=logp(z0)−∑ilog∣det∂fi/∂zi−1∣.
Cells 4–5 define three 2-D toy datasets: two moons (the one used), a mixture of four Gaussians with standard deviation 0.5, and the SIGGRAPH point set, which needs a siggraph.pkl file that is not included in the repository.
Cell 7 builds the model: a logistic prior, a uniform pushed through an inverse sigmoid, with logpZ(z)=∑i[−log(1+ezi)−log(1+e−zi)] (the Gaussian prior is commented out). NICE uses the same prior and prefers it for its better-behaved gradients (Dinh, Krueger and Bengio, 2015, §3.4). The change-of-variables formula holds for any base density, so only logpZ changes. The flow is three blocks of ActNorm, an invertible 1×1 “convolution” and a neural-spline coupling layer (8 spline bins, tail bound 3, hidden width 16), described in Flow architectures.
Cells 9–11 train with Adam (learning rate 10−4, weight decay 10−5) on the loss above: zs, prior_logprob, log_det = model(x_batch), logprob = prior_logprob + log_det, loss = -torch.sum(logprob), for 1000 iterations, each on a fresh batch of 128 samples. The loss is summed over the batch rather than averaged as in L(θ), which only rescales the gradient. nflib names the directions the other way round from this note: its forward runs data → latent (our f−1) and accumulates our ∑ilog∣det∂fi−1/∂zi∣, while model.sample draws from the prior and runs inverse (our f).
Cells 13–17 map data to latents and prior samples to data, and show how a grid is warped layer by layer. Cell 13 draws its prior points with model.prior.sample([128, 2]); the prior already has two coordinates, so this returns a 128×2×2 tensor and the scatter plot shows 256 prior points instead of 128, which is harmless (sample((128,)) gives the intended shape). Cell 17 runs one more training step and draws the grid warp once: its 500-step loop breaks at k=0.
Cell 19 colours a grid by prior_logprob.exp(), that is pZ(f−1(x))without the log-determinant. This is exactly the naive formula from the start of this note; the model density is (prior_logprob + log_det).exp().
Flows need layers that are expressive and still have a cheap Jacobian determinant by construction. Flow architectures builds them: coupling layers (NICE, RealNVP), masked autoregressive layers (MAF, IAF) and Glow’s invertible 1×1 convolutions, then spline couplings, ActNorm and multi-scale flows for images, and finally the planar and radial flows of Rezende and Mohamed.