How to use variational inference#
Variational inference (VI) fits a tractable distribution \(q\) to the posterior by
optimizing a divergence against the potential. In sbi it is a sampler: it works with
any potential, so it is available for NLE and NRE, and it is the option to reach for when
MCMC is too slow or when sampling latency matters. See
how to choose sampling algorithms for how it compares to the
alternatives.
VIPosterior has two modes, and they are mutually exclusive:
Fixed-observation VI (
train()) learns one approximation for one \(x_o\).Amortized VI (
train_amortized()) learns a conditional approximation \(q(\theta \mid x)\) that serves many observations.
Calling one on a posterior that was already trained in the other mode discards the earlier
fit and raises a warning, so use separate VIPosterior objects when both results are
needed.
Fixed-observation VI#
Building and training are separate steps. Pass VIPosteriorParameters to choose the
objective:
from sbi.inference.posteriors import VIPosteriorParameters
vi_posterior = inference.build_posterior(
posterior_parameters=VIPosteriorParameters(vi_method="rKL"),
)
vi_posterior.train(x=x_o)
vi_samples = vi_posterior.sample((1000,), x=x_o)
Fixed-observation VI supports vi_method="rKL", "fKL", "IW", or "alpha". Some are
mode-seeking ("rKL", "alpha" above 1) and some are mass-covering ("fKL", "IW",
"alpha" below 1).
Check the approximation#
VI is approximate, so verify the fit before relying on it. The evaluate() method prints a
quality score: by default the shape parameter \(\hat{k}\) of a generalized Pareto
distribution fitted to the tail of the importance weights of \(q\) against the potential,
where below roughly 0.5 is good and above 1.0 indicates a poor approximation
(Yao et al., 2018). Passing
quality_control_metric="prop" instead reports an \(R^2\) of \(q\) against the joint, where
values above 0.5 are good.
vi_posterior.evaluate()
Where feasible, also compare against MCMC on the same observation. evaluate() and the
vi_method choices apply to fixed-observation VI only.
Refine a fixed-observation VI posterior#
Sampling-importance-resampling (SIR) can use the trained VI posterior as a proposal. This
workflow is fixed at x_o; it does not imply batched refinement of an amortized
posterior.
from sbi.inference import ImportanceSamplingPosterior
refined_posterior = ImportanceSamplingPosterior(
potential_fn=vi_posterior.potential_fn,
proposal=vi_posterior,
method="sir",
).set_default_x(x_o)
refined_samples = refined_posterior.sample((1000,), oversampling_factor=32)
Check the importance weights before relying on the refined result. See the dedicated importance-sampling guide for details.
Sequential NLE with VI#
Fixed-observation VI can also act as the sampler in sequential NLE. In each round, train
or update the NLE, fit a VIPosterior to x_o, sample parameters from it for the next
simulations, append those simulations, and repeat. This is SNLE with VI instead of MCMC
(Glöckler et al., 2022).
proposal = prior
for _ in range(num_rounds):
theta = proposal.sample((num_sims,))
x = simulator(theta)
inference.append_simulations(theta, x).train()
posterior = inference.build_posterior(
posterior_parameters=VIPosteriorParameters(vi_method="fKL"),
).set_default_x(x_o)
proposal = posterior.train()
Amortized VI#
Amortized VI learns a conditional approximation \(q(\theta \mid x)\) from simulation pairs,
so one fit serves many observations. The variational family is set with q, which accepts
the usual estimator strings:
amortized_vi = inference.build_posterior(
posterior_parameters=VIPosteriorParameters(
q="nsf", num_transforms=2, hidden_features=32
),
)
amortized_vi.train_amortized(theta, x)
Use sample() for one observation, sample_batched() for several observations at once,
and log_prob() to evaluate the learned normalized approximation. There is no
log_prob_batched() for VI posteriors, so evaluate one observation at a time.
samples = amortized_vi.sample((1000,), x=x_o)
batched_samples = amortized_vi.sample_batched((1000,), x=x_batch)
log_probs = amortized_vi.log_prob(samples, x=x_o)
Amortized VI currently optimizes the evidence lower bound (ELBO), which corresponds to
reverse KL; the alternative vi_method choices do not apply. Check accuracy on
representative held-out observations, for example with
expected coverage or
SBC.