autofit.SMC#
- class SMC[source]#
Bases:
AbstractMCMCA BlackJAX adaptive tempered Sequential Monte Carlo (SMC) non-linear search with a gradient inner kernel.
SMC anneals a cloud of
num_particlesparticles along a tempering path from a normalised starting distribution (lambda = 0) to the posterior (lambda = 1), moving the particles at each temperature with an inner MCMC kernel and reweighting/resampling between temperatures. Two properties make it the lead sampler of the JAX-native wave:It yields the log evidence for free – the sum of every step’s tempering
log_likelihood_incrementislog Z, on the same scale a nested sampler reports.Its inner kernel is gradient-based (MALA by default, HMC optionally), so it exploits the JAX-native differentiable likelihood rather than random-walking.
The autofit
Analysismust therefore be constructed withuse_jax=True(and JAX run in float64,JAX_ENABLE_X64=True); a clear error is raised at fit time otherwise.For BlackJAX, see https://github.com/blackjax-devs/blackjax.
Whitening – and why it is the whole game. The inner kernel takes a single scalar step size, so the target must be close to isotropic and unit-scale for any step to work. The search therefore samples in a whitened space
z, related to the physical parameters by the affine mapx = shift + L @ z, and this is whatinverse_mass_matrixsets:Prior-whitening does not whiten the posterior. Measured on a 15-parameter lens model, the posterior is 269x anisotropic in prior-whitened coordinates (one parameter’s prior scale is 8.0 against a posterior std of 2e-4). A scalar step tuned to the mean of that spread is ~88x too large for the tightest parameter and acceptance pins at exactly 0.000.
Diagonal whitening is not enough. The posterior is correlated (condition number 568, correlation coefficient 0.95 between two parameters); diagonal whitening leaves a thin tilted ridge a spherical proposal walks off. Whitening uses the Cholesky factor of the full covariance.
Cold, there is nothing better than the prior scale, which is what
inverse_mass_matrix=Nonefalls back to.
Warm starting – and how the evidence survives it. These samplers are meant to be handed a starting point near the maximum-likelihood solution by a JAX optimizer; cold-benchmarking them is not a fair test (on the lens model above, every cold arm sat ~190,000 log-units below the optimizer’s solution). To warm start:
search = af.SMC( initializer=result.start_point_from(), inverse_mass_matrix=result, )
Simply dropping the particles at the previous best fit would destroy the log evidence, which is only valid when tempering starts from a normalised distribution. So the warm path does not shortcut
lambda: it still starts the tempering atlambda = 0, but from a normalised Gaussian referenceg = N(shift, L L^T)centred on the warm-start point rather than from the prior, bridginglog target_lambda = log g + lambda * (log prior + log L - log g)
onto BlackJAX’s
logprior_fn + lambda * loglikelihood_fn. Becausegintegrates to 1, the accumulated increments still estimatelog Z = log integral(prior * L)– the true evidence, directly comparable to Nautilus. The prior must carry its normalisation here (it cancels in a Metropolis ratio but not in the evidence), and the whitening Jacobianlog|det L|is added back.Judging a run. Never judge an SMC fit by “it reached
lambda = 1”. When acceptance collapses to ~0, adaptive tempering can force a single huge increment straight tolambda = 1and report a meaninglesslog_evidencewhile still looking converged. Judge it by the per-step acceptance trace and the max-log-likelihood progression, both recorded insearch_internaland surfaced on SamplesSMC asacceptance_rate_list/lambda_list/ess_list.- Parameters:
name (
Optional[str]) – The name of the search, controlling the last folder results are output to.path_prefix (
Optional[str]) – The path of folders prefixing the name folder where results are output.unique_tag (
Optional[str]) – A unique tag for this model-fit, used as a folder between the path prefix and the search name and as the SQLite identifier.num_particles (
int) – The number of SMC particles carried along the tempering path. This is also the number of posterior samples the fit returns.kernel (
str) – The gradient inner kernel used to move the particles at each temperature:"mala"(default) or"hmc". HMC holds acceptance far higher aslambda -> 1but costs ~4x the likelihood/gradient evaluations; measured on the lens model, plain MALA matched its max log likelihood and log evidence at a quarter of the evaluations.num_mcmc_steps (
int) – The number of inner-kernel updates applied to every particle at each temperature.num_integration_steps (
int) – Leapfrog steps per HMC trajectory. Ignored whenkernel="mala".target_ess (
float) – The effective sample size, as a fraction ofnum_particles, that adaptive tempering targets when choosing eachlambdaincrement. Higher means a finer schedule (more, smaller steps).step_size (
Optional[float]) – The inner kernel’s step size, in whitened units.None(default) auto-scales it from the target width (see below). Units trap: MALA proposesx + eps*grad + sqrt(2*eps)*xi, so itsstep_sizeis a squared length and the proposal length issqrt(2*eps); HMC’s step size is a length. The auto-scaling applies the optimal MALA ruleell = 2.38 * d^(-1/6) * sigma,eps = ell^2 / 2, andsigma * d^(-1/4)for HMC, so a hand-setstep_sizemust respect the same convention. There is deliberately no per-temperature step adaptation: BlackJAX’sinner_kernel_tuningwas measured to collapse acceptance (0.04-0.12, worse than a fixed step’s 0.84 -> 0.15 decay) on this problem.whiten_inflate (
float) – The warm-start Gaussian reference is deliberately widened by this factor so it covers the posterior (the tempering path misses mass if the reference is narrower than the target). It also sets the auto step size: in whitened units the reference has width 1 but the posterior has width1 / whiten_inflate, so the step targets the posterior width. Targeting the reference width instead overshoots bywhiten_inflate^2and pins acceptance at zero (measured:eps=1.148 -> acc 0.00,eps=0.1 -> acc 0.94).max_smc_steps (
int) – A hard cap on the number of SMC temperatures, so a pathological run terminates instead of annealing forever. A run that hits it is reported as not converged.batch_size (
int) – Forwarded to BlackJAX: when> 0, particles are processed in sequential batches of this size viajax.lax.mapinstead of one fulljax.vmap, trading speed for peak GPU memory.0(default) keeps the fullvmap.seed (
int) – Integer seed passed tojax.random.PRNGKey.initializer (
Optional[Initializer]) – Generates the initial particles. Defaults to InitializerPrior – cold SMC’s evidence requires the particles to be drawn from the prior, so the InitializerBall default the other MCMC searches use would silently invalidatelog_evidence. When warm-started (inverse_mass_matrixgiven), the initializer supplies only the centre of the Gaussian reference and the particles are drawn from that reference instead – passresult.start_point_from()(equivalentlyInitializerParamStartPoints.from_result(result)).inverse_mass_matrix (
Union[None,str,ndarray,object]) –The covariance the sampling space is whitened by (named for API parity with BlackJAXNUTS, where the same specification seeds window adaptation’s metric):
None(default): cold. Whiten by the per-parameter prior width.a 1-D
numpyarray of shape(n_dim,): a diagonal covariance.a 2-D
numpyarray of shape(n_dim, n_dim): a full covariance, Cholesky-factorised.a Result or Samples object: its
samples.covariance_matrix. RaisesValueErrorif that covariance looks MLE-only (too few samples, or non-finite / identity) – pass an explicit array in that case, e.g. from a Laplace approximation.
The
"diagonal"/"dense"strings BlackJAXNUTS accepts are rejected here: they name an adaptation strategy, and SMC does not adapt its metric, so they would silently give a cold run.auto_correlation_settings (
AutoCorrelationsSettings) – Kept for API parity with the other MCMC searches. SMC particles are not a chain, so no auto-correlation diagnostics are computed andcheck_for_convergencedefaults toFalse.iterations_per_full_update (
Optional[int]) – Inherited from the autonerves config whenNone. SMC callsperform_updateonce per temperature (SMC steps are coarse and few), so this does not chunk the run.number_of_cores (
int) – Used only when generating the initial particles. The tempering loop itself runs vmapped on a single device.silence (
bool) – If True, the default print output of the non-linear search is silenced.session (
Optional[Session]) – An SQLalchemy session instance.
Methods
Override in subclasses to reduce sampler iterations for test mode.
check_modelcopy_with_pathsThe inner kernel's step size in whitened units:
step_sizeif given, otherwise auto-scaled from the target width.exact_fitfitFit a model, M with some function f that takes instances of the class represented by model M and gives a score for their fitness.
make_poolMake the pool instance used to parallelize a NonLinearSearch alongside a set of unique ids for every process in the pool.
make_sneakier_poolmake_sneaky_poolCreate a pool for multiprocessing that uses slight-of-hand to avoid copying the fitness function between processes multiple times.
optimisePerform optimisation for expectation propagation.
Pickle the search-internal dict.
perform_updatePerform an update of the non-linear search's model-fitting results.
perform_visualizationPerform visualization of the non-linear search's model-fitting results.
plot_resultsplot_start_pointVisualize the starting point of the non-linear search, using an instance of the model at the starting point of the maximum likelihood estimator.
post_fit_outputCleans up the output folderds after a completed non-linear search.
pre_fit_outputOutputs attributes of fit before the non-linear search begins.
result_via_completed_fitReturns the result of the non-linear search of a completed model-fit.
samples_fromLoads the samples of a non-linear search from its output files.
Convert the particle cloud pickled under
search_internal/into a SamplesSMC.start_resume_fitAttributes
Load the pickled search-internal dict written by
_fit.Whether the run whitens (and tempers) from a warm-start covariance rather than from the prior.
loggerLog 'msg % args' with severity 'DEBUG'.
namepathsquick_update_messageOne line, logged at the start of every search, telling the user the real cadence of the on-the-fly maximum-likelihood updates.
should_plot_start_pointtimerReturns the timer of the search, which is used to output informaiton such as how long the search took and how much parallelization sped up the search time.
- apply_test_mode()[source]#
Override in subclasses to reduce sampler iterations for test mode.
Called during __init__ when test mode is active (level 1). Subclasses should directly mutate instance attributes to minimize the number of iterations the sampler performs.
- property is_warm_start: bool#
Whether the run whitens (and tempers) from a warm-start covariance rather than from the prior. Set by passing a Result / Samples / covariance array as
inverse_mass_matrix.
- effective_step_size(n_dim)[source]#
The inner kernel’s step size in whitened units:
step_sizeif given, otherwise auto-scaled from the target width.Warm-started, the target width is the posterior width, which in whitened units is
1 / whiten_inflate(the reference is inflated to cover the posterior, so scaling to the reference’s own width of 1 overshoots bywhiten_inflate^2). Cold, the posterior width is unknown and _COLD_TARGET_WIDTH is used.- Parameters:
n_dim (
int) – The number of free model parameters, which sets the dimension scaling of the optimal step.
- property backend_filename#
- output_search_internal(search_internal)[source]#
Pickle the search-internal dict.
BlackJAX has no native on-disk format (cf. emcee’s HDFBackend), so we round-trip the particle cloud + tempering diagnostics via pickle, bypassing
self.paths.save_search_internalfor the same reason BlackJAXNUTS does: the autofit dill path chokes on a few numpy/jax-backed members, and a direct pickle of already-numpy data is robust.NullPaths(noname/path_prefix) setssearch_internal_pathtoNoneto suppress disk output – skip silently in that case.
- samples_via_internal_from(model, search_internal=None)[source]#
Convert the particle cloud pickled under
search_internal/into a SamplesSMC.SMC particles are weighted samples: each carries the normalised importance weight blackjax assigns it at the current temperature, so the weights (not a uniform 1.0) are what the PDF, medians and errors are computed from.