petitRADTRANS.sbi.flows.objectives#
Conditional encoder+flow model container and the training objective.
Holds _PosteriorModel (the encoder + flow + auxiliary scale head bundled
as one Equinox module) and the loss functions optimised by
ConditionalFlowPosterior: the
conditional negative-log-likelihood (NPE) objective with its optional spline and
invertibility regularization, and the amortized-variational (ELBO) objective.
Extracted from flows.posterior so the objective maths lives apart from the
estimator’s plumbing.
Classes#
Trainable encoder + conditional flow bundled as one Equinox module. |
Functions#
|
Mean log-amplitude across the spectrum blocks of one observation. |
Per-sample log-amplitude targets for the auxiliary scale loss. |
|
|
Encode a batch of observations into conditioning vectors. |
|
Evaluation NPE loss for one batch (no regularization terms). |
|
Training NPE loss for one batch (with spline / invertibility regularization). |
|
Conditional negative-log-likelihood (NPE) objective for one batch. |
|
Differentiable inverse round-trip + log-det-closure penalty. |
|
Return an amortized-variational (ELBO) training loss. |
|
Per-checkpoint flow invertibility / collapse diagnostics. |
Module Contents#
- class petitRADTRANS.sbi.flows.objectives._PosteriorModel#
Bases:
equinox.ModuleTrainable encoder + conditional flow bundled as one Equinox module.
Holds the observation
encoder, the conditionalflow, and an auxiliaryscale_head(a small linear readout used by the optional amplitude-scale loss), together with the static regularization weights/targets read by the loss functions in this module. Bundling them keeps the whole trainable model a single pytree so Optax updates and Equinox (de)serialization act on it as a unit.- flow: Any#
- scale_head: equinox.nn.Linear#
- aux_scale_loss_weight: float#
- spline_small_bin_regularization_weight: float#
- spline_derivative_regularization_weight: float#
- spline_min_bin_ratio_target: float#
- spline_min_derivative_target: float#
- spline_max_derivative_target: float#
- invertibility_loss_weight: float#
- invertibility_loss_n_samples: int#
- bnpe_balance_loss_weight: float#
- petitRADTRANS.sbi.flows.objectives._mean_spectral_log_scale(blocks: list[petitRADTRANS.sbi.observation.ObservationBlock]) float | None#
Mean log-amplitude across the spectrum blocks of one observation.
Reads each spectrum block’s
log_spectrum_scale(orlog_median_flux) metadata and averages the finite values, giving a single scalar that summarises the observation’s overall flux scale. Used as the regression target of the optional auxiliary scale loss. ReturnsNonewhen no spectrum block carries a finite scale.
- petitRADTRANS.sbi.flows.objectives._scale_targets_from_observations(observations: Any) jax.numpy.ndarray | None#
Per-sample log-amplitude targets for the auxiliary scale loss.
Extracts one scalar log-scale per observation in the batch – from the pre-stacked
log_scalechannel (field index 4) of each spectrum block, or via_mean_spectral_log_scale()for block-list observations. The result is the regression target thescale_headis trained against whenaux_scale_loss_weight > 0, which keeps an explicit amplitude signal in the embedding. ReturnsNonefor observation representations that carry no spectral scale.
- petitRADTRANS.sbi.flows.objectives.batch_embeddings(model: _PosteriorModel, observations: Any) jax.numpy.ndarray#
Encode a batch of observations into conditioning vectors.
Dispatches over the supported observation representations and returns a
(batch, embedding_dim)float32 array: already-encoded arrays pass through;PreStackedObservationsuse the JIT-friendlyencode_from_prestackedpath; a list of equally-structured block lists uses the vmappedencode_stacked_batch; otherwise each observation is encoded individually. This is the single entry point the loss and refinement paths use to turn observations into the flow’s conditioning context.
- petitRADTRANS.sbi.flows.objectives.compute_loss(model: _PosteriorModel, batch: petitRADTRANS.sbi.flows.base.PosteriorBatch) jax.numpy.ndarray#
Evaluation NPE loss for one batch (no regularization terms).
Plain conditional negative log-likelihood, used for validation / model selection where the optimisation-only regularization terms should not perturb the reported value. See
loss_from_observations().
- petitRADTRANS.sbi.flows.objectives.training_loss(model: _PosteriorModel, batch: petitRADTRANS.sbi.flows.base.PosteriorBatch) jax.numpy.ndarray#
Training NPE loss for one batch (with spline / invertibility regularization).
Identical to
compute_loss()but enables the regularization terms that only shape the optimisation (spline bin/derivative penalties and the invertibility penalty). This is the function minimised by the trainer.
- petitRADTRANS.sbi.flows.objectives.loss_from_observations(model: _PosteriorModel, parameters: jax.numpy.ndarray, observations: Any, parameter_space: str, *, include_spline_regularization: bool) jax.numpy.ndarray#
Conditional negative-log-likelihood (NPE) objective for one batch.
Encodes
observationsinto conditioning vectors, evaluates the flow’s log-density ofparametersin the requestedparameter_space(applying the unit-cube change of variables when needed), and returns the mean negative log-likelihood over the finite entries. Non-finite log-probabilities are masked out rather than allowed to poison the average, and the log-density is clipped to a wide finite range for numerical stability.When
include_spline_regularizationis set, two optimisation-only terms are added (and only if their weights are positive): the spline bin-ratio / derivative penalties from_spline_regularization_terms(), which keep a rational-quadratic spline well-conditioned, and the invertibility penalty (invertibility_penalty()), which keeps an iterative-inverse flow invertible as it sharpens. Whenmodel.aux_scale_loss_weight > 0an auxiliary mean-squared error between thescale_headprediction and the per-observation log-amplitude target (_scale_targets_from_observations()) is also added, preserving an explicit amplitude signal in the embedding.Parameters#
- model:
The encoder + flow bundle (
_PosteriorModel).- parameters:
Parameter batch of shape
(batch, n_parameters), inparameter_spacecoordinates.- observations:
Batch of observations in any representation accepted by
batch_embeddings().- parameter_space:
'physical','cube', or'unconstrained'– selects whether the cube change-of-variables correction is applied.- include_spline_regularization:
Whether to add the optimisation-only regularization terms (used for training, disabled for evaluation).
Returns#
- jnp.ndarray
Scalar loss (mean negative log-likelihood plus any enabled penalties).
- petitRADTRANS.sbi.flows.objectives.invertibility_penalty(model: _PosteriorModel, embeddings: jax.numpy.ndarray, n_samples: int) jax.numpy.ndarray#
Differentiable inverse round-trip + log-det-closure penalty.
Draws base samples
z ~ N(0, I), maps them to flow space with the (iterative) inverse, then back to latent space with the analytic forward. The inverse output is detached withstop_gradientso no gradient flows through the bisection solver; the gradient instead trains the forward map to be consistent with its own inverse. This penalises exactly theinverse_forwardround-trip error and the inverse/forward log-det closure that the validation diagnostics report – the quantities that diverge as a neural-autoregressive flow sharpens (val_loss keeps falling while the sampler that draws posterior samples becomes non-invertible, so the deployed posterior predicts nonsense).The penalty is bounded in scale: the reconstruction term is a mean squared error in latent space and the log-det term is normalised by the parameter dimension, so a single
invertibility_loss_weightcontrols both. For flows with an exact analytic inverse (affine/spline) the penalty is ~0 and merely costs a little compute.
- petitRADTRANS.sbi.flows.objectives.make_elbo_loss(log_likelihood_fn: Callable[[jax.numpy.ndarray, Any], jax.numpy.ndarray], parameter_space: str, *, num_samples: int = 1) Callable[[_PosteriorModel, petitRADTRANS.sbi.flows.base.PosteriorBatch, Any], jax.numpy.ndarray]#
Return an amortized-variational (ELBO) training loss.
Maximizes, for observations
xdrawn from the (prior-predictive) dataset, the (tempered) ELBO- ELBO_beta(x) = E_{q(theta|x)}[ beta * log p(x|theta) + log p(theta)
log q(theta|x) ]
with a single- (or few-) sample reparameterized estimator.
q(theta|x)is the conditional flow: latentszare drawn from the flow base and pushed throughflow.inverseto reparameterized samples, so the gradient flows through both the flow and the encoder.The returned loss takes a third argument
beta(a scalar in (0, 1]): the inverse likelihood temperature.betascales the log-likelihood, which for a Gaussian is exactly equivalent to inflating the noise tosigma_eff = sigma / sqrt(beta)(a power posteriorp_betawhose target is the true posterior atbeta = 1). The entropy-log qis kept at full weight. Annealingbetafrom small -> 1 tames the gradient stiffness from the very small observational noise (which would otherwise swamp the entropy term ~10^6 : 1 and drive an over-confident, poorly-located posterior), lets the entropy shape the width during annealing, and recovers the untempered posterior oncebeta = 1.The
-log q(entropy) term diverges to-infasqcollapses to a point mass, so a delta posterior is structurally impossible.log p(x|theta)is supplied by the injected differentiable forward-model likelihood evaluated at the physical parameters reconstructed from the sampled cube coordinates. Withparameter_space='cube'the prior is uniform on the unit hypercube, solog p(theta_cube) = 0and is dropped.Parameters#
- log_likelihood_fn:
(theta_cube, observations) -> (batch,)returning the Gaussian observational log-likelihoodlog p(x | theta)for each batch element. Receives unit-cube coordinates (shape(batch, dim)) and the batch’s prestacked observations; it owns the cube->physical transform, the differentiable forward model, and the noise model. Must be JAX-differentiable w.r.t.theta_cube.- parameter_space:
Must be
"cube".- num_samples:
Number of reparameterized posterior draws per observation used to estimate the ELBO expectation.
1is standard for amortized VI; larger values reduce gradient variance at a proportional forward-model cost.
- petitRADTRANS.sbi.flows.objectives.compute_validation_diagnostics(model: _PosteriorModel, batch: petitRADTRANS.sbi.flows.base.PosteriorBatch, *, verbose_diagnostics: bool = False) dict[str, float]#
Per-checkpoint flow invertibility / collapse diagnostics.
Probes the trained flow on a small slice of a validation batch and returns a dictionary of scalar metrics that quantify how trustworthy the flow’s sampler and density are – the inputs to the checkpoint-selection gate (
_flow_validation_stability_metrics()/_flow_validation_selection_metric()). The metrics fall into a few groups:Round-trip errors –
forward_inverse_*andinverse_forward_*max/mean absolute errors and the log-det closure of the forward/inverse pair. A flow whose analytic forward and (possibly iterative) inverse disagree produces samples that do not match its own density; these errors grow as a neural-autoregressive flow sharpens, which is the dominant way a low-noise posterior silently degrades.Iterative-solver health – residuals, bracket widths, expansion steps, and converged/failure fractions for flows inverted by bisection.
Support occupancy –
cube_edge_hit_rate: the fraction of sampled coordinates pinned at the unit-cube edges, a signature of density collapse.Spline conditioning – the statistics from
_spline_parameter_statistics()(bin widths/heights, derivative extremes, floor-hit fractions).
Parameters#
- model:
The encoder + flow bundle to probe.
- batch:
Validation batch; only the leading
_VALIDATION_DIAGNOSTIC_SAMPLESrows are used.- verbose_diagnostics:
When
True, include the extra per-dimension cube-edge breakdown used by the verbose training diagnostics.
Returns#
- dict[str, float]
Flat mapping of metric name to scalar value (
nanfor metrics that do not apply to the current flow family or an empty batch).