Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Forward vs. inverse parameterisation

One bijection, two directions — and which one you make cheap decides what the flow is good at

02 — Forward vs. inverse parameterisation

A normalizing flow is a bijection TT, so it can be run in either direction. That sounds symmetric, but it almost never is: one direction is a closed-form expression and the other needs an iterative solve. Which direction you make cheap decides whether your flow is good at density estimation or at sampling.

What you will see

1. A flow runs both ways

Let z=T(x)z = T(x) map data to a standard-Gaussian latent. The two things we ever ask of a flow use opposite directions:

operationdirectionneedsused for
log_prob(x)forward x→zx \to zT(x)T(x) and log⁡∣det⁡JT(x)∣\log\lvert\det J_T(x)\rvertdensity estimation, MLE training
sample()inverse z→xz \to xT−1(z)T^{-1}(z), z∼N(0,I)z\sim\mathcal{N}(0,I)generation, simulation

Both are always possible (that’s what “bijection” means), but their cost and their differentiability can differ sharply. The culprit is the marginal transform.

2. Analytic forward, iterative inverse — with optimistix

The atom of Gaussianization is the per-coordinate map z=Φ−1(F(x))z = \Phi^{-1}(F(x)), where FF is a mixture-of-Gaussians CDF,

F(x)=∑kwk Φ ⁣(x−μkσk).F(x) = \sum_{k} w_k\,\Phi\!\Big(\frac{x-\mu_k}{\sigma_k}\Big).

Forward (x→u=F(x)x \to u = F(x)) is one closed-form sum. Inverse (u→x=F−1(u)u \to x = F^{-1}(u)) has no closed form, so we frame it as a root-find: solve g(x)=F(x)−u=0g(x) = F(x) - u = 0. We hand that to optimistix Kidger (2021) — the same solver library gauss_flows depends on — using its bracketing Bisection solver, which is bullet-proof because FF is monotone.

forward F(x): closed form, one evaluation
inverse F^-1(u) via optimistix: max|x - x_rec| = 1.63e-10
<Figure size 1100x420 with 2 Axes>

Left: inverting FF means reading the curve right-to-left — there is no formula, so optimistix hunts for the xx that lands on each target uu. Right: the residual falls geometrically with the solver budget, hitting the float64 floor in ~40 steps. Accurate and robust — but it is a loop. How to differentiate that loop (and why naively unrolling it fails) is its own story, told in Part 1, notebook 03 when we train a mixture-CDF.

3. The asymmetry on a real flow

gauss_flows builds its marginal layers from exactly this mixture-CDF, so a whole flow inherits the asymmetry: log_prob runs the analytic forward maps, while sample runs the bisection inverse inside every marginal layer. We time both on the same flow (JIT-compiled and warmed up for a fair race).

log_prob (forward, analytic)  :  19.54 ms / 5000 pts
sample   (inverse, bisection) : 764.82 ms / 5000 pts
sample is 39x more expensive than log_prob
<Figure size 620x400 with 1 Axes>

4. The parameterisation choice

The map TT and its inverse T−1T^{-1} describe the same flow — but we choose which one to store as the cheap, closed-form direction. Whatever we store cheaply, the other direction pays the iterative price.

  • Density-estimation flows call log_prob constantly. Store the forward map cheaply → fast training, slow sampling. This is what gauss_flows Gaussianization flows do, hence §3.
  • Sampling / variational flows call sample constantly. Store the inverse cheaply → fast sampling, slow density.

In flowjax the switch is one wrapper, Invert, which swaps a bijector’s forward and inverse.

Invert(b).transform == b.inverse : True
=> 'forward' and 'inverse' are a labelling choice, not a fixed property.

Recap

concepttakeawayin code
two directionsforward for density, inverse for samplingflow.log_prob / flow.sample
mixture-CDF inversea monotone root-findoptimistix.root_find + Bisection
measured asymmetrysample ≈ 39× log_prob for Gaussianizationtimed, JIT-warmed
parameterisationstore the cheap direction; Invert swaps itflowjax.bijections.Invert
differentiating the inverseunrolling / one-step / adjointPart 1, nb 03

Next up. We have been mapping to a standard Gaussian without asking why that target. 03 — Why a standard Gaussian? shows the three properties — maximum entropy, separability, trivial primitives — that make N(0,I)\mathcal{N}(0, I) the natural destination.

References
  1. Kidger, P. (2021). On Neural Differential Equations [Phdthesis]. University of Oxford.
  2. Papamakarios, G., Pavlakou, T., & Murray, I. (2017). Masked Autoregressive Flow for Density Estimation. Advances in Neural Information Processing Systems (NeurIPS).
  3. Kingma, D. P., Salimans, T., Jozefowicz, R., Chen, X., Sutskever, I., & Welling, M. (2016). Improving Variational Inference with Inverse Autoregressive Flow. Advances in Neural Information Processing Systems (NeurIPS).
  4. Dinh, L., Sohl-Dickstein, J., & Bengio, S. (2017). Density Estimation using Real NVP. International Conference on Learning Representations (ICLR).