VLA · Paper guide
Flow Matching for Generative Modeling
The training recipe behind modern robot action generators, explained through the questions an engineer would ask.
This is a guide to the Flow Matching paper, not a sentence-by-sentence paraphrase. It is not a robotics paper, but π0, GR00T N1 and AsyncVLA all generate actions with its recipe, so understanding it makes those guides easier to follow. Its companion is the Rectified Flow guide, which explains what the straight-line idea guarantees; together the two give the full picture of flow matching. Part A is a 4-minute overview. Parts B to D explain the method, the training and the experiments one idea at a time. Equations and code are folded away in Part E, and Part F is a critical review of the paper’s tables and claims, including a link to the sign question in the π0 and GR00T N1 guides.
How to use this page
- In a hurry: read Part A (about 4 minutes).
- To understand the method: add Parts B to D. Each idea follows the same pattern: intuition, the problem it solves, how it works, an example, then technical details and where to find them in the paper.
- To check or rebuild it: open the folded sections (equations, theorems, hyperparameters, runnable examples) and read Part F.
Open the paper (arXiv:2210.02747) beside this page; section, table, theorem and equation references are to it. We paraphrase and never reproduce its text. Statements are labelled so you can tell them apart: Reported by the paper, Our calculation from the paper’s numbers, and Our interpretation. Runnable examples are marked Toy illustration when they are our own code and never present results from the paper. Because the paper has no robot data, the robot examples are labelled illustrations.
Part A · about 4 minutes
Start here: the paper at a glance
The problem
A generative model learns to produce new samples that look like its training data: images, or, in the robot papers on this site, chunks of robot actions. The most popular recipe, diffusion, trains a network to remove noise. It trains stably, but it can only follow one family of paths from noise to data, which the authors say leads to very long training and the need for special samplers. A more general idea is the continuous normalizing flow (CNF): describe how a noise sample should move to become a data sample using a learned “velocity” at every point and time. Until this paper, the known ways to train a CNF either simulated the movement during training, which is expensive, or used integrals that cannot be computed or gradients that are biased.
The main contribution
- Flow matching (FM). Train the velocity network by plain regression: tell it, point by point, which way the data distribution’s “current” should be flowing. No simulation of the movement is needed during training.[1]
- The conditional trick. The right target velocity cannot be computed, but a target built from one data example at a time can, and training on it gives the same gradients (the paper’s second theorem). This is the idea that makes the method simple and scalable.
- Freedom in the path. Any smooth Gaussian path from noise to data works, and ordinary diffusion paths are special cases. The authors propose a simple straight-line path from optimal transport (OT) theory, along which each sample moves in a straight line at constant speed.
How the model works, in one paragraph
To train, pick a data example and a noise sample, pick a time between 0 (noise) and 1 (data), and take the point that is that far along the path between them. Ask the network for its velocity at that point and time, and compare it with the target velocity, which for the straight-line path is simply data minus noise. To generate, draw noise and follow the network’s velocity forward in time with an ordinary differential equation (ODE) solver, taking small steps until time 1.
What it learns from, and what it is tested on
Image generation on CIFAR-10 and ImageNet at three resolutions (32, 64 and 128 pixels) and 64-to-256-pixel super-resolution, plus a 2-D toy. The same network architecture is trained with different methods and compared on three measures: likelihood in bits per dimension (the negative log-likelihood, NLL, per image number; lower is better), sample quality by the Fréchet Inception Distance (FID) (lower is better), and the cost of sampling as the number of function evaluations (NFE, network calls; lower is cheaper).
What the paper reports
Numbers as printed in the paper (Table 1 and Table 2 and the ImageNet-128 table):
| Test | Flow matching with OT paths | Best comparison |
|---|---|---|
| CIFAR-10: NLL / FID / NFE | 2.99 / 6.35 / 142 | DDPM: 3.12 / 7.48 / 274 |
| ImageNet 64×64: NLL / FID / NFE | 3.31 / 14.45 / 138 | DDPM: 3.32 / 17.36 / 264 |
| ImageNet 128×128: NLL / FID | 2.90 / 20.9 | best listed generative adversarial network (GAN): FID 21.7 |
| Super-resolution 64→256: FID | 3.4 | SR3: 5.2 |
What to keep in mind
- This is an image-generation paper. The robot papers use its recipe for actions; the paper itself contains no robot experiments.
- Several margins are small, for example 0.01 bits per dimension on ImageNet, and the paper reports single runs without intervals.
- Two tables in the paper disagree on the likelihood of two models, and the training table is inconsistent for CIFAR-10 (Part F).
- The straight-line property is exact for each single-example path; it does not make the full learned field straight, as the authors say themselves.
If you read nothing else: flow matching trains a generator by regressing a velocity along a chosen path from noise to data, using one example at a time, and samples by following that velocity with an ODE solver. The straight-line path needs fewer steps than diffusion paths in the paper’s tests. The robot policies of π0, GR00T N1 and AsyncVLA use exactly this recipe.
Check your understanding: Why does the paper regress onto a target built from a single data example instead of the “true” velocity field?
The true (marginal) velocity field involves an integral over the whole data distribution and cannot be computed. A single example’s target can be computed in closed form, and the paper proves that training on it gives the same gradients, because the average of the per-example targets is the true field.
Part B
Understand the method
There is no robot in this paper, so we use one as the running example: the thing being generated is an action chunk, a short sequence of motor commands, treated as a single point in a space with many dimensions (one per number). Plain words first, technical names second; the equations are collected in Part E.
1. Flows and velocity fields: moving noise into data
- Intuition
- Imagine a cloud of dust (random noise) and an arrow at every point and every moment that says which way and how fast the dust there should move. Follow the arrows for one unit of time and the dust has formed the picture.
- The problem it solves
- To generate data we need a rule that turns easy-to-sample random noise into realistic data.
- How it works
- A vector field v assigns a velocity to every point x at every time t. Following it from time 0 to time 1 is a flow, defined by an ordinary differential equation (ODE): the position changes at the speed the field gives. A continuous normalizing flow (CNF) uses a neural network for the field. Starting from a simple distribution such as standard normal noise, the flow reshapes it into a distribution that should match the data.
- Example
- Illustration, not from the paper A noisy 16-action chunk is a point in a space with one dimension per number. The network’s velocity at that point says how each number should change next; following it for a while yields a clean chunk.
- Technical details
- The reshaping of the distribution is written as a push-forward, and whether a field really generates a given path of distributions can be tested with the continuity equation (Appendix B). CNFs were introduced as neural ODEs; the paper recaps how to compute the probability of a data point (Appendix C).
- Evidence in the paper
- §2 · Equations 1 to 4 · Appendices B and C
Check your understanding: What does the neural network output in a continuous normalizing flow?
A velocity: for a given point and time it says which way, and how fast, to move. The generated sample is found by following those velocities.
2. Probability paths and the flow matching objective
- Intuition
- Before choosing the arrows, decide the story of how the whole cloud of dust should change over time: pure noise at the start, the data distribution at the end, a smooth blend in between. That story is the probability path.
- The problem it solves
- If we knew a path and a velocity field that produces it, training would be easy: just make the network match the field. But for real data we know neither in closed form.
- How it works
- A probability path pt starts at simple noise (time 0) and ends near the data distribution (time 1). The flow matching objective asks the network v to match the field u that generates the path: minimise the average squared difference between v and u over random times and points on the path.
- Example
- Illustration, not from the paper At time 0 the cloud is random action chunks; at time 1 it is the distribution of the chunks in the demonstrations; at time 0.5 it is a half-noisy mixture.
- Why the authors chose it
- It is a simple regression objective, which is attractive compared with maximum-likelihood training of flows, where every training step needs a numerical ODE simulation.
- Technical details
- The paper notes the objective is intractable on its own: it needs a path pt that ends at the data and its generating field ut in closed form, neither of which is available.
- Evidence in the paper
- §3 · Equation 5
Check your understanding: Why is the plain flow matching objective unusable as it stands?
Its target is the field that generates a path ending at the data distribution, and that field is not known in closed form for real data.
3. The conditional trick: one example at a time
- Intuition
- To teach someone the average heading of a crowd, you need not compute the average yourself: show them one person’s heading at a time, chosen at random, and they will settle on the average.
- The problem it solves
- The target field is an average over the entire data distribution, which cannot be computed.
- How it works
- For each single data example x1, define an easy path from noise to a narrow bump around x1, and the field that generates it. The overall path is the mixture of these per-example paths, and the overall field is their average weighted by how many examples pass through each point (Theorem 1 says this average field really generates the overall path). The conditional flow matching (CFM) objective regresses the network onto the per-example field. Theorem 2 shows that CFM and the original objective have identical gradients, so minimising one minimises the other.
- Example
- Illustration, not from the paper One demonstration chunk x1 and one noise chunk give one target velocity. Each such target is a noisy sample of the ideal field; training averages many of them.
- Why the authors chose it
- Per-example targets can be computed in closed form and sampled without bias. The idea parallels denoising score matching in diffusion models.
- Technical details
- The example below uses data that is either −2 or +2. Every single target is far from the true field, yet the average of the targets of the samples passing near a point matches the exact field, which is what Theorem 2 relies on.
Run the example: single targets are noisy, but their average is the field
Toy illustrationWhat each part does
- Sample many data points (−2 or +2) and noise values, and put each at its point at time 0.5.
- The target of each sample is its data minus its noise.
- At several positions, average the targets of the samples that are near that position and compare with the exact marginal velocity.
import numpy as np rng = np.random.default_rng(0) # A toy "dataset": the data is either -2 or +2, equally likely (one number per sample). # Flow Matching with the straight-line (OT) path: x_t = (1 - t) * x0 + t * x1, x0 is noise, x1 is data. t = 0.5 N = 4_000_000 x1 = rng.choice([-2.0, 2.0], N) # data samples x0 = rng.normal(size=N) # noise samples xt = (1 - t) * x0 + t * x1 # where each sample sits at time t target = x1 - x0 # the per-example ("conditional") target velocity def marginal_velocity(x, t): # The exact marginal velocity field for this toy: the average target over all examples that pass through x. # Posterior probability that the example came from the data point +2 given it is at x at time t: w_pos = np.exp(-0.5 * ((x - 2.0 * t) / (1 - t)) ** 2) w_neg = np.exp(-0.5 * ((x + 2.0 * t) / (1 - t)) ** 2) p_pos = w_pos / (w_pos + w_neg) mean_x1 = 2.0 * p_pos - 2.0 * (1 - p_pos) # E[x1 | x_t = x] mean_x0 = (x - t * mean_x1) / (1 - t) # E[x0 | x_t = x] return mean_x1 - mean_x0 print("position x | examples near x | one target (std) | average target | exact marginal velocity") for x in (-1.0, -0.3, 0.0, 0.4, 1.2): near = np.abs(xt - x) < 0.02 # all examples that are (almost) at x at time t print(f"{x:>10.1f} | {near.sum():>15,} | {target[near].std():>16.2f} | {target[near].mean():>14.3f} | {marginal_velocity(x, t):>10.3f}") print() print("each single target is very noisy, but their average matches the marginal field (Theorem 2's idea)")Output:
position x | examples near x | one target (std) | average target | exact marginal velocity -1.0 | 63,640 | 0.15 | -1.997 | -1.997 -0.3 | 25,907 | 2.23 | -2.718 | -2.735 0.0 | 17,287 | 4.00 | -0.028 | 0.000 0.4 | 32,219 | 1.55 | 2.885 | 2.887 1.2 | 58,512 | 0.05 | 1.600 | 1.599 each single target is very noisy, but their average matches the marginal field (Theorem 2's idea)A one-dimensional toy that makes the average computable; it illustrates the statement of the theorem, it does not prove it.
- Evidence in the paper
- §3.1 and §3.2 · Equations 6 to 9 · Theorems 1 and 2 · Appendix A
Check your understanding: If every individual target is so noisy, why does training work?
The network is trained on many random examples, and its best prediction at a point is the average of the targets there. Theorem 2 says that average is exactly the field that generates the desired path.
4. Gaussian paths, diffusion as a special case, and the straight-line path
- Intuition
- Each example’s path is a blurry bump that starts wide (noise) and shrinks onto the example. You choose how the bump’s centre moves and how fast its width shrinks. Different choices give different journeys from noise to data.
- The problem it solves
- The method needs a concrete, easy-to-compute per-example path and field.
- How it works
- The authors use Gaussian bumps whose centre μt and width σt are chosen freely (equal to noise at time 0 and a narrow bump at the example at time 1). Theorem 3 gives the field in closed form from μ and σ. Diffusion paths (the “variance exploding” and “variance preserving” ones) are particular choices, so the framework contains diffusion. The new choice is to let the centre and the width change linearly with time: the optimal transport (OT) path. Each noise sample then moves in a straight line at constant speed to its data example, and the regression target is just data minus (almost) noise.
- Example
- Illustration, not from the paper For one chunk x1 and one noise chunk x0, the intermediate chunk at time t is (1 − t)·x0 + t·x1 (up to a tiny constant) and the target velocity is x1 − x0, the same at every time.
- Why the authors chose it
- The paper reports that the OT path gives faster training, faster sampling and better results than the diffusion paths. The straight line is also simple to regress: the target has a constant direction.
- Technical details
- The OT conditional flow is optimal between the two Gaussians, but the authors note this does not make the combined (marginal) field optimal. The example below checks Theorem 3 numerically and shows how a diffusion path wanders: for the same data value, the noise samples’ trajectories under the variance-preserving path bend away from a straight line and can overshoot their final value.
Run the example: straight paths against diffusion paths
Toy illustrationWhat each part does
- Define the OT path and the (reversed) variance-preserving diffusion path from the paper’s equations.
- Follow one noise sample along each and measure its distance from a straight line.
- Check Theorem 3’s field against the numerical slope, and scan several starting noise values for overshoots.
import numpy as np # Paths from the paper (t = 0 is noise, t = 1 is data). psi_t(x0) = sigma_t * x0 + mu_t maps noise x0 to the path. sigma_min = 0.01 def ot(t, x1): # Equation 20: mean and std change linearly return t * x1, 1 - (1 - sigma_min) * t b_min, b_max = 0.1, 20.0 # noise schedule used for the diffusion baseline (Appendix E.1) def vp(t, x1): # Equation 18: reversed variance-preserving diffusion path s = 1 - t T = s * b_min + 0.5 * s * s * (b_max - b_min) alpha = np.exp(-0.5 * T) return alpha * x1, np.sqrt(1 - alpha ** 2) x0, x1 = 1.0, 2.0 # one noise value and one data value ts = np.linspace(0.0, 1.0, 1001) for name, path in (("OT path", ot), ("VP diffusion path", vp)): mu, sigma = path(ts, x1) traj = sigma * x0 + mu # where this noise sample travels chord = traj[0] + (traj[-1] - traj[0]) * ts # the straight line between its start and end print(f"{name:<18} start {traj[0]:.3f}, end {traj[-1]:.3f}, lowest point {traj.min():.3f}, " f"largest distance from a straight line {np.abs(traj - chord).max():.3f}") # Does a path "overshoot" or turn back? Check several noise values for the same data value x1 = 2. print() print("noise value x0 | OT path monotonic? | VP path monotonic? | VP: first moves the wrong way by | VP: goes past its end value by") for x0v in (-2.0, 0.0, 1.0, 2.0, 3.0, 4.0): mono = [] for path in (ot, vp): mu, sigma = path(ts, x1) steps = np.diff(sigma * x0v + mu) mono.append(bool(np.all(steps >= -1e-12) or np.all(steps <= 1e-12))) mu, sigma = vp(ts, x1) traj = sigma * x0v + mu direction = 1.0 if traj[-1] > traj[0] else -1.0 # which way the path is heading overall wrong_way = round(max(float(np.max((traj[0] - traj) * direction)), 0.0), 3) + 0.0 past_end = round(max(float(np.max((traj - traj[-1]) * direction)), 0.0), 3) + 0.0 print(f"{x0v:>14} | {str(mono[0]):<18} | {str(mono[1]):<18} | {wrong_way:>32.3f} | {past_end:>30.3f}") # Theorem 3: the vector field is u = sigma'/sigma * (x - mu) + mu'. Check it against the path's own time derivative. print() for name, path in (("OT path", ot), ("VP diffusion path", vp)): d = 1e-6 errors = [] for t in np.linspace(0.05, 0.95, 19): mu, sigma = path(t, x1) mu2, sigma2 = path(t + d, x1) mu_p, sigma_p = (mu2 - mu) / d, (sigma2 - sigma) / d x = sigma * x0 + mu # a point on the path formula = sigma_p / sigma * (x - mu) + mu_p # Theorem 3 slope = ((sigma2 * x0 + mu2) - x) / d # d/dt psi_t(x0) errors.append(abs(formula - slope)) print(f"{name:<18} largest difference between the formula and the slope: {max(errors):.2e}") # The OT target (Equation 21 at t = 0 with sigma_min -> 0): u = x1 - (1 - sigma_min) * x0 print() print("OT target x1 - (1 - sigma_min) * x0 =", round(x1 - (1 - sigma_min) * x0, 3), " (the same for every t: a constant direction)")Output:
OT path start 1.000, end 2.010, lowest point 1.000, largest distance from a straight line 0.000 VP diffusion path start 1.013, end 2.000, lowest point 1.013, largest distance from a straight line 0.405 noise value x0 | OT path monotonic? | VP path monotonic? | VP: first moves the wrong way by | VP: goes past its end value by -2.0 | True | True | 0.000 | 0.000 0.0 | True | True | 0.000 | 0.000 1.0 | True | False | 0.000 | 0.236 2.0 | True | False | 0.815 | 0.000 3.0 | True | False | 0.592 | 0.000 4.0 | True | False | 0.459 | 0.000 OT path largest difference between the formula and the slope: 1.67e-10 VP diffusion path largest difference between the formula and the slope: 2.22e-10 OT target x1 - (1 - sigma_min) * x0 = 1.01 (the same for every t: a constant direction)One-dimensional, single data value, noise schedule from Appendix E.1. It illustrates the paper’s Figure 3, it is not a reproduction of its image experiments.
- Evidence in the paper
- §4 · §4.1 Examples I and II · Equations 10 to 23 · Theorem 3 · Figures 2 and 3
Check your understanding: What does “straight line at constant speed” buy you when generating?
Each noise sample’s journey is a straight line, so fewer, larger steps of an ODE solver follow it accurately. In the paper it shows up as fewer function evaluations for the same quality.
5. Sampling: following the velocity with an ODE solver
- Intuition
- Drop a speck of dust into the cloud at a random place and let the arrows carry it; each small step uses the arrow where it currently is.
- The problem it solves
- After training we need to turn a fresh noise sample into a new data sample.
- How it works
- Draw noise x0, then solve the ODE from time 0 to time 1 with the trained network as the velocity. The simplest solver, Euler, takes a step of size δ along the current velocity. The midpoint method looks half a step ahead first. The paper evaluates with an adaptive solver (dopri5) and also with fixed-step solvers at a low budget of network calls, called the number of function evaluations (NFE).
- Example
- Illustration, not from the paper A robot policy based on this recipe draws a random action chunk and applies, for example, 4 or 10 Euler steps (the GR00T N1 and π0 guides).
- Why the authors chose it
- ODE solvers are efficient, with many schemes to choose from; the paper argues that this makes sampling by an ODE preferable to sampling a diffusion process as a stochastic equation.
- Technical details
- The toy below uses the exact velocity field of the two-point data. With a single step both solvers fail, with two steps the midpoint method does much better than Euler, and by four to eight steps both land on the data. The paper reports that the OT-trained models need about 60% of the evaluations of the diffusion-trained models for the same numerical error (Figure 7, for ImageNet 32×32).
Run the example: how many steps are needed?
Toy illustrationWhat each part does
- Write the exact velocity field for the two-point data.
- Start from noise and take 1, 2, 4, 8 or 16 steps with Euler or the midpoint method.
- Measure how close the final samples are to the data points (−2 and +2).
import numpy as np rng = np.random.default_rng(1) def marginal_velocity(x, t): # exact marginal velocity for data that is -2 or +2 with equal probability, straight-line path w_pos = np.exp(-0.5 * ((x - 2.0 * t) / (1 - t)) ** 2) w_neg = np.exp(-0.5 * ((x + 2.0 * t) / (1 - t)) ** 2) p_pos = w_pos / (w_pos + w_neg) m = 2.0 * p_pos - 2.0 * (1 - p_pos) return m - (x - t * m) / (1 - t) def sample(steps, solver, n=20000): # Start from noise at t = 0 and follow the velocity field to t = 1. x = rng.normal(size=n) dt = 1.0 / steps for k in range(steps): t = k * dt if solver == "euler": x = x + dt * marginal_velocity(x, t) else: # midpoint: look half a step ahead first mid = x + 0.5 * dt * marginal_velocity(x, t) x = x + dt * marginal_velocity(mid, t + 0.5 * dt) return x print("steps | solver | share of samples within 0.3 of a data point | mean distance to the nearest data point") for steps in (1, 2, 4, 8, 16): for solver in ("euler", "midpoint"): x = sample(steps, solver) dist = np.minimum(np.abs(x - 2.0), np.abs(x + 2.0)) print(f"{steps:>5} | {solver:<8} | {100 * np.mean(dist < 0.3):>43.1f}% | {dist.mean():>38.3f}")Output:
steps | solver | share of samples within 0.3 of a data point | mean distance to the nearest data point 1 | euler | 0.0% | 2.000 1 | midpoint | 7.9% | 1.376 2 | euler | 52.7% | 0.519 2 | midpoint | 82.1% | 0.189 4 | euler | 99.1% | 0.010 4 | midpoint | 99.9% | 0.001 8 | euler | 100.0% | 0.000 8 | midpoint | 100.0% | 0.000 16 | euler | 100.0% | 0.000 16 | midpoint | 100.0% | 0.000Exact toy field, not a trained network; it shows why a few steps can be enough for a straight-line path, not the paper’s ImageNet numbers.
- Evidence in the paper
- §6.2 · Figures 4, 6 and 7 · Appendix E
Check your understanding: Why does the midpoint method need fewer steps than Euler in the toy?
It looks ahead by half a step and uses the velocity there, which follows the curved parts of the field better; in the toy that gets most samples to the data points with only two steps.
Part C
Understand the training and the measurements
What a training step looks like, how the paper’s models were set up and trained, and how the three measures used in the tables (likelihood, FID and NFE) are computed.
The training step: simulation-free regression
- Intuition
- Show the network a random moment in the journey of one random example and ask it to say which way the example is heading.
- The problem it solves
- Earlier CNF training either ran a numerical ODE simulation at every training step (slow), used integrals that could not be computed in many dimensions, or had biased gradients.
- How it works
- For each example in a batch: draw a data example x1, draw noise x0, draw a time t uniformly from 0 to 1, compute the point on the path, and take a gradient step on the squared difference between the network’s velocity there and the target velocity. For the OT path the target is x1 − (1 − σmin) x0, where σmin is a small constant that leaves the final bump slightly wide.
- Example
- Illustration, not from the paper One demonstration chunk, one noise chunk and one time give one training pair: (point, time) → target velocity.
- Why the authors chose it
- No ODE is solved during training, and the gradients are unbiased, so the method scales to high-dimensional data such as ImageNet images.
- Technical details
- The loss is the plain squared error of Equation 23. The robot papers (π0, GR00T N1, AsyncVLA) use this same regression, with time conventions that differ between papers (Part F).
- Evidence in the paper
- §3.2 · §4.1 Equation 23 · Section 5 (related work)
Check your understanding: What does “simulation-free” mean?
Training never has to solve the ODE that carries noise to data. Each step needs only a single forward pass of the network at a random point and time.
How the models were set up and trained
- Intuition
- A fair race needs the same car for every driver: here the same network, hyperparameters and training length for every method.
- The problem it solves
- Methods can only be compared if everything except the training objective is held fixed.
- How it works
- Images use the U-Net of Dhariwal and Nichol with minor changes; the 2-D toy uses a five-layer network of 512 units. The paper trains flow matching with the OT path, flow matching with a diffusion path, and score matching with a diffusion path on the same architecture and hyperparameters for the same number of epochs (Appendix E). Training uses the Adam optimiser, with 16-bit mixed precision for the larger images, on 2 to 32 GPUs depending on the dataset.
- Why the authors chose it
- The comparison is meant to show that the training objective and the path matter, not the network.
- Technical details
- Table 3 gives batch sizes, iterations and epochs for each dataset. Our check shows that for CIFAR-10 and ImageNet-128 these columns do not agree with each other (Part F).
Run the example: epochs, iterations and batch size
Our calculationWhat each part does
- Type in each dataset’s training-set size and the batch size, iterations and epochs of Table 3.
- Compute the epochs that batch size × iterations implies and the iterations the printed epochs imply.
- Check the ImageNet-128 comparison with Dhariwal and Nichol’s training effort.
# Table 3: does effective batch size x iterations match the number of epochs? (our check) cifar_train = 50_000 # CIFAR-10 training images (standard) imagenet_train = 1_281_167 # ImageNet training images (standard) rows = { # name: (training images, effective batch, iterations, epochs as printed) "CIFAR-10": (cifar_train, 256, 391_000, 1000), "ImageNet 32": (imagenet_train, 1024, 250_000, 200), "ImageNet 64": (imagenet_train, 2048, 157_000, 250), "ImageNet 128": (imagenet_train, 1536, 500_000, 571), } print("name | images seen | epochs implied | epochs printed | iterations implied by the printed epochs") for name, (n, batch, iters, epochs) in rows.items(): seen = batch * iters print(f"{name:<13} | {seen / 1e6:>8.0f} M | {seen / n:>14.0f} | {epochs:>14} | {epochs * n / batch / 1000:>10.0f} k (printed {iters // 1000} k)") print() print("one iteration per 391 per epoch would mean a batch of", round(cifar_train / 391), "for CIFAR-10 (the table says 256)") # Section 6.1: ImageNet-128 training effort against Dhariwal and Nichol dn = 4_360_000 * 256 # 4.36 million iterations at batch 256 for batch in (1500, 1536): fm = 500_000 * batch print(f"ImageNet-128: FM sees {fm / 1e6:.0f} M images against {dn / 1e6:.0f} M -> {100 * (1 - fm / dn):.0f}% fewer (batch {batch})")Output:
name | images seen | epochs implied | epochs printed | iterations implied by the printed epochs CIFAR-10 | 100 M | 2002 | 1000 | 195 k (printed 391 k) ImageNet 32 | 256 M | 200 | 200 | 250 k (printed 250 k) ImageNet 64 | 322 M | 251 | 250 | 156 k (printed 157 k) ImageNet 128 | 768 M | 599 | 571 | 476 k (printed 500 k) one iteration per 391 per epoch would mean a batch of 128 for CIFAR-10 (the table says 256) ImageNet-128: FM sees 750 M images against 1116 M -> 33% fewer (batch 1500) ImageNet-128: FM sees 768 M images against 1116 M -> 31% fewer (batch 1536)
Uses the standard training-set sizes (50,000 for CIFAR-10, about 1.28 million for ImageNet); these are our assumptions.
- Evidence in the paper
- §6.1 · Appendix E and Table 3
Check your understanding: The same architecture and epochs are used for every method. Why is that important?
Otherwise a difference in results could come from a bigger network or longer training instead of from the objective or the path that is being compared.
How quality is measured: likelihood, FID and NFE
- Intuition
- Three questions: how likely does the model think real images are (likelihood), do its samples look real to a feature extractor (FID), and how many network calls does one sample cost (NFE)?
- The problem it solves
- Different generative models must be compared on common ground.
- How it works
- Likelihood is reported as the negative log-likelihood in bits per dimension (BPD): total bits to describe an image divided by the number of numbers in it. For a flow, the probability of a data point is computed by integrating the divergence of the velocity along the flow (Appendix C), after a standard “dequantisation” step that adds uniform noise to the 8-bit pixel values, with an importance-weighted estimate over K noise draws. FID compares feature statistics of generated and real images (lower is better). NFE is the number of network evaluations an adaptive ODE solver (dopri5, tolerance 1e-5) needs, averaged over 50,000 samples.
- Example
- Illustration, not from the paper For a robot, the analogue of NFE is the number of denoising steps, 4 in GR00T N1 and 10 in π0, which determine how fast actions can be produced.
- Why the authors chose it
- Together they cover fit to the data, sample quality and sampling cost.
- Technical details
Run the example: what a difference in bits per dimension means
Our calculationWhat each part does
- Count the numbers in a CIFAR-10 and an ImageNet-64 image.
- Convert bits per dimension to bits and nats per image.
- Express small differences between methods as bits per image and as a share of the total.
import math # Bits per dimension (BPD) = negative log-likelihood in bits, divided by the number of numbers in the image. dims = {"CIFAR-10 (3 x 32 x 32)": 3 * 32 * 32, "ImageNet 64 (3 x 64 x 64)": 3 * 64 * 64, "ImageNet 128 (3 x 128 x 128)": 3 * 128 * 128} for name, d in dims.items(): print(f"{name}: {d:,} numbers per image") d = dims["CIFAR-10 (3 x 32 x 32)"] for bpd in (2.99, 3.09): bits = bpd * d print(f"BPD {bpd} on CIFAR-10 = {bits:,.0f} bits = {bits * math.log(2):,.0f} nats per image") diff = (3.09 - 2.99) * d print(f"the gap between 3.09 and 2.99 is {diff:,.0f} bits per image, about {100 * diff / (3.09 * d):.1f}% of the total") d64 = dims["ImageNet 64 (3 x 64 x 64)"] print(f"on ImageNet 64, 3.32 against 3.31 is {(3.32 - 3.31) * d64:,.0f} bits per image, {100 * (3.32 - 3.31) / 3.32:.2f}% of the total") print("the importance-weighted estimate in Table 4 moves the same model by up to", round(3.62 - 3.53, 2), "BPD (ImageNet 32, K = 1 against K = 15)")Output:
CIFAR-10 (3 x 32 x 32): 3,072 numbers per image ImageNet 64 (3 x 64 x 64): 12,288 numbers per image ImageNet 128 (3 x 128 x 128): 49,152 numbers per image BPD 2.99 on CIFAR-10 = 9,185 bits = 6,367 nats per image BPD 3.09 on CIFAR-10 = 9,492 bits = 6,580 nats per image the gap between 3.09 and 2.99 is 307 bits per image, about 3.2% of the total on ImageNet 64, 3.32 against 3.31 is 123 bits per image, 0.30% of the total the importance-weighted estimate in Table 4 moves the same model by up to 0.09 BPD (ImageNet 32, K = 1 against K = 15)
Arithmetic that puts the paper’s small likelihood margins into perspective.
- Evidence in the paper
- §6.1 · Appendix C and E.2 · Table 4 (effect of K)
Check your understanding: Is a likelihood of 3.31 against 3.32 bits per dimension a large difference?
On a 64×64 image that is about 123 bits out of roughly 40,000, a 0.3% difference, and it is smaller than the 0.04 to 0.09 bits per dimension by which the choice of K moves the same ImageNet model (Table 4).
Part D
Understand the experiments
What was compared, what the numbers say, and what they do not say. All numbers are as printed in the paper unless marked as our calculation.
The set-up: data, rivals and measures
- Intuition
- The same network is trained five ways, and the five are compared on the same three measures.
- How it works
Data: CIFAR-10 (32×32 images), and ImageNet at 32×32, 64×64 and 128×128, all unconditional (no labels), plus a 2-D checkerboard for pictures, and 64→256 super-resolution (conditional generation).
Methods on the same network: DDPM (the standard diffusion training loss), score matching with a diffusion path, ScoreFlow (score matching with a likelihood-motivated weighting), flow matching with the diffusion path, and flow matching with the OT path. For ImageNet-128, flow matching is compared with published GAN results.
Measures: likelihood (bits per dimension), FID and NFE; super-resolution adds the inception score and two pixel-similarity measures, the peak signal-to-noise ratio (PSNR) and the structural similarity (SSIM).
- Evidence in the paper
- §6 · §6.1 to 6.3 · Appendix E
Check your understanding: Why were the models for the different methods trained on the same architecture?
To make the training objective the only difference. The paper’s claim is about objectives and paths, not network design.
Likelihood, sample quality and cost (Table 1)
- Technical details
Table 1 (left), as printed. Lower is better in every column. Bold marks the best value. Method CIFAR-10 NLL FID NFE ImageNet-32 NLL FID NFE ImageNet-64 NLL FID NFE DDPM 3.12 7.48 274 3.54 6.99 262 3.32 17.36 264 Score matching 3.16 19.94 242 3.56 5.68 178 3.40 19.74 441 ScoreFlow 3.09 20.78 428 3.55 14.14 195 3.36 24.95 601 FM with diffusion path 3.10 8.06 183 3.54 6.37 193 3.33 16.88 187 FM with OT path 2.99 6.35 142 3.53 5.02 122 3.31 14.45 138 FM with the OT path has the best value in all nine columns, with the largest advantage in the number of function evaluations: about half of DDPM’s and, for ImageNet-64, less than a third of score matching’s. Our calculation The likelihood margins are tiny on ImageNet (0.01 bits per dimension). In the same table, flow matching with the diffusion path is not uniformly better than score matching with the same path: on ImageNet-32 score matching has the lower FID (5.68 against 6.37).
Run the example: re-check Table 1 against Table 4
Our calculationWhat each part does
- Type in Table 1 and the largest-K column of Table 4.
- Compare each pair of likelihoods and find the best method per column.
- Compute the NFE ratios and compare flow matching with score matching on the same path.
# Table 1 (left): NLL (bits per dimension), FID and NFE, then Table 4's likelihood with the largest K used in Table 1. t1 = { # CIFAR-10 (NLL, FID, NFE), ImageNet 32 (NLL, FID, NFE), ImageNet 64 (NLL, FID, NFE) "DDPM": [(3.12, 7.48, 274), (3.54, 6.99, 262), (3.32, 17.36, 264)], "Score Matching": [(3.16, 19.94, 242), (3.56, 5.68, 178), (3.40, 19.74, 441)], "ScoreFlow": [(3.09, 20.78, 428), (3.55, 14.14, 195), (3.36, 24.95, 601)], "FM w/ Diffusion": [(3.10, 8.06, 183), (3.54, 6.37, 193), (3.33, 16.88, 187)], "FM w/ OT": [(2.99, 6.35, 142), (3.53, 5.02, 122), (3.31, 14.45, 138)], } t4_last_k = { # Table 4, K = 50 (CIFAR-10), K = 15 (ImageNet 32), K = 10 (ImageNet 64) "DDPM": (3.12, 3.54, 3.32), "Score Matching": (3.16, 3.57, 3.40), "ScoreFlow": (3.09, 3.55, 3.36), "FM w/ Diffusion": (3.10, 3.56, 3.33), "FM w/ OT": (2.99, 3.53, 3.31), } sets = ["CIFAR-10", "ImageNet 32", "ImageNet 64"] print("does Table 1's NLL equal Table 4's largest-K value?") for name, rows in t1.items(): same = [rows[i][0] == t4_last_k[name][i] for i in range(3)] print(f" {name:<16} {same}") print() print("best method in each column (NLL, FID, NFE):") for i, s in enumerate(sets): for j, m in enumerate(("NLL", "FID", "NFE")): best = min(t1, key=lambda r: t1[r][i][j]) print(f" {s:<12} {m}: {best} ({t1[best][i][j]})") print() print("NFE of FM w/ OT as a share of each baseline's NFE:") for i, s in enumerate(sets): parts = ", ".join(f"{m} {100 * t1['FM w/ OT'][i][2] / t1[m][i][2]:.0f}%" for m in ("DDPM", "Score Matching", "ScoreFlow", "FM w/ Diffusion")) print(f" {s:<12} {parts}") print() print("flow matching with the diffusion path against score matching with the same path (FID):") for i, s in enumerate(sets): fm, sm = t1["FM w/ Diffusion"][i][1], t1["Score Matching"][i][1] print(f" {s:<12} FM {fm} vs SM {sm}: {'FM better' if fm < sm else 'SM better'}") print() print("NLL gap between FM w/ OT and the best other method (bits per dimension):") for i, s in enumerate(sets): others = min(t1[m][i][0] for m in t1 if m != "FM w/ OT") print(f" {s:<12} {round(others - t1['FM w/ OT'][i][0], 2)}")Output:
does Table 1's NLL equal Table 4's largest-K value? DDPM [True, True, True] Score Matching [True, False, True] ScoreFlow [True, True, True] FM w/ Diffusion [True, False, True] FM w/ OT [True, True, True] best method in each column (NLL, FID, NFE): CIFAR-10 NLL: FM w/ OT (2.99) CIFAR-10 FID: FM w/ OT (6.35) CIFAR-10 NFE: FM w/ OT (142) ImageNet 32 NLL: FM w/ OT (3.53) ImageNet 32 FID: FM w/ OT (5.02) ImageNet 32 NFE: FM w/ OT (122) ImageNet 64 NLL: FM w/ OT (3.31) ImageNet 64 FID: FM w/ OT (14.45) ImageNet 64 NFE: FM w/ OT (138) NFE of FM w/ OT as a share of each baseline's NFE: CIFAR-10 DDPM 52%, Score Matching 59%, ScoreFlow 33%, FM w/ Diffusion 78% ImageNet 32 DDPM 47%, Score Matching 69%, ScoreFlow 63%, FM w/ Diffusion 63% ImageNet 64 DDPM 52%, Score Matching 31%, ScoreFlow 23%, FM w/ Diffusion 74% flow matching with the diffusion path against score matching with the same path (FID): CIFAR-10 FM 8.06 vs SM 19.94: FM better ImageNet 32 FM 6.37 vs SM 5.68: SM better ImageNet 64 FM 16.88 vs SM 19.74: FM better NLL gap between FM w/ OT and the best other method (bits per dimension): CIFAR-10 0.1 ImageNet 32 0.01 ImageNet 64 0.01
- Evidence in the paper
- §6.1 · Table 1 · Table 4 (Appendix E.2)
Check your understanding: Which column shows the clearest advantage of the OT path, and why?
The number of function evaluations: flow matching with OT needs about half of DDPM’s and often a third or less of score matching’s, because straight paths are easier for an ODE solver. Likelihood margins are much smaller.
Faster training and cheaper sampling
- How it works
- Two further claims are backed by figures: flow matching with the OT path lowers FID faster during training on ImageNet-64 (Figure 5), and for a fixed budget of fixed-step solver evaluations, it reaches the same numerical error with about 60% of the evaluations and gives better FID at low evaluation counts than the diffusion-path models (Figure 7, ImageNet-32). For ImageNet-128 the authors compare 500 thousand iterations at batch size 1.5 thousand with 4.36 million at 256 for the diffusion model of Dhariwal and Nichol.
- Technical details
Our calculation By our arithmetic the ImageNet-128 model saw about a third fewer images (750 million against 1,116 million), consistent with the “33% less” in the text, though the 31% from the table’s batch size of 1,536 is slightly different (Part F). The paper also says that the cost of sampling stays constant during flow-matching training, whereas it varies for score matching (Figure 10).
- Evidence in the paper
- §6.1 “Faster training” · §6.2 · Figures 5, 7 and 10 · Table 3
Check your understanding: What would you need to see to be sure the OT path is cheaper to sample, not just in one model?
The same advantage across datasets, network sizes and repeated runs. The paper shows the numerical-error curve for one model (ImageNet-32); the NFE column of Table 1 supports it on three datasets.
ImageNet 128×128 against GANs
- How it works
- A flow-matching model with the OT path, a 25% larger network, is trained on ImageNet-128 and compared on FID with published unconditional GAN results (MGAN, PacGAN2, Logo-GAN-AE, self-conditioned GAN, unconditional BigGAN and PGMGAN). The paper reports a likelihood of 2.90 bits per dimension and an FID of 20.9.
- Technical details
ImageNet 128×128 FID, as printed. IC-GAN, which uses a conditioning network, is left out of the table by the authors. Model FID MGAN 58.9 PacGAN2 57.5 Logo-GAN-AE 50.9 Self-conditioned GAN 41.7 Unconditional BigGAN 25.3 PGMGAN 21.7 FM with OT path 20.9 Our interpretation The margin over PGMGAN is 0.8 FID points with no uncertainty reported, and the GAN numbers come from different papers.
- Evidence in the paper
- §6.1 · Table 1 (right) · Figures 11 to 13
Check your understanding: Why is a 0.8 FID margin over one competitor weak evidence?
FID has run-to-run variation that the paper does not report, and the competitor’s number comes from a different paper with its own training and evaluation choices.
Super-resolution (conditional generation)
- How it works
- To test conditional generation, the model upsamples ImageNet images from 64×64 to 256×256, following the evaluation of the SR3 paper, and is compared with SR3, a plain regression model and the real validation images (“reference”).
- Technical details
Table 2, as printed. Bold marks the best of the three models (not the reference). Model FID ↓ IS ↑ PSNR ↑ SSIM ↑ Reference 1.9 240.8 – – Regression 15.2 121.1 27.9 0.801 SR3 5.2 180.1 26.4 0.762 FM with OT path 3.4 200.8 24.7 0.747 Flow matching has the best FID and inception score (IS) but the lowest peak signal-to-noise ratio (PSNR) and structural similarity (SSIM) of the three. The paper calls the PSNR and SSIM “similar” to SR3’s and argues, following the SR3 authors, that FID and IS indicate quality better. Our calculation The gaps to SR3 are 1.7 dB in PSNR and 0.015 in SSIM.
Run the example: the numbers of Table 2
Our calculationWhat each part does
- Type in Table 2.
- Compute the differences between flow matching and SR3, and between flow matching and the regression model.
# Table 2: image super-resolution (64x64 -> 256x256) on the ImageNet validation set rows = { # FID (lower is better), IS (higher), PSNR (higher), SSIM (higher) "Reference": (1.9, 240.8, None, None), "Regression": (15.2, 121.1, 27.9, 0.801), "SR3": (5.2, 180.1, 26.4, 0.762), "FM w/ OT": (3.4, 200.8, 24.7, 0.747), } fm, sr3, reg = rows["FM w/ OT"], rows["SR3"], rows["Regression"] print("FM w/ OT minus SR3:") print(" FID ", round(fm[0] - sr3[0], 1), "(lower is better)") print(" IS ", round(fm[1] - sr3[1], 1), "(higher is better)") print(" PSNR ", round(fm[2] - sr3[2], 1), "dB (higher is better)") print(" SSIM ", round(fm[3] - sr3[3], 3), "(higher is better)") print() print("FM w/ OT minus the plain regression model:") print(" PSNR ", round(fm[2] - reg[2], 1), "dB; SSIM ", round(fm[3] - reg[3], 3)) print() print("FID is", round(sr3[0] / fm[0], 2), "times lower than SR3's, but PSNR is lowest of the three and SSIM is lowest of the three")Output:
FM w/ OT minus SR3: FID -1.8 (lower is better) IS 20.7 (higher is better) PSNR -1.7 dB (higher is better) SSIM -0.015 (higher is better) FM w/ OT minus the plain regression model: PSNR -3.2 dB; SSIM -0.054 FID is 1.53 times lower than SR3's, but PSNR is lowest of the three and SSIM is lowest of the three
Arithmetic on the printed table.
- Evidence in the paper
- §6.3 · Table 2 · Figures 14 and 15
Check your understanding: The model has the best FID but the worst PSNR. What does that suggest?
PSNR and SSIM reward matching the exact pixels of the original, while FID rewards realistic-looking images. A model that produces sharp, plausible but not pixel-exact details will do better on FID and worse on PSNR.
What the results show
- With the same network, flow matching with the OT path has the best likelihood, FID and cost in all nine columns of Table 1.
- It needs about half the function evaluations of DDPM and often far fewer than score matching to sample.
- It trains with fewer images than the diffusion model it is compared against on ImageNet-128 and reaches a competitive FID.
- It can be used for conditional generation (super-resolution) with a better FID than SR3.
What they do not show
- That the margins are larger than run-to-run noise: no repeated runs or intervals are reported, and some likelihood gaps are 0.01 bits per dimension.
- That flow matching with the diffusion path is better than score matching with it: the table is mixed, and two likelihood entries disagree with Table 4.
- That the straight-line property carries over to the learned marginal field; the paper only guarantees it for each per-example path.
- Anything about robot actions: the paper has no robot data, and its images are far larger than action chunks.
Part E · optional
Engineering deep dive
The equations, the three theorems in words, likelihood computation, the relation to diffusion, the training table and the likelihood-estimate table, for readers who want to rebuild or audit the method. Everything is collapsed; Parts A to D do not depend on it.
The equations
Time runs from 0 (noise) to 1 (data) in this paper. Symbols: x a point, x1 a data example, x0 a noise sample, vt the network’s velocity, ut the target velocity, pt a probability path, q the data distribution.
Reported by the paper The flow of a velocity field (Equations 1 and 2):
Reported by the paper The flow matching objective (Equation 5), and the marginal path and field built from per-example ones (Equations 6 and 8):
Reported by the paper Conditional flow matching (Equation 9), whose gradient equals that of the objective above:
Reported by the paper Gaussian conditional paths (Equations 10, 11 and 15; Theorem 3):
Reported by the paper The optimal-transport path (Equations 20 to 23): mean and standard deviation change linearly, with a small σmin:
Reported by the paper The diffusion paths are the variance-exploding path (Equations 16 and 17) and the variance-preserving path (Equations 18 and 19). The latter uses αt = exp(−T(t)/2), T(t) = ∫0t β(s) ds and pt(x | x1) = N( x | α1−t x1, (1 − α²1−t) I ).
Our calculation For the OT path with σmin → 0 the target is x1 − x0: data minus noise. The robot papers (π0, GR00T N1) use the same path but print the opposite sign; see F10.
The three theorems, in words
- Theorem 1. If each per-example field generates its per-example path, then the averaged field (weighted by how much of each path passes through a point) generates the averaged path. Proof idea: check the continuity equation; differentiating the mixture of paths and moving the derivative inside the integral gives the averaged field.
- Theorem 2. The conditional objective differs from the flow matching objective by a constant that does not depend on the network’s parameters, so their gradients are equal. Proof idea: expand the squared difference; the term with the network’s output alone is the same under both objectives, and the cross term is equal because averaging the per-example fields gives the marginal field (Fubini’s theorem lets the integrals swap).
- Theorem 3. For a Gaussian path built from a time-dependent mean and standard deviation, the unique field of the affine flow ψt(x) = σt x + μt is given by Equation 15. Proof idea: invert ψ, differentiate it with respect to time and substitute.
These are our summaries of Appendix A; read the appendix for the assumptions (such as bounded fields and positive densities).
Computing the likelihood (Appendix C)
Reported by the paper The probability of a data point is obtained from the instantaneous change-of-variables formula: the log-density changes along the flow by minus the divergence of the velocity, so one can integrate an ODE that carries both the point and the accumulated divergence, then add the log-density of the noise at the start. Data are dequantised with uniform noise and the reported value is an importance-weighted estimate over K noise draws, solved with the adaptive dopri5 solver at tolerance 1e-5. Values for different K are in Table 4 (below).
Relation to diffusion (Appendix D) and the baselines (Appendix E.1)
- Reported by the paper The conditional fields for the variance-exploding and variance-preserving paths coincide with the vector fields of the probability-flow ODE of diffusion models; a lemma converts the diffusion convention (data at time 0) to this paper’s (noise at time 0) by the map ũt(x) = −u1−t(x).
- Reported by the paper Baselines: score matching regresses the score (with weights σt² for the original and β(1 − t) for ScoreFlow), and the DDPM loss regresses the noise. Samples for all of them are produced by an ODE with the field of Equation 46; DDPM samples use the same equation with the score set from the predicted noise.
- Reported by the paper Diffusion path settings: βmin = 0.1, βmax = 20, time sampled in [0, 1 − ε] with ε = 1e-5.
Hyperparameters (Table 3)
| CIFAR-10 | ImageNet-32 | ImageNet-64 | ImageNet-128 | |
|---|---|---|---|---|
| Channels | 256 | 256 | 192 | 256 |
| Depth | 2 | 3 | 3 | 3 |
| Channel multiples | 1,2,2,2 | 1,2,2,2 | 1,2,3,4 | 1,1,2,3,4 |
| Attention heads / head channels | 4 / 64 | 4 / 64 | 4 / 64 | 4 / 64 |
| Attention resolution | 16 | 16, 8 | 32, 16, 8 | 32, 16, 8 |
| Effective batch size | 256 | 1,024 | 2,048 | 1,536 |
| GPUs | 2 | 4 | 16 | 32 |
| Epochs | 1,000 | 200 | 250 | 571 |
| Iterations | 391k | 250k | 157k | 500k |
| Learning rate | 5e-4 | 1e-4 | 1e-4 | 1e-4 |
| Schedule | polynomial decay | polynomial decay | constant | polynomial decay |
| Warm-up steps | 45k | 20k | – | 20k |
Likelihood estimates for different K (Table 4, selected rows)
| Model | CIFAR-10 K = 1 / 20 / 50 | ImageNet-32 K = 1 / 5 / 15 | ImageNet-64 K = 1 / 5 / 10 |
|---|---|---|---|
| DDPM | 3.24 / 3.14 / 3.12 | 3.62 / 3.57 / 3.54 | 3.36 / 3.33 / 3.32 |
| Score matching | 3.28 / 3.18 / 3.16 | 3.65 / 3.59 / 3.57 | 3.43 / 3.41 / 3.40 |
| FM with diffusion path | 3.23 / 3.13 / 3.10 | 3.64 / 3.58 / 3.56 | 3.37 / 3.34 / 3.33 |
| FM with OT path | 3.11 / 3.01 / 2.99 | 3.62 / 3.56 / 3.53 | 3.35 / 3.33 / 3.31 |
Part F
Critical paper review
Everything above reports what the paper says. This part is our independent reading: where its tables disagree with each other, where wording is stronger than the numbers, and where the method’s claims reach beyond the experiments. This is a foundational paper with a sound core; none of these findings touches its theory. Each one links back to the concept it affects, and the calculations are reproducible in the examples. The paper has no limitations section; we flag the limits its text does state in the last finding.
Numbers that do not agree
-
F1. Table 1 and Table 4 disagree on two likelihoods Numerical inconsistency
What the paper says. Table 1 reports negative log-likelihood in bits per dimension; Table 4 gives the same quantity for different numbers of noise draws K. Table 1 should equal the largest-K entry of Table 4.
What we found. It does for every entry except two, both on ImageNet-32: flow matching with the diffusion path is 3.54 in Table 1 and 3.56 in Table 4, and score matching is 3.56 against 3.57. With Table 4’s value, flow matching with the diffusion path (3.56) would be worse than DDPM (3.54) and ScoreFlow (3.55) instead of tying DDPM.
Why it matters. A small one, but it affects the one column where the diffusion-path version of flow matching looks competitive; the OT row is the same in both tables. Concept: Table 1 · example
-
F2. Table 3: batch size, iterations and epochs do not fit for CIFAR-10 and ImageNet-128 Numerical inconsistency
What the paper says. For CIFAR-10: effective batch size 256, 1,000 epochs, 391k iterations. For ImageNet-128: batch size 1,536, 571 epochs, 500k iterations. ImageNet-32 and 64 are consistent.
What we found. With 50,000 CIFAR-10 training images (standard), 391k iterations at batch size 256 is about 2,000 epochs, not 1,000; 391 iterations per epoch would mean a batch of 128. For ImageNet-128, 500k iterations at 1,536 is about 600 epochs against 571 printed (about 476k iterations for 571). The text’s “33% less throughput” is 33% with a batch of 1,500 and 31% with the table’s 1,536.
Why it matters. Most likely typos in the table, with no effect on the conclusions, but the training budget cannot be taken from the table with confidence. The ImageNet-128 comparison with Dhariwal and Nichol is about 31% to 33% fewer images either way. Concept: How the models were trained · example
-
F3. Same iterations, more iterations or same epochs for the baselines? Ambiguity
What the paper says. Section 6.1 says all models use the same architecture, hyperparameters and number of iterations, but baselines are allowed more iterations for better convergence. Appendix E says all methods are trained for the same number of epochs.
What we found. These statements do not describe the same protocol: either the baselines got more training or they did not. Table 3 lists one number of epochs and iterations per dataset.
Why it matters. If the baselines trained longer, the comparison is even more favourable to flow matching than it looks; if not, “allowed more iterations” is inaccurate. The paper does not say which. Concept: The set-up
How far the claims go
-
F4. Flow matching with a diffusion path against score matching Method caveat
What the paper says. Even on diffusion paths, flow matching is described as more robust and stable and as achieving superior performance compared with score matching.
What we found. In Table 1 flow matching with the diffusion path beats score matching on CIFAR-10 (FID 8.06 against 19.94) and ImageNet-64 (16.88 against 19.74), but score matching has the lower FID on ImageNet-32 (5.68 against 6.37) and the likelihood differences are 0.00 to 0.06. The score-matching and ScoreFlow FIDs on CIFAR-10 (about 20) are far above DDPM’s 7.48; the authors note their architecture is not tuned for CIFAR-10 and that their FIDs are higher than previously published.
Why it matters. The evidence is mixed and from single runs; “more stable” (training curves are shown for one dataset) is not measured with repeated runs. The OT path’s advantage is much clearer than the diffusion-path advantage. Concept: Table 1 · example
-
F5. Likelihood margins of 0.01 bits per dimension Method caveat
What the paper says. FM with OT achieves the best likelihood on every dataset.
What we found. On ImageNet-32 and ImageNet-64 the margin over the next-best method is 0.01 bits per dimension, about 123 bits of roughly 40,000 on a 64×64 image (0.3%). The same model’s estimate moves by 0.04 to 0.09 bits per dimension when K changes (Table 4). No repeated runs, seeds or intervals are given.
Why it matters. Only the CIFAR-10 likelihood gap (0.10) is clearly larger than the estimation effects; on ImageNet the likelihoods are effectively tied. Concept: How quality is measured · example
-
F6. “DDPM” here is not the usual DDPM sampler Ambiguity
What the paper says. DDPM is a baseline in Table 1 with its NFE, FID and NLL.
What we found. Appendix E.1 says the baselines, including the DDPM loss, are sampled by solving an ODE with the field of Equation 46 (with the score taken from the predicted noise), using an adaptive solver. The standard DDPM sampler is an ancestral (stochastic) sampler with a fixed number of steps, so the “DDPM” row measures DDPM-trained models under an ODE sampler.
Why it matters. The NFE and FID of the baselines are for ODE sampling, which is the paper’s point of comparison but not how DDPM is normally used. Concept: The set-up · Measures
-
F7. “OT paths are guaranteed to stay straight” Method caveat
What the paper says. Particles under the OT displacement map move in straight lines at constant speed, and diffusion trajectories can overshoot their final sample.
What we found. Straightness is exact for each per-example conditional path (the example confirms the diffusion path bends away from a straight line and can overshoot). The authors themselves say that the optimality of the conditional flow does not make the marginal field an optimal transport solution, and the trained network follows the marginal field. The 60%-of-evaluations result is one model (ImageNet-32) with fixed-step solvers.
Why it matters. The practical benefit (fewer steps) is shown empirically; the idea that learned sampling paths are straight is not guaranteed and is shown only by pictures (Figure 6). Concept: Gaussian and straight paths · example
-
F8. “Similar PSNR and SSIM” in super-resolution Ambiguity
What the paper says. FM with OT achieves similar PSNR and SSIM values to SR3 while considerably improving FID and IS.
What we found. PSNR is 24.7 against SR3’s 26.4 (1.7 dB lower) and the regression model’s 27.9, and SSIM is 0.747 against 0.762 and 0.801: lowest of the three on both. FID (3.4 against 5.2) and IS (200.8 against 180.1) are better. The argument that FID and IS better indicate quality is borrowed from the SR3 paper.
Why it matters. The metrics disagree, which is expected (they measure different things), but “similar” understates the pixel-level gap; the claim of better quality rests on FID and IS only. Concept: Super-resolution · example
-
F9. The ImageNet-128 “state of the art” Method caveat
What the paper says. The FID on ImageNet 128×128 is state-of-the-art, with the exception of IC-GAN, which uses conditioning with a self-supervised network and is left out of the table.
What we found. The margin over the best listed GAN (PGMGAN, 21.7 against 20.9) is 0.8 FID points with no repeated runs. The GAN numbers are from different papers with their own protocols, and the flow-matching model has a 25% larger network than the diffusion model it is compared with in training cost.
Why it matters. The result shows flow matching is competitive on ImageNet-128 with the unconditional GANs listed; “state of the art” depends on which comparisons are included. Concept: ImageNet 128×128
For the robot papers, and the paper’s own limits
-
F10. The sign of the target, and what it means for π0 and GR00T N1 Numerical inconsistency
What the paper says. With time 0 at noise and 1 at data, the straight-line path is ψt(x) = (1 − (1 − σmin)t)x0 + t x1 and the regression target is x1 − (1 − σmin)x0: data minus noise.
What we found. The π0 and GR00T N1 papers use the same path (τ = 0 is noise, τ = 1 is the clean actions A) but print the target as ε − A, noise minus data, which is the opposite sign from this paper’s Equation 23, and then integrate forward with a positive step. The example confirms the path’s slope is A − ε and that a step with the printed target moves away from the data.
Why it matters. This supports the finding in the π0 and GR00T N1 guides that the printed sign there is probably a typo or a change of convention (the authors’ code decides). The AsyncVLA paper avoids the issue by running time backwards (1 = noise). Concept: Gaussian and straight paths · π0 guide F1 · GR00T N1 guide F1
Run the example: the sign of the target, compared with the robot papers
Our calculationWhat each part does
- Build the OT path and measure its slope.
- Compare it with the target of this paper and with the target printed in the π0 and GR00T N1 papers.
- Take one Euler step with each target and see whether it moves toward the data.
import numpy as np rng = np.random.default_rng(0) # Flow Matching paper, Section 4.1 (t = 0 is noise, t = 1 is data), OT path: # psi_t(x0) = (1 - (1 - s) t) x0 + t x1 and the training target (Equation 21 / 23): u = x1 - (1 - s) x0 s = 1e-5 # sigma_min: tiny, so the path is nearly the straight line x1 = rng.normal(size=4) # data (an action chunk, in the robot papers) x0 = rng.normal(size=4) # noise def psi(t): return (1 - (1 - s) * t) * x0 + t * x1 d = 1e-6 slope = (psi(0.5 + d) - psi(0.5)) / d target_fm = x1 - (1 - s) * x0 print("path slope equals the Flow Matching target x1 - x0:", bool(np.allclose(slope, target_fm, atol=1e-4))) # The pi0 and GR00T N1 papers write the same path, A_tau = tau * A + (1 - tau) * eps (tau = 0 noise, tau = 1 data), # with A = x1 and eps = x0 -- but print the regression target as eps - A. printed_target = x0 - x1 print("path of those papers equals the FM path:", bool(np.allclose(psi(0.3), 0.3 * x1 + 0.7 * x0, atol=1e-4))) print("their printed target eps - A is the negative of the FM target:", bool(np.allclose(printed_target, -target_fm, atol=1e-3))) print("an Euler step with the FM target moves toward the data: ", float(np.linalg.norm(x0 + 0.1 * target_fm - x1)) < float(np.linalg.norm(x0 - x1))) print("an Euler step with the printed target moves away from it: ", float(np.linalg.norm(x0 + 0.1 * printed_target - x1)) > float(np.linalg.norm(x0 - x1)))Output:
path slope equals the Flow Matching target x1 - x0: True path of those papers equals the FM path: True their printed target eps - A is the negative of the FM target: True an Euler step with the FM target moves toward the data: True an Euler step with the printed target moves away from it: True
Random vectors stand in for an action chunk and noise; the point is only the sign.
-
F11. What the paper says about its limits Limitation
What the paper says. The conclusion expects flow matching to allow many more probability paths (for example non-isotropic Gaussians or more general kernels); the paper notes that the conditional OT flow is optimal but this does not make the marginal vector field optimal; the social-responsibility section notes that image generation can be misused and points to energy savings from less training.
What we found. There is no dedicated limitations section. The experiments are limited to images (CIFAR-10, ImageNet) and super-resolution, with single runs and no intervals; there is no robot or other continuous-control data, and no study of how the choices of the paper (OT path, simulation-free regression) behave for low-dimensional, highly multimodal data such as actions.
Why it matters. The theory is general, but the evidence for robotics comes from the robot papers, not from this one. Concept: Table 1 · Gaussian paths
Knowledge check
Try each question first, then reveal the explanation.
Question 1
In your own words: what does the network learn in flow matching, and how is a new sample generated?
Explanation
It learns a velocity: for a point and a time it says which way the point should move to turn noise into data. To generate, draw noise and follow the learned velocity from time 0 to time 1 with an ODE solver, in a few to many small steps.
Question 2
Why is training on one example’s target at a time legitimate?
Explanation
The ideal target is an average over the whole data distribution and cannot be computed, but the average of the per-example targets equals it; the paper proves that the conditional objective has the same gradients as the ideal one (Theorem 2), so minimising it minimises the ideal.
Question 3
What is special about the optimal-transport path, and what does the paper not guarantee about it?
Explanation
Each noise sample moves in a straight line at constant speed to its data example, and the regression target (data minus noise) has a constant direction. The straightness is exact for each per-example path; it does not make the learned marginal field optimal or straight, which the authors state.
Question 4
Name one inconsistency in the paper’s tables and one claim that is stronger than its numbers.
Explanation
For example: Table 1 and Table 4 give different likelihoods for flow matching with the diffusion path on ImageNet-32 (3.54 against 3.56); or Table 3’s CIFAR-10 batch size and iterations imply about 2,000 epochs rather than 1,000. And: the paper calls the PSNR and SSIM of its super-resolution model “similar” to SR3’s, but both are lower.
Glossary
- Generative model
- A model that learns to produce new samples that look like its training data.
- Diffusion
- A family of generative models that learn to remove noise step by step.
- Vector field
- A rule that gives a velocity (a direction and speed) at every point and time.
- Flow
- The movement of points obtained by following a vector field over time.
- ODE
- Ordinary differential equation: here, “the position changes at the speed the field gives”.
- CNF
- Continuous normalizing flow: a flow whose vector field is a neural network.
- Probability path
- A smooth sequence of distributions from noise (time 0) to data (time 1).
- Flow matching (FM)
- Training the velocity network by regression onto a target field that generates a chosen path.
- Conditional flow matching (CFM)
- The same, but with the target built from one data example at a time; it has identical gradients.
- Marginal vs conditional
- Marginal: averaged over all examples; conditional: for a single example.
- Gaussian path
- A path whose distribution at each time is a Gaussian bump with a chosen centre and width.
- Optimal transport (OT) path
- The path in which each noise sample moves in a straight line at constant speed.
- VE / VP
- Variance exploding and variance preserving: two standard diffusion paths.
- Euler / midpoint solver
- Simple ways to follow a velocity: Euler steps along the current velocity, midpoint looks half a step ahead.
- NFE
- Number of function evaluations: how many network calls sampling needs.
- NLL / BPD
- Negative log-likelihood, in bits per dimension: lower means the model fits held-out data better.
- FID
- Fréchet Inception Distance: compares feature statistics of generated and real images; lower is better.
- IS
- Inception score: higher means more recognisable and varied images.
- PSNR / SSIM
- Peak signal-to-noise ratio and structural similarity: pixel-level similarity to the original image.
- GAN
- Generative adversarial network: a generator trained against a discriminator.
- Dequantisation
- Adding small uniform noise to 8-bit pixel values so that likelihoods of continuous models are meaningful.
References
Numbered notes in the text, like [1], point here. Each entry says what it is cited for and how that was checked. Papers and books can be revised or misread, so follow the links before relying on a detail. Code marked “Toy model” is our own illustration of an idea, not the code of the cited system.
(2023). Flow matching for generative modeling. ICLR 2023 / arXiv. arXiv:2210.02747
Cited for:
- Flow Matching is a simulation-free way to train continuous normalizing flows by regressing the vector fields of fixed conditional probability paths; sampling works with off-the-shelf numerical ODE solvers. Checked against the paper’s abstract.