Skip to main content

Flow Matching: Simplified Generative Modeling

How Flow Matching simplifies generative modeling by learning straight transport paths from noise to data — faster sampling, simpler training, and the foundation of modern generation systems.

TL;DR

Flow Matching trains a continuous normalizing flow by regressing a velocity field on chosen conditional probability paths. The original paper includes diffusion paths and a conditional Gaussian optimal transport path with linear mean and standard deviation. The latter gives straight conditional trajectories, but the learned marginal trajectories need not be straight or globally optimal. Training requires no ODE simulation; generation still requires numerical integration. Sampling efficiency depends on the learned field, solver, and quality target, rather than a universal 10–50× reduction.

The Core Idea: Choose a Probability Path

Generative modeling asks how to transform simple noise into complex data. Flow Matching makes the probability path an explicit design choice, then trains a neural velocity field v_\theta(\mathbf{x},t) to generate it. Diffusion probability paths are among the supported choices; the conditional OT construction offers a different path with simple velocity targets.

Generation integrates the learned field from noise to a final sample:

\frac{d\mathbf{x}_t}{dt}=v_\theta(\mathbf{x}_t,t),\quad \mathbf{x}_0\sim\mathcal N(0,I)

The network sees position and time, not the destination data point. The pipeline diagram is an authored schematic; its fixed straight connections do not show measured model trajectories. An ODE solver’s error depends on the actual field, so straight conditional supervision alone does not permit arbitrary large steps.

Why Straight Paths Matter

For the original conditional OT path, each fixed noise–data pair follows a straight trajectory at constant velocity. This makes its regression target simple. After mixing over data points, the marginal field averages conditional velocities with position-dependent posterior weights. Its trajectories can curve even though every conditional training path is straight.

This authored geometric comparison contrasts fixed straight and curved paths, rather than executing diffusion or a learned flow. Its pixel lengths describe those drawings. Neither training variance nor sampling quality is measured. The original experiments compare specific objectives and solvers; they do not establish a universal step count or guarantee that Flow Matching avoids curves.

The Velocity Field

The velocity field v_\theta(\mathbf{x},t) takes a position and a time and returns a velocity. Unlike conditional supervision, generation does not have access to a particular target \mathbf{x}_1. The learned field must represent how the whole distribution moves.

The arrows above come from an authored analytic field, with hand-defined attraction toward two cluster centers. They are not learned network outputs. For an exact continuous ODE, suitable regularity and uniqueness conditions support an invertible flow. Continuity alone does not establish those conditions, and a finite Euler discretization does not guarantee invertibility or exact reverse recovery.

Training: Conditional Flow Matching

Conditional Flow Matching (CFM) turns fitting the marginal velocity field into regression on tractable conditional examples. Sections 3.1–3.2 establish the connection: Theorem 1 constructs the marginal field with a posterior-weighted mixture, and Theorem 2 gives equal expected parameter gradients for FM and CFM, assuming positive marginal densities.

For the conditional Gaussian OT path in Equations 20–23, draw independent noise and data samples, and a uniform time. Keep a positive residual noise scale:

a(t)=1-(1-\sigma_{\min})t
\mathbf{x}_t=a(t)\mathbf{x}_0+t\mathbf{x}_1
\mathbf{u}=\mathbf{x}_1-(1-\sigma_{\min})\mathbf{x}_0

At t=1 the path reaches \mathbf{x}_1+\sigma_{\min}\mathbf{x}_0, so its distribution approximates the data distribution with residual Gaussian noise. Setting sigma_min to zero gives the familiar interpolation only as a separate limiting case.

This authored training diagram illustrates that zero-noise limit. Its prediction arrow is hand-rotated, and its displayed error is normalized by the squared target magnitude; no network is trained in the diagram. The executable reference below instead uses positive sigma_min and performs real gradient updates.

The loss uses the squared velocity-vector norm, averaged over the batch:

\ell_b=\sum_j(v_{\theta,bj}-u_{bj})^2
\mathcal L_{\mathrm{CFM}}=\frac1B\sum_b\ell_b

This is velocity regression related to mean squared error; averaging over components as well would change the scale by a factor of the dimension. Conditional targets are constant along each of these paths, but differ between examples. Training samples the conditional path without an ODE solve. The learned field then generates a marginal trajectory using only state and time.

Implementation

The seven operations below keep conditional supervision separate from generation. They execute the positive-noise Gaussian construction in the original paper, then integrate a reduced learned field. Later minibatch pairing methods are discussed afterward.

Offline CPU mechanics: seeded synthetic two-dimensional targets and a reduced 32-unit MLP, with positive sigma_min=0.05. No pretrained weights, image semantics, native GPU performance, or benchmark reproduction. These seven rows connect conditional supervision to field-only sampling.

1. Draw independent endpoints and time

Original paper

§3.2 · Eq. 9; §4.1 · Eq. 23

Independent noise and data draws supply conditional regression examples.

Math and tensor shapes

x_0\sim\mathcal N(0,I),\quad x_1\sim q
t\sim\mathcal U[0,1]

The local generator seeds synthetic two-mode targets. Independent pairing is not a globally optimal coupling. The paper conditions its Gaussian path on x1; x0 is the noise used to draw a point on that path.

x0, x1 [B,D]; t [B,1]; smoke B=16, D=2

Python implementation

1. Draw independent endpoints and time
python
def draw_endpoints(batch=16, dimension=2, seed=7):
    """Draw independent Gaussian noise, synthetic two-mode data, and time."""
    _positive_int(batch, "batch")
    _positive_int(dimension, "dimension")
    generator = torch.Generator(device="cpu").manual_seed(seed)
    x0 = torch.randn(batch, dimension, generator=generator)
    modes = 2 * torch.randint(0, 2, (batch, 1), generator=generator) - 1
    x1 = 2 * modes + 0.2 * torch.randn(batch, dimension, generator=generator)
    t = torch.rand(batch, 1, generator=generator)
    return x0, x1, t

2. Keep a positive terminal noise scale

Original paper

§4.1 · Example II, Eq. 20 and 22

The mean and standard deviation change linearly in time.

Math and tensor shapes

a(t)=1-(1-\sigma_{\min})t
x_t=a(t)x_0+tx_1
x_{t=1}=x_1+\sigma_{\min}x_0

sigma_min=0.05 is this reference’s explicit positive choice. The endpoint distribution is a Gaussian mixture around data, not exactly the data distribution. The familiar zero-noise interpolation is a separate limiting case, excluded from this positive-density API.

a, t [B,1] broadcast over endpoints [B,D]

Python implementation

2. Keep a positive terminal noise scale
python
def conditional_path(x0, x1, t, sigma_min=0.05):
    """Evaluate Eq. 22; at t=1 the endpoint is x1 + sigma_min*x0."""
    _pair(x0, x1)
    _time(x0, t)
    _sigma(sigma_min)
    a = 1 - (1 - sigma_min) * t
    return a * x0 + t * x1

3. Differentiate the conditional path

Original paper

§4.1 · Eq. 21–23

Evaluating the conditional vector field on its path yields a constant target.

Math and tensor shapes

u_t(x\mid x_1)=\frac{x_1-(1-\sigma_{\min})x}{a(t)}
\frac{dx_t}{dt}=x_1-(1-\sigma_{\min})x_0

The first formula is a field at an arbitrary x; substituting x=x_t cancels the time-dependent terms. The second formula is the target actually used in training. A centered finite-difference check independently verifies this derivative.

Conditional target u [B,D], with no time dependence along one path

Python implementation

3. Differentiate the conditional path
python
def conditional_target(x0, x1, sigma_min=0.05):
    """Differentiate Eq. 22 along a fixed conditional trajectory."""
    _pair(x0, x1)
    _sigma(sigma_min)
    return x1 - (1 - sigma_min) * x0

4. Learn a field that cannot see the target

Original paper

§2 · Eq. 1–2; §3.1 · Theorem 1, Eq. 8

The learned marginal field accepts only the current position and time.

Math and tensor shapes

v_\theta:\mathbb R^D\times[0,1]\to\mathbb R^D

Theorem 1 connects conditional fields to a marginal field using a posterior-weighted average, not a plain average of pair velocities. The reduced MLP learns that field through regression. It never accepts x1; straight conditional trajectories do not ensure straight marginal sampling trajectories.

Concatenated [B,D+1] → 32-unit tanh MLP → [B,D]

Python implementation

4. Learn a field that cannot see the target
python
class VelocityModel(nn.Module):
    """Reduced field v(x,t); the unknown target x1 is never an input."""

    def __init__(self, dimension=2, hidden=32):
        super().__init__()
        _positive_int(dimension, "dimension")
        _positive_int(hidden, "hidden")
        self.dimension = dimension
        self.layers = nn.Sequential(
            nn.Linear(dimension + 1, hidden),
            nn.Tanh(),
            nn.Linear(hidden, dimension),
        )

    def forward(self, x, t):
        """Map state [B,D] and time [B,1] to velocity [B,D]."""
        _state(x)
        _time(x, t)
        if x.shape[1] != self.dimension:
            raise ValueError("state dimension must match model")
        return self.layers(torch.cat((x, t), dim=1))

5. Regress velocities and update real parameters

Original paper

§3.2 · Theorem 2, Eq. 9; §4.1 · Eq. 23

Conditional and marginal objectives have equal expected parameter gradients under the theorem’s assumptions.

Math and tensor shapes

\ell_b=\sum_{j=1}^{D}(v_{\theta,bj}-u_{bj})^2
\mathcal L=\frac1B\sum_{b=1}^{B}\ell_b

This is the squared vector-norm reduction in Eq. 23. An elementwise MSE mean would divide by D as well. The smoke performs 64 SGD updates at learning rate 0.02 on one fixed synthetic batch, measures finite parameter gradients and parameter changes, and checks reduced regression loss. It does not establish the theorem by training a toy network.

Residual [B,D] → component sum [B] → batch mean scalar

Python implementation

5. Regress velocities and update real parameters
python
def cfm_loss(model, x0, x1, t, sigma_min=0.05):
    """Use Eq. 23's squared vector norm, then average over the batch."""
    xt = conditional_path(x0, x1, t, sigma_min)
    target = conditional_target(x0, x1, sigma_min)
    prediction = model(xt, t)
    if (
        not isinstance(prediction, torch.Tensor)
        or prediction.shape != target.shape
        or prediction.dtype != target.dtype
        or prediction.device != target.device
        or not torch.isfinite(prediction).all()
    ):
        raise ValueError("field must return finite matching [B,D] velocities")
    return (prediction - target).square().sum(dim=1).mean()


def update_field(model, optimizer, x0, x1, t, sigma_min=0.05):
    """Perform a real optimizer step and report the preceding gradient norm."""
    optimizer.zero_grad(set_to_none=True)
    loss = cfm_loss(model, x0, x1, t, sigma_min)
    loss.backward()
    gradients = [p.grad for p in model.parameters()]
    if any(g is None or not torch.isfinite(g).all() for g in gradients):
        raise ValueError("all parameter gradients must be finite")
    grad_norm = torch.sqrt(sum(g.square().sum() for g in gradients))
    optimizer.step()
    return float(loss.detach()), float(grad_norm)

6. Generate using only the learned field

Original paper

§2 · Eq. 1–2; authored Euler discretization

The generative ODE is integrated from a fresh or supplied noise state.

Math and tensor shapes

h=1/N,\quad t_k=kh
x_{k+1}=x_k+h\,v_\theta(x_k,t_k)

Euler and its 32 steps are pedagogical numerical choices, not the paper’s adaptive solver configuration. Sampling receives no x1 or conditional target velocity. Constant-field and exponential-growth analytic oracles check the integrator, including decreasing error on refinement for the nonconstant field. This establishes neither general solver accuracy nor invertibility.

State [B,D] → trajectory [N+1,B,D]; smoke N=32

Python implementation

6. Generate using only the learned field
python
@torch.no_grad()
def euler_integrator(field, x0, steps=32):
    """Integrate dx/dt=field(x,t) with pedagogical Euler step h=1/steps."""
    _state(x0)
    _positive_int(steps, "steps")
    x = x0.clone()
    trajectory = [x.clone()]
    h = 1 / steps
    for k in range(steps):
        t = x.new_full((x.shape[0], 1), k * h)
        velocity = field(x, t)
        if (
            not isinstance(velocity, torch.Tensor)
            or velocity.shape != x.shape
            or velocity.dtype != x.dtype
            or velocity.device != x.device
            or not torch.isfinite(velocity).all()
        ):
            raise ValueError(
                "field must return finite matching [B,D] velocities"
            )
        x = x + h * velocity
        _state(x)
        trajectory.append(x.clone())
    return torch.stack(trajectory)

7. Keep supervision and generation separate

Original paper

§4.1 · Eq. 22 versus §2 · Eq. 1

A conditional training trajectory and a generated trajectory answer different questions.

Math and tensor shapes

\psi_t(x_0)=a(t)x_0+tx_1
\dot\phi_t=v_\theta(\phi_t,t)

The two arrays share starting noise for comparison, but only the training path uses the known target. The smoke reports their measured endpoint coordinates and maximum difference. It never substitutes the conditional target into the learned sampling field. Synthetic outputs do not demonstrate image quality, universal step reductions, or transport optimality.

Separate conditional_training and generated arrays [33,16,2]

Python implementation

7. Keep supervision and generation separate
python
@torch.no_grad()
def compare_paths(model, x0, x1, sigma_min=0.05, steps=32):
    """Keep conditional training paths separate from field-only sampling."""
    _positive_int(steps, "steps")
    conditional = torch.stack(
        [
            conditional_path(
                x0, x1, x0.new_full((len(x0), 1), k / steps), sigma_min
            )
            for k in range(steps + 1)
        ]
    )
    generated = euler_integrator(model, x0, steps)
    return {"conditional_training": conditional, "generated": generated}

Run the canonical source behind every highlighted excerpt. Smoke JSON records source_sha256, seed, reductions, shapes, actual model gradients and updates, separate endpoints, path derivative and residual endpoint errors, and Euler oracle errors. Import performs no training or sampling.

flowmatching.pyrequirements-flowmatching.txtOriginal Flow Matching paper

python -m pip install -r requirements-flowmatching.txt
python flowmatching.py --smoke --seed 7

Optimal Transport: Better Pairings

The original conditional Gaussian displacement map is optimal between its two conditional Gaussian distributions. Section 4.1 explicitly warns that this does not make the marginal field a global optimal transport solution. Independent noise–data pairing in the reference above is enough for that original construction.

Later work by Tong et al. studies minibatch transport couplings between sampled noise and data. Hungarian assignment or Sinkhorn methods optimize a specified transport objective within a finite batch; costs and approximation behavior depend on batch size and solver. Nearest-neighbor assignment does not generally solve the global assignment problem, and optimized pairings need not form parallel trajectories.

This authored comparison sorts points by vertical coordinate for an OT-like pairing. It is not a Hungarian or Sinkhorn implementation. The displayed lengths and crossings are measurements of the drawing; no training variance is measured. The preserved atong01/conditional-flow-matching repository is a later CFM/OT implementation associated with this line of work, rather than provenance for the original paper’s implementation.

How Flow Matching Compares

Generative Modeling Method Comparison

Authored qualitative comparison of mathematical frameworks and training objectives. Ratings are teaching summaries, not measured quality or speed benchmarks; step counts depend on model and solver.

Flow Matching

Framework: ODE
Steps:
Solver dependent
Training:
Excellent
Quality:
Excellent
Speed:
Excellent

Conditional velocity regression; deterministic ODE sampling; marginal paths may curve

DDPM

Framework: Markov chain
Steps:
Solver dependent
Training:
Excellent
Quality:
Excellent
Speed:
Poor

Simple noise prediction training, but slow iterative denoising at inference

Score SDE

Framework: Stochastic DE
Steps:
Solver dependent
Training:
Moderate
Quality:
Excellent
Speed:
Moderate

Score matching requires careful noise schedule design and SDE solvers

Normalizing Flows

Framework: Bijective maps
Steps:
1 (single pass)
Training:
Poor
Quality:
Moderate
Speed:
Excellent

Single forward pass, but architecturally constrained to invertible transforms

Flow Matching excels at…

Simulation-free conditional velocity regression with selectable probability paths, including diffusion paths. Empirical sampling tradeoffs depend on the learned marginal field, numerical solver, and quality target; no universal step reduction follows.

Considerations

Later optimal transport pairing within mini-batches can add computational overhead; it is not required by the original construction. The ODE formulation, while elegant, requires careful numerical integration to avoid drift. One-pass discrete normalizing flows have a different architecture; practical speed comparisons require a specified model and workload.

Key Takeaways

  1. Conditional geometry and marginal generation differ. Straight Gaussian conditional paths provide simple targets, while learned marginal trajectories may curve and need not be globally optimal.

  2. Training is velocity regression. With positive sigma_min the target is \mathbf{x}_1-(1-\sigma_{\min})\mathbf{x}_0. Theorem 2 relates conditional and marginal objectives through their expected parameter gradients, not equality of each sampled loss.

  3. Pairing is a separate choice. The original construction uses independent draws. Later minibatch OT can alter training couplings, but does not guarantee parallel paths or improvements for every setting.

  4. Generation requires a numerical solver. Exact continuous-flow properties require appropriate ODE assumptions; a small Euler demonstration does not prove accuracy, invertibility, or sample quality.

  5. Diffusion paths remain included. Flow Matching provides a simulation-free training objective for a family of probability paths, including diffusion and conditional OT paths.

Impact and Legacy

Flow Matching helped make simulation-free training of continuous normalizing flows practical at scale. Subsequent systems combine related velocity-regression ideas with new architectures, conditioning, and sampling methods. Stable Diffusion 3’s research paper uses rectified flow transformers. SDXL Turbo’s Adversarial Diffusion Distillation paper describes diffusion distillation, so it should not be attributed to the original Flow Matching method.

Applications now extend across image, video, audio, molecular, and other generative modeling domains. Their quality and speed depend on the full training and sampling system; the two-dimensional mechanics here do not reproduce those systems or establish their performance.

The lasting connection is between tractable conditional regression and a distribution-level generative field. Understanding that connection also clarifies why conditional Gaussian OT, later minibatch OT coupling, and learned sampling trajectories must be evaluated separately.

  • Attention Is All You Need — The transformer architecture that underlies the neural networks used in Flow Matching
  • Deep Residual Learning — Residual connections central to the U-Net and DiT architectures used in flow-based generators
  • DINO — Self-supervised visual features often used as perceptual losses for training flow-based image generators
  • DINOv2 — Universal visual features that complement flow-based generation with strong discriminative representations

If you found this paper review helpful, consider sharing it with others.

Mastodon