A plain-words, poke-the-pictures introduction

Bending the Bell Curve

Normalizing flows are one of the friendliest big ideas in machine learning: take a plain bell curve and bend it, carefully, until it matches your data. This page explains how — no background needed.

650 points from a plain bell curve, flowing into a spiral — and back. This loop is the whole idea. The rest of the page just slows it down. forward →
Section 1The problem: machines need a map of plausibility

Where do things tend to land?

Ask a thousand adults their height and you won't get a thousand random numbers. The answers pile up around 170 cm, thin out toward 150 and 190, and almost never reach 250. There is a shape to the answers. Statisticians call that shape a probability distribution — a map of where values tend to land, and where they basically never do.

Everything a machine-learning model generates — a face, a voice, a molecule — is a draw from some distribution. So two abilities matter enormously. First, sampling: produce a brand-new example that looks like it belongs with the real ones. Second, scoring: given an example, say how plausible it is. Scoring is what lets a model whisper “this jet-engine reading looks weird” or “this molecule is unlikely to occur.”

For a bell curve, both are easy — it's one tidy formula with two knobs (where's the middle, how wide is the spread). But the distribution of, say, real handwritten digits lives in hundreds of dimensions and has a wildly complicated shape. Nobody can write its formula down by hand.

The bell curve (a “normal” distribution). One clean formula. Easy to sample from, easy to score. Also: boring — nothing real looks like this.
A realistic distribution. Lumpy, skewed, multiple clusters — and this is just one dimension. No formula exists for this. Yet it's what we actually want.
The tension

Simple distributions are workable but wrong. Real distributions are right but unworkable. Normalizing flows resolve this with a trick: keep the simple one — and reshape it.

Section 2The idea: reshape, don't rebuild

Probability as clay

Picture the bell curve as a mound of soft clay. Its thickness at any spot is the probability of values landing there. Now reshape the mound — stretch it here, squeeze it there — until it matches the complicated shape you actually want. You never created or destroyed clay. You only moved it.

A normalizing flow is exactly this, done with math. It's a chain of small reshaping steps applied to a simple distribution. But the steps must obey two house rules:

Rule 1 — no tearing. The reshaping must be smooth. Neighboring points stay neighbors; nothing teleports. (This is why it's called a flow — the points drift like particles in slow water.)

Rule 2 — no folding. Two different points may never land on the same spot. Every destination has exactly one origin, so the whole reshaping can be run backwards. In math terms, each step is invertible.

Follow the two rules and you get a superpower: any point in the final shape can be traced back to the exact point in the bell curve it came from — and probability can be carried along the way.
bell curve
step 1stretch
a bit bent
step 2push
bent further
step 3swirl
data shape
run forward →Sampling. Draw a boring bell-curve point, push it through the steps, out comes realistic data.
← run backwardScoring. Take real data, trace it back to the bell curve, and read off exactly how plausible it is.
Section 3Try it: bend a bell curve yourself

One slider, one transformation

Below is a real normalizing flow — a tiny one, with a single reshaping step. The dots are samples from a bell curve; the curve above them is the distribution's shape. The bend slider applies a smooth, invertible stretch that pushes points away from the center. Drag it and watch a valley form: one bump becomes two.

Interactive · a one-step flow in 1-D drag the sliders
before — the bell curve after — the reshaped distribution dots: 90 samples being carried along

Notice where the curve gets low: exactly where the dots got stretched apart. That's not a coincidence — it's the entire secret, and it's next.

Section 4The one rule of the game

Probability is never created or destroyed

Look at the shaded slice in the demo above. Before the bend, it holds some fixed share of all probability — say 6%. After the bend it holds… still exactly 6%. The slice got wider, so the curve over it must get lower, because the amount of clay inside is locked. Stretch a region by 2× and its density drops to ½. Squeeze it to half and the density doubles.

new height=old height÷stretch
pafter(y) = pbefore(x) |stretch(x)|
“stretch” is how much the map stretched space right there, and x is the point that lands on y. Mathematicians call this the change-of-variables formula — the only equation this page needs.

This is why the two house rules matter so much. No folding means each y has exactly one x to look up. No tearing (smoothness) means “how much it stretched here” is a well-defined number at every point. The transformation effectively keeps a receipt for every stretch and squeeze it performs — and the receipts are what let us compute exact probabilities in the final, complicated shape.

In two or more dimensions the idea is identical, just with area instead of width: take a tiny square, see how much the transformation inflates or deflates it. That local area-stretch factor has a fancy name — the Jacobian determinant — but it is still just “how much did this patch stretch.”

So why is it called a “normalizing flow”?

Flow, because samples drift smoothly through each small step, like fluid. Normalizing, because of the backward direction: run real data backwards through the chain and it settles into a normal distribution — the bell curve's formal name.

And how does it learn?

The reshaping steps have adjustable knobs (in practice, neural networks). Training shows the model real examples and asks: run these backwards — did they land in the fat middle of the bell curve, or out in the tails? Then it nudges the knobs so the real data becomes as plausible as possible. The stretch receipts keep the model honest: it can't just squash everything into the middle, because extreme squeezing is penalized by exactly the amount it squeezed. That's the whole training loop — no adversary, no approximation, just “make the data likely.”

A peek at the actual equation (optional)

Write the whole chain of steps as one invertible function f taking bell-curve points to data. For a data point x, its exact log-probability is:

logp(x) = log pbell (f1(x)) + log |det Jf1 (x)|

First term: “where did x land when traced back, and how likely is that spot on the bell curve?” Second term: “sum of the stretch receipts along the way.” Training maximizes this quantity, averaged over real data, by gradient descent. Everything is exact — which is the signature feature of flows.

Section 5Try it: stack simple steps

Simple moves, stacked, get you anywhere

One step can only reshape so much. The real power move is stacking: each layer is almost embarrassingly simple, but their composition is expressive. Below, 750 points from a 2-D bell-curve cloud pass through just two layers. Layer 1 is as plain as it gets — stretch the horizontal axis, squeeze the vertical — turning the blob into a bar. Layer 2 is a swirl: each point rotates by an amount that grows with its distance from the center, winding the bar's ends into arms. A galaxy, from a blob, in two moves.

Interactive · a two-layer flow in 2-D drag the slider, or jump by stage
— layer 1: stretch → — layer 2: swirl →
each dot keeps its color — started far left … started far right — so you can see nothing tears or folds

Drag the slider leftward and you're running the flow in its normalizing direction — the spiral melts back into a bell curve. Real flows stack dozens of learned layers like these (with names like coupling layers), each simple enough that its stretch receipt is cheap to compute, together flexible enough to model faces, audio, or molecules.

Section 6Where flows show up

In the wild

Flows had a star turn in image generation — OpenAI's Glow produced sharp faces and let you smoothly morph attributes, because every image maps to a point in bell-curve space where arithmetic is easy. NVIDIA's WaveGlow synthesized speech. In the sciences, flows act as Boltzmann generators, proposing plausible molecule configurations in one shot instead of simulating them for hours. And because flows compute exact plausibility scores, they quietly power anomaly detection — flagging the sensor reading, transaction, or particle event that real data says shouldn't happen.

Generative modelExact plausibility score?Its character, in one line
Normalizing flowyes — exactReversible by construction; its honesty (exact scores) costs it some architectural freedom.
GANnoA forger and a detective train against each other; sharp samples, but it can't score anything.
VAEapproximate onlyCompresses data through a bottleneck; scores exist but are estimates, not exact.
Diffusionindirect / costlyLearns to undo noise, step by step; today's image champion, but slower and scores take work.

Flows are no longer the loudest model in the room — diffusion took that seat — but the idea didn't fade; it dissolved into everything. Modern “flow matching” methods, used inside several state-of-the-art generators, are the same picture you've been playing with: probability, flowing smoothly from a bell curve to data.

Section 7Check yourself

Three questions

RecapIf you remember three things
1
Reshape, don't rebuild. A flow turns a bell curve into a complicated distribution through a chain of small, smooth, reversible steps.
2
Probability is conserved. Stretch a region and its density thins; squeeze and it thickens. New height = old height ÷ stretch. The “receipts” make scores exact.
3
Two directions, two gifts. Forward = generate new data. Backward = “normalize” data and read off exactly how plausible it is.
Pocket glossary
Distribution
A map of plausibility: which values tend to occur, and how often.
Density
The height of that map at one spot. Higher = values land here more often.
Base distribution
The simple starting shape, almost always a bell curve (a “standard normal”).
Invertible
Undoable. Every output has exactly one input, so the map runs backwards too.
Jacobian determinant (juh-KOH-bee-un)
The local stretch factor: how much a tiny patch of space grew or shrank at a given point.
Change of variables
The rule that carries density through a transformation: new height = old height ÷ stretch.
Coupling layer
A popular flow layer that shifts and scales half the coordinates based on the other half — expressive, yet trivially invertible.
Likelihood
The plausibility score a model assigns to data. Flows compute it exactly; training pushes it up.
If you want to go deeper