Fit#
High-level fitting API for blayers models.
Reduces boilerplate when fitting Bayesian models by providing sensible defaults for guides, optimizers, learning rate schedules, and prediction.
Example
from blayers.layers import AdaptiveLayer
from blayers.links import gaussian_link
from blayers.fit import fit
def model(x, y=None):
mu = AdaptiveLayer()('mu', x)
return gaussian_link(mu, y)
# Fit with batched VI
result = fit(model, y=y_train, batch_size=1024, num_epochs=100, x=x_train)
# Predict on new data
preds = result.predict(x=x_test)
print(preds.mean, preds.std)
# Fit with MCMC
result = fit(model, y=y_train, method="mcmc", x=x_train)
preds = result.predict(x=x_test)
# Fit with Stein Variational Gradient Descent
result = fit(model, y=y_train, method="svgd", num_steps=500, x=x_train)
preds = result.predict(x=x_test)
Constants (non-array kwargs) are automatically bound via functools.partial,
so you never need to wrap your model manually:
def model(x, n_conditions, y=None):
...
# n_conditions is an int → auto-bound; x is an array → batched
result = fit(model, y=y_train, batch_size=4096, num_epochs=250,
x=x_train, n_conditions=10)
- class blayers.fit.Predictions(mean, std, samples)[source]#
Bases:
objectPosterior predictive output from
FittedModel.predict().- Parameters:
mean (Array)
std (Array)
samples (Array)
- mean: Array#
Point predictions averaged over posterior samples. Shape
(n,).
- std: Array#
Predictive standard deviation over posterior samples. Shape
(n,).
- samples: Array#
Raw posterior predictive draws. Shape
(num_samples, n, ...).
- __init__(mean, std, samples)#
- Parameters:
mean (Array)
std (Array)
samples (Array)
- Return type:
None
- class blayers.fit.FittedModel(model_fn, method, params=None, guide=None, losses=None, posterior_samples=None, mcmc=None, num_particles=None)[source]#
Bases:
objectA fitted blayers model.
Created by
fit(). Providespredict()for posterior predictive inference andsummary()for inspecting latent variable posteriors.- Parameters:
model_fn (Callable[[...], Any])
method (str)
params (dict[str, Any] | None)
guide (Any | None)
losses (Array | None)
posterior_samples (dict[str, Any] | None)
mcmc (Any | None)
num_particles (int | None)
- model_fn: Callable[[...], Any]#
The model function with any constants already bound.
- method: str#
One of
"vi","mcmc", or"svgd".
- params: dict[str, Any] | None#
SVI / SVGD parameters.
- guide: Any | None#
Fitted variational / Stein guide.
- losses: Array | None#
Per-step loss curve (VI / SVGD).
- posterior_samples: dict[str, Any] | None#
MCMC posterior samples (MCMC only).
- __init__(model_fn, method, params=None, guide=None, losses=None, posterior_samples=None, mcmc=None, num_particles=None)#
- Parameters:
model_fn (Callable[[...], Any])
method (str)
params (dict[str, Any] | None)
guide (Any | None)
losses (Array | None)
posterior_samples (dict[str, Any] | None)
mcmc (Any | None)
num_particles (int | None)
- Return type:
None
- mcmc: Any | None#
The fitted
numpyro.infer.MCMCobject (MCMC only). Retained soto_arviz()can hand it straight toarviz.from_numpyrofor divergences, R-hat, ESS, and log-likelihood.
- num_particles: int | None#
Number of Stein particles (SVGD only).
- predict(*, num_samples=100, seed=1, **data)[source]#
Generate posterior predictive predictions on new data.
- Parameters:
num_samples (int) – Number of posterior samples to draw. For VI this controls the guide; for MCMC all posterior samples are used regardless.
seed (int) – Random seed for the predictive distribution. Fixed by default, so repeated calls return identical draws — vary it to see Monte Carlo variability (identical reruns are not method determinism).
**data – Model inputs excluding
y. Constants that were auto-bound duringfit()should not be passed again.
- Return type:
Notes
.mean/.stdassume a continuous outcome. For the classification / discrete links (logit_link,categorical_link,ordinal_link, count links) the label mean is not meaningful — work from.samplesinstead (e.g. per-observation modal class, or class probabilities via(samples == k).mean(axis=0)).
- summary(*, num_samples=1000, seed=2, **data)[source]#
Summarize the posterior of each latent variable.
- Parameters:
num_samples (int) – Samples to draw from the guide (VI only; ignored for MCMC).
seed (int) – Random seed. Fixed by default, so repeated calls return identical draws — vary it to see Monte Carlo variability.
**data – Model inputs (excluding
y) needed so the guide can determine parameter shapes. Required for VI; ignored for MCMC.
- Returns:
{site_name: {"mean": ..., "std": ..., "q025": ..., "q975": ..., "shape": ...}}- Return type:
dict
- to_arviz(*, y=None, num_samples=1000, seed=3, **data)[source]#
Convert the fit to an ArviZ
InferenceData.Reuses NumPyro’s own ArviZ bridge rather than reimplementing diagnostics:
MCMC — delegates to
arviz.from_numpyro(mcmc), which carries over posterior draws, sample stats (divergences), and per-observation log-likelihood.y/**dataare ignored (already baked into the completed MCMC run).VI — draws from the fitted guide, computes per-observation log-likelihood with
numpyro.infer.log_likelihood, and assembles anInferenceDataviaarviz.from_dict. The observedy(and any model inputs) are required so thelog_likelihoodandobserved_datagroups can be built.
The result plugs straight into
arviz.summary(R-hat / ESS),arviz.waic,arviz.loo, and the ArviZ plotting suite — so model comparison isaz.compare({"a": fit_a.to_arviz(...), ...}).- Parameters:
y (jax.Array, optional) – Observed target. Required for VI (to build the
log_likelihoodandobserved_datagroups); ignored for MCMC.num_samples (int) – Posterior draws to take from the guide (VI only).
seed (int) – Random seed for guide sampling (VI only).
**data – Model inputs (e.g.
x) needed to evaluate the model. Ignored for MCMC.
- Return type:
arviz.InferenceData
Notes
SVGD is not supported: its handful of Stein particles do not form a meaningful sample for WAIC/LOO, and its params do not map cleanly onto model sites. Fit with
method="mcmc"ormethod="vi"for ArviZ-based comparison.
- blayers.fit.fit(model_fn, *, y, method='vi', batch_size=None, num_epochs=None, num_steps=None, lr=0.01, schedule='cosine', guide=None, optimizer=None, num_warmup=500, num_mcmc_samples=1000, num_chains=1, autoreparam_model=True, num_particles=10, kernel_fn=None, seed=0, **kwargs)[source]#
Fit a blayers model via variational inference, MCMC, or SVGD.
Keyword arguments that are JAX/numpy arrays are treated as data and batched during training. Non-array keyword arguments (ints, floats, strings, etc.) are treated as constants and bound to the model via
functools.partialso they don’t need to be passed again at predict time.- Parameters:
model_fn (Callable) – A NumPyro model function that accepts
yas a keyword argument.y (jax.Array) – Target / observed values.
method (
"vi","mcmc", or"svgd") – Inference method. Default"vi".batch_size (int, optional) – Mini-batch size for VI. If None the full dataset is used each step (appropriate for small datasets).
num_epochs (int, optional) – Number of full passes through the data. Exactly one of num_epochs or num_steps is required for VI and SVGD.
num_steps (int, optional) – Total number of gradient updates. Exactly one of num_epochs or num_steps is required for VI and SVGD.
lr (float) – Peak learning rate (default 0.01). For SVGD this is the Adagrad step size. Ignored when optimizer is given.
schedule (str) – LR schedule name:
"cosine"(default),"warmup_cosine", or"constant". Only used for VI.guide (type or AutoGuide instance, optional) – Variational family. Pass a class (instantiated on model_fn) or a ready-to-use instance. Default:
AutoDiagonalNormal. Not used for SVGD (which auto-generates anAutoDeltaguide).optimizer (optax.GradientTransformation, optional) – A fully-constructed optax optimizer. When provided, lr and schedule are ignored. Not used for SVGD.
num_warmup (int) – MCMC warmup iterations (default 500).
num_mcmc_samples (int) – MCMC posterior samples to draw (default 1000).
num_chains (int) – Number of MCMC chains (default 1).
autoreparam_model (bool) – Automatically reparameterize LocScale distributions for MCMC (default True).
num_particles (int) – Number of Stein particles (default 10). Only used for SVGD.
kernel_fn (SteinKernel, optional) – Kernel for SVGD. Default:
RBFKernel().seed (int) – Random seed (default 0).
**kwargs – Model inputs. Arrays → batched data. Non-arrays → constants bound via
partial.
- Returns:
Object with
.predict(**data)and.summary(**data)methods.- Return type:
Examples
Batched VI (the common case for large datasets):
>>> result = fit(model, y=y_train, batch_size=4096, num_epochs=250, ... x=x_train, n_conditions=10) >>> preds = result.predict(x=x_test)
Full-dataset VI (small datasets):
>>> result = fit(model, y=y_train, num_steps=20000, x=x_train)
MCMC:
>>> result = fit(model, y=y_train, method="mcmc", x=x_train)
SVGD:
>>> result = fit(model, y=y_train, method="svgd", num_steps=500, ... num_particles=20, x=x_train)
- blayers.fit.sample_prior(model_fn, *, num_samples=500, seed=0, **data)[source]#
Draw from a model’s prior (and prior predictive) before fitting.
Runs the model with no observed
y, so every latent site and the"obs"site are sampled straight from the prior. Use it to sanity-check that your priors imply sensible outcomes — the core of the “tweak priors as you wish” workflow — before committing to inference.- Parameters:
model_fn (Callable) – A blayers / NumPyro model. Pass inputs the same way you would to
fit(), but withouty— supplyingywould condition the"obs"site and defeat the purpose.num_samples (int) – Number of prior draws (default 500).
seed (int) – Random seed (default 0).
**data – Model inputs (e.g.
x) and any constants, used to fix the shapes of the sampled sites.
- Returns:
{site_name: array of shape (num_samples, *site_shape)}, including the prior-predictive"obs"site.- Return type:
dict
Examples
>>> prior = sample_prior(model, x=x_train, num_samples=1000) >>> prior["obs"].shape # (1000, n) prior-predictive outcomes >>> prior["AdaptiveLayer_mu_beta"].mean(axis=0) # prior mean of a latent