API Reference
Per-class arguments, output shapes, and stated limits. This is a lookup page, not a tutorial: it assumes you have already fitted something in Get started and now need the exact behaviour of one call.
Coverage is not complete. StructuralModel, BayesianDynamicGLM, VarianceParameter
and ForecastSession are public but documented only in their guides —
structural composition and
dynamic GLMs.
Each section states what a model does not do as well as what it does. Those limits are deliberate and current; where a thing is not supported, it says so next to the thing.
Linear Gaussian state-space models
LinearGaussianStateSpace implements a Kalman filter and Rauch--Tung--Striebel
smoother for an arbitrary-dimensional latent state and a single scalar observation per
time point. Arrays use the conventional model
The transition is the same at every time step. The observation row is the same at every time step unless you set per-time rows; see what may vary with time below.
initial_mean and initial_covariance describe x[-1], immediately before the
first observation. The filter applies one transition/process-noise prediction before
updating on y[0]. This convention also applies when forecasting an empty history.
Construct a general model with NumPy arrays, or use the local_level(),
local_linear_trend(), seasonal_local_level(), and zero-mean stationary_ar1()
constructors. filter(y) returns predicted and filtered state means/covariances plus
the observed-data log likelihood. smooth(y) returns the filtered and smoothed state
moments and the same log likelihood; it does not carry the predicted moments, so keep
the filter(y) result if you need those. forecast(y, steps) returns future
latent-state and observation means/variances. A NaN observation is treated as missing
and causes a prediction-only step; infinities are rejected.
forecast.observation_covariance contains the joint covariance across future scalar
observations. cumulative_observation_means, cumulative_observation_variances, and
cumulative_interval(level=0.95) summarize prefix totals without discarding
cross-horizon dependence. forecast.interval(level=0.95) returns lower and upper pointwise Gaussian
predictive bounds. Its uncertainty_kind is "conditional_fixed_parameters":
the interval includes filtered-state, future-process, and observation noise, but
does not include uncertainty about the supplied system parameters. It is therefore
a conditional predictive interval, not yet a parameter-integrated Bayesian credible
interval.
seasonal_local_level(period=..., ...) builds a sum-to-zero dummy-seasonal system.
Its supplied seasonal and level variances remain fixed; it does not estimate them.
The optional initial_seasonal_effects is one complete cycle in forecast order and
must sum to zero.
What may vary with time
Some of the system may vary with time and some may not. The observation row may vary:
with_observation_rows(rows) supplies one row per training time. A model built that
way then requires forecast(y, steps, future_observation_rows=R): calling
forecast(y, steps) on it raises rather than silently reusing the constant row, and R
must have exactly steps rows. See
time-varying observation rows.
The transition matrix, the process covariance, and the initial mean and covariance are
constant for the whole series and horizon; there is no API to vary them. In the Rust
core the per-time observation variance can also vary, through
with_observation_variances; that is used internally by the structural models and is
not exposed in Python, where the observation variance is a single constant.
Whether or not the rows vary, the parameters are supplied, not estimated. Noise is
Gaussian and the observation is univariate. Process covariance may be positive
semidefinite so deterministic state shifts are representable; initial covariance must
be positive definite, and observation variance must be positive. This API does not
estimate system parameters, support multivariate observations, or integrate a Kalman
likelihood into ModelBuilder.
Filtering, smoothing, and forecasting release the Python GIL after converting the input NumPy array.
Joint hierarchical means for ragged series
BayesianHierarchicalMean fits all supplied programs in one posterior:
population_mean ~ Normal(population_mean_prior, population_variance_prior)
group_mean[g] ~ Normal(population_mean, group_variance)
program_mean[p] ~ Normal(group_mean[group_index[p]], program_variance)
y[p, t] ~ Normal(program_mean[p], observation_variance)
The three variances have explicit InverseGammaPrior(shape, scale) priors. The
specialized conjugate Gibbs kernel draws exact full conditionals, so it does not send
NUTS/HMC through the funnel geometry of a centered hierarchy. Centered Gibbs chains can
still be highly autocorrelated when a variance component approaches zero. This remains
finite MCMC: use multiple chains and inspect fit.summary() or fit.diagnostics() for
rank-normalized R-hat, bulk/tail ESS, and MCSE, especially with few groups or sparse
programs.
model = rmc.BayesianHierarchicalMean(
group_variance_prior=rmc.InverseGammaPrior(3.0, 20.0),
program_variance_prior=rmc.InverseGammaPrior(3.0, 10.0),
observation_variance_prior=rmc.InverseGammaPrior(3.0, 25.0),
population_mean_prior=100.0,
population_variance_prior=400.0,
)
fit = model.fit(
[program_a, program_b, program_c],
group_index=[0, 0, 1],
program_names=["a", "b", "c"],
group_names=["division-a", "division-b"],
chains=4,
warmup=500,
draws=1_000,
seed=42,
)
forecast = fit.forecast(steps=12, seed=43)
Series are genuinely ragged and each may contain one or more finite observations.
NaN positions are ignored by the likelihood, infinities are rejected, and input
program order is preserved. Conditional on the variance draws, the program posterior
mean weights its sample mean by
n * program_variance / (n * program_variance + observation_variance). A one-point
program therefore receives more groupward shrinkage than an otherwise comparable long
program. How strongly either program leans on its group depends on the learned ratio of
program to observation variance; the shrinkage strength is inferred rather than manually
assigned.
fit.get_samples() returns scalar population/variance/standard-deviation arrays shaped
(chain, draw), group means shaped (chain, draw, group), and program means shaped
(chain, draw, program). time_counts, observed_counts, group_index,
program_names, and group_names preserve the ragged hierarchy metadata.
Hierarchical validation and numerical failures raise InferenceError, which subclasses
ValueError.
Forecast state_samples and observation_samples have shape
(chain, draw, program, step). Selecting [:, :, program, :] produces the same
(chain, draw, step) layout as other fitted forecast objects. Rollups must be formed
inside each joint draw:
company_draws = forecast.observation_samples.sum(axis=2)
division_draws = forecast.group_observation_samples # chain, draw, group, step
assert np.array_equal(company_draws, forecast.total_observation_samples)
Forecast storage is contiguous per posterior draw and does not retain a redundant copy of the static state at every step. To fail predictably instead of risking process OOM, one fit is limited to 50 million retained parameter values and one forecast call to 25 million materialized observation values. Refit with fewer retained chains/draws, or reduce the forecast horizon, if a guard is reached.
BayesianHierarchicalMean pools a static intercept only. Time ordering does not affect
the fit, and future observations are conditionally iid around each program mean. For a
pooled level that moves over time, see BayesianHierarchicalDynamicRegression in
dynamic GLMs. This model does not
pool trends or seasonal shapes and is not a stochastic local-level model. A common
within-program observation variance and shared group/program variances are assumed;
variance priors can materially influence singleton programs and weakly populated groups.
Bayesian local-level forecasting
BayesianLocalLevel estimates the two unknown noise variances in the scalar model
x[-1] ~ Normal(initial_mean, initial_variance)
x[t] = x[t-1] + Normal(0, process_variance)
y[t] = x[t] + Normal(0, observation_variance)
It uses joint forward-filtering/backward-sampling state draws and conjugate Gibbs updates for the variances, following the FFBS/data-augmentation approach described by Frühwirth-Schnatter (1994) and Carter and Kohn (1994).
Priors are deliberately explicit because variance scales depend on the units of the series:
model = rmc.BayesianLocalLevel(
process_variance_prior=rmc.InverseGammaPrior(shape=2.5, scale=0.3),
observation_variance_prior=rmc.InverseGammaPrior(shape=2.5, scale=0.6),
initial_mean=0.0,
initial_variance=4.0,
)
fit = model.fit(y, chains=4, draws=1000, warmup=500, seed=42)
forecast = fit.forecast(steps=12, seed=43)
predictive_lower, predictive_upper = forecast.interval(0.95)
state_lower, state_upper = forecast.state_interval(0.95)
InverseGammaPrior(shape, scale) is a prior on a variance, with density
proportional to x^(-shape-1) exp(-scale/x). fit.get_samples_2d() returns both
variance and standard-deviation draws plus the terminal latent level, all preserving
(chain, draw) shape. fit.to_arviz() exports the parameters and observed series for
convergence checks.
forecast.state_samples and forecast.observation_samples have shape
(chain, draw, step) and contain coherent paths. state_interval() is a pointwise
equal-tailed latent-state posterior credible interval. interval() is a pointwise
equal-tailed posterior-predictive interval for future observations. The latter
integrates parameter uncertainty, terminal-state uncertainty, future process noise,
and observation noise. It is not a simultaneous trajectory band.
NaN retains a missing time step and infinities are rejected. Fitting requires at
least two finite observations. This specialized model assumes equally spaced scalar
Gaussian observations. Add known covariates with fit(..., exog=X,
coefficient_prior=GaussianCoefficientPrior(...)) and supply future exog to the
returned regression fit. See regression and Fourier forecasting.
Irregular timestamps are not modeled automatically. Gibbs output remains finite
MCMC output, so inspect multiple-chain convergence and effective sample sizes rather
than treating it as an analytic posterior.
Bayesian seasonal local-level forecasting
BayesianSeasonalLocalLevel adds one stochastic sum-to-zero dummy-seasonal component
to a stochastic local level. It jointly samples latent states with multivariate FFBS and
updates level, seasonal, and observation variances from explicit inverse-gamma priors.
model = rmc.BayesianSeasonalLocalLevel(
period=12,
level_variance_prior=rmc.InverseGammaPrior(3.0, 2.0),
seasonal_variance_prior=rmc.InverseGammaPrior(3.0, 1.0),
observation_variance_prior=rmc.InverseGammaPrior(3.0, 8.0),
initial_level=100.0,
initial_seasonal_effects=np.zeros(12),
initial_level_variance=25.0,
initial_seasonal_variance=9.0,
)
fit = model.fit(y, chains=4, draws=1000, warmup=500, seed=42)
forecast = fit.forecast(steps=12, seed=43)
lower, upper = forecast.interval(0.95)
cumulative_lower, cumulative_upper = forecast.cumulative_interval(0.95)
The initial seasonal vector is one cycle in forecast order and must sum to zero.
forecast.level_samples, seasonal_samples, observation_samples, and
cumulative_observation_samples have shape (chain, draw, step). Cumulative paths are
formed inside each posterior draw before quantiles are calculated.
The fitted model is equally spaced, scalar, Gaussian, and single-seasonal. Seasonal
innovations preserve structural identification but do not force every realized rolling
cycle to sum exactly to zero. Missing values retain their time positions. Fitting
requires three finite observations, one per inferred variance, with no full-cycle
minimum. Short histories can be
strongly sensitive to initial-state and variance priors. The regression extension and
fourier_design provide a smaller harmonic model for long periods.
All specialized fits expose summary(), diagnostics(), and sampler_stats.
Hamiltonian divergences and acceptance are unavailable for Gibbs/FFBS and exact
conjugate sampling. Independent batches preserve cell identity
and return per-cell fits, errors, diagnostics, and forecasts.
For sparse amounts, use BayesianHurdleLogNormal; for
payment-event triangles, use DirichletMultinomialRunoff. Their data,
prior, and inference contracts are documented separately from Gaussian forecasting.
Bayesian local-linear-trend forecasting
BayesianLocalLinearTrend fits the two-state structural model
[level[-1], slope[-1]] ~ Normal(initial_mean, initial_covariance)
level[t] = level[t-1] + slope[t-1] + Normal(0, level_variance)
slope[t] = slope[t-1] + Normal(0, slope_variance)
y[t] = level[t] + Normal(0, observation_variance)
All three variance priors are explicit. The initial covariance is configured with level variance, slope variance, and an optional level/slope covariance and must be strictly positive definite.
model = rmc.BayesianLocalLinearTrend(
level_variance_prior=rmc.InverseGammaPrior(3.0, 0.24),
slope_variance_prior=rmc.InverseGammaPrior(3.0, 0.04),
observation_variance_prior=rmc.InverseGammaPrior(3.0, 0.70),
initial_level=0.0,
initial_slope=0.0,
initial_level_variance=4.0,
initial_slope_variance=1.0,
)
fit = model.fit(y, chains=4, draws=1000, warmup=500, thin=1, seed=42)
forecast = fit.forecast(steps=12, seed=43)
predictive_lower, predictive_upper = forecast.interval(0.95)
level_lower, level_upper = forecast.level_interval(0.95)
slope_lower, slope_upper = forecast.slope_interval(0.95)
Level, slope, and observation samples each have shape (chain, draw, step) and belong
to the same coherent paths. interval() is the observation posterior-predictive
interval; level_interval() and slope_interval() summarize the latent states. The
process innovations are independent (diagonal process covariance). NaN retains a
scheduled missing time point. Variance components can be weakly identified near zero,
so inspect multi-chain convergence.
Bayesian autoregression AR(p)
BayesianAutoRegression(order=p) and its shorter alias BayesianAR fit any positive
caller-selected order under the conditional Gaussian likelihood
y[t] = intercept + phi[1] y[t-1] + ... + phi[p] y[t-p] + epsilon[t]
epsilon[t] ~ Normal(0, innovation_variance)
The explicit conjugate prior is
innovation_variance ~ InverseGamma(variance_shape, variance_scale)
coefficients | innovation_variance
~ Normal(coefficient_mean, innovation_variance * coefficient_precision^-1)
Coefficients are always [intercept, lag_1, ..., lag_p].
order = 3
prior = rmc.NormalInverseGammaPrior(
coefficient_mean=np.zeros(order + 1),
coefficient_precision=np.eye(order + 1) * 0.05,
variance_shape=2.5,
variance_scale=0.2,
)
model = rmc.BayesianAutoRegression(order=order, prior=prior)
fit = model.fit(y, chains=4, draws=1000, seed=42)
forecast = fit.forecast(steps=12, seed=43)
lower, upper = forecast.interval(0.95)
This is a directly observed AR(p), distinct from the latent
LinearGaussianStateSpace.stationary_ar1() model with separate process and measurement
noise. The conjugate posterior draws are independent, so there is no warmup or thinning.
fit.get_samples() returns coefficient with shape (chain, draw, p + 1) and innovation
variance/standard deviation with shape (chain, draw). Forecast observation and recursive
conditional-mean paths have shape (chain, draw, step).
The likelihood conditions on the first p observations. Input must be complete, finite,
equally spaced, and longer than p. Coefficient draws are not restricted to the
stationary region and are never silently clipped; explosive recursive draws return a
numerical error. interval() is a pointwise equal-tailed posterior-predictive interval,
not a simultaneous path band.
ModelBuilder
Constructs a model. Data can be bound at build time or passed later to rmc.sample(),
rmc.batch_sample(), or rmc.sample_prior_predictive(). dims maps a data key to a
named population dimension; keys left out use the compatibility dimension "obs".
Data values must be 1-D or 2-D arrays (or lists) of real numbers. Integer arrays are
accepted when every value is exactly representable as a float64. Scalars, arrays
with more than two dimensions, boolean, string, bytes, object or complex arrays,
True/False inside a list, masked arrays with a masked entry, and long doubles or
integers that float64 would round are rejected with an error naming the key rather
than converted. Convert an object column with .astype(float); mark a missing value
with NaN where the model allows one.
The builder also has data(name, dim=None), potential(name, expression) for a bare
log-density term (the expression must be scalar), and deterministic(name, expression)
for a named quantity recorded alongside the draws. See
custom models.
Priors
| Method | Distribution | Notes |
|---|---|---|
normal_prior(name, mu, sigma) |
Normal(mu, sigma) | mu and sigma may be float or earlier ParamRef values |
half_normal_prior(name, sigma) |
HalfNormal(sigma) | sigma may be float or earlier ParamRef |
exponential_prior(name, rate) |
Exponential(rate) | rate may be float or earlier ParamRef |
log_normal_prior(name, mu, sigma) |
LogNormal(mu, sigma) | mu and sigma may be float or earlier ParamRef |
student_t_prior(name, nu, mu=0.0, sigma=1.0) |
StudentT(nu, mu, sigma) | scalar only |
gamma_prior(name, alpha, beta) |
Gamma(alpha, beta) | scalar only |
beta_prior(name, alpha, beta) |
Beta(alpha, beta) | scalar only |
uniform_prior(name, lower=0.0, upper=1.0) |
Uniform(lower, upper) | scalar only |
vector_normal_prior(name, n, mu=0.0, sigma=1.0) |
Normal(mu, sigma)^n | explicit vector block |
bernoulli_prior(name, p=0.5) |
Bernoulli(p) | discrete; see the note below |
poisson_prior(name, lam) |
Poisson(lam) | discrete; see the note below |
All scalar prior methods return a ParamRef. vector_normal_prior() returns a VectorParamRef.
The two discrete priors are not merely a poor fit for gradient-based inference; they
are refused by it. A model declaring a Bernoulli or Poisson prior raises ValueError
from builder.compile(), rmc.sample(), and rmc.batch_sample(). They are usable
only with sample_prior_predictive(). Posterior inference needs continuous parameters
or an explicit marginalization you write yourself.
Hierarchical priors and automatic non-centering
Scalar hierarchical priors are supported for:
normal_prior()with parameter-valuedmuand/orsigmahalf_normal_prior()with parameter-valuedsigmaexponential_prior()with parameter-valuedratelog_normal_prior()with parameter-valuedmuand/orsigma
When a scalar normal_prior() depends on another parameter through mu or sigma,
rustmc automatically compiles it as a non-centered latent where appropriate. Users still
see the logical parameter name in summaries, diagnostics, ArviZ export, and predictive
workflows.
Vector-valued hierarchical priors are not yet supported.
Likelihoods
| Method | Family | Linear predictor | Extra parameter |
|---|---|---|---|
normal_likelihood(name, mu_expr, sigma, observed_key) |
Normal | mu_expr |
sigma is float or ParamRef |
bernoulli_logit_likelihood(name, eta_expr, observed_key) |
Bernoulli with logit link | eta_expr |
none |
poisson_log_likelihood(name, eta_expr, observed_key) |
Poisson with log link | eta_expr |
none |
exponential_likelihood(name, eta_expr, observed_key) |
Exponential with log-rate link | eta_expr |
none |
log_normal_likelihood(name, mu_expr, sigma, observed_key) |
LogNormal | mu_expr |
sigma is float or ParamRef |
negative_binomial_likelihood(name, eta_expr, alpha, observed_key) |
NegativeBinomial with log-mean link | eta_expr |
alpha is float or ParamRef |
Likelihood expressions accept:
- a bare
ParamRef beta * "x"alpha + beta * "x"beta @ "X"for matrix-vector regression- additive constants such as
alpha + beta * "x" + 1.0
That list is the fused fast paths, not the whole vocabulary. Expressions also support
-, /, ** and unary negation, and the methods .exp(), .log(), .sqrt(),
.sigmoid(), .tanh(), .softplus(), .sin(), .cos() and .sum().
beta["group_key"] selects one element of a vector parameter per observation, keyed
by an integer-valued data column. Custom models has the details.
build()
Returns a ModelSpec, the opaque handle passed to the sampling and predictive APIs.
compile()
Returns a CompiledModel containing immutable graph structure and a DataSchema, without
concrete observation payloads. Matrix column counts and parameter shapes are structural;
the observation row count belongs to each binding.
CompiledModel
| Member | Description |
|---|---|
param_names |
Structural parameter names |
required_keys |
Predictor, response, and matrix keys required by the schema |
structure_id |
Process-local identity useful for checking structure reuse |
bind(data, id="0", strict=True, check_finite=True) |
Validate data and return a BoundModel |
sample(data_or_binding, **sampler_options) |
Sample one validated dataset and return FitResult |
sample_batch(datasets, ids=None, shared=None, **sampler_options) |
Sample many datasets and return BatchFit in input order |
BoundModel exposes id and n_obs and can be reused only with the CompiledModel
that created it. In sample_batch(), keys supplied through shared are converted once
and cannot be shadowed by a per-dataset dictionary. Dataset IDs must be unique and match
the number of datasets.
BatchFit.ids preserves caller order; len(batch_fit) returns the dataset count and
batch_fit[i] returns a BatchResult.
sample_batch(..., errors=...) chooses what happens when one dataset fails to bind or
sample. The default errors="raise" propagates the first failure. With
errors="collect", every cell is attempted and BatchFit.errors returns a
{dataset_id: message} mapping containing only the failed cells, so an empty mapping
means every cell succeeded. Successful cells are retrieved normally; batch_fit.get(id)
and batch_fit[i] on a failed cell raise ValueError carrying that cell's ID and
message rather than returning a placeholder. len(batch_fit) still counts every dataset,
failed cells included. Any other value of errors raises ValueError.
batch = compiled.sample_batch(
[good_data, malformed_data], ids=["a", "broken"], errors="collect",
)
batch.errors # {"broken": "..."}
fit = batch.get("a") # BatchResult
batch.get("broken") # raises ValueError: dataset 'broken': ...
Context-manager contract
ModelBuilder, CompiledModel, BoundModel, and BatchFit may be used with
with when lexical scoping improves readability:
with rmc.ModelBuilder() as builder:
beta = builder.normal_prior("beta", 0.0, 1.0)
builder.normal_likelihood("obs", beta * "x", 1.0, "y")
with builder.compile() as compiled:
with compiled.bind(data, id="store-17") as bound:
fit = compiled.sample(bound)
Entering returns the same object and exiting propagates exceptions. No object is closed or invalidated, so the builder, compiled model, binding, and batch result remain usable afterward. There is no ambient or thread-local current model: model declarations must always be called on the intended builder. Context syntax does not compile a builder or bind data automatically.
rmc.sample()
fit = rmc.sample(
model_spec,
data=None,
chains=4,
draws=1000,
warmup=500,
seed=42,
threads=0,
step_size=0.0,
target_accept=0.8,
sampler="nuts",
max_tree_depth=10,
num_leapfrog_steps=15,
show_progress=True,
init=None,
metric="auto",
)
Returns a FitResult.
Notes:
samplermay be"nuts"or"hmc".initsupplies starting positions. WithNone, each chain starts at its own random point, uniform on (-2, 2) in unconstrained coordinates, as Stan does. A start whose log density or gradient is not finite is redrawn; if none of 100 draws works, the origin is tried, and failing thatsample()asks forinit.- Chain
cdraws from a stream derived fromseedandcthrough separate mixing rounds, so neither neighbouring seeds nor any fixed offset of the seed reproduce another fit's chains. metricsets how warmup adapts the metric of vector parameters."diag"is Stan's default diagonal metric."dense"estimates a full covariance for each vector parameter of at most 512 elements, shrinking its correlations when a window has fewer than two draws per element."auto"(the default) stays diagonal unless a vector parameter's warmup draws show correlation well beyond their own sampling noise, which suits strongly correlated regression coefficients. It considers a dense block only when a warmup window has at least two draws per element, so at the defaultwarmup=500vectors of more than 100 elements stay diagonal; use a longer warmup or"dense"for a large, strongly correlated vector. Scalar parameters are always diagonal.- Warmup uses a windowed schedule, Stan's from 500 iterations: an initial buffer of
min(75, 15%)of warmup, doubling metric windows from 25 draws (fewer when warmup is below about 170), and a terminal buffer ofmin(50, 10%)but at least 25 iterations. A window whose successor could not fit at twice its size is stretched to the terminal buffer, so no window after the first is shorter than 25 draws. Below 41 warmup iterations only the step size adapts. threads=0uses Rayon defaults.max_tree_depthapplies to NUTS.num_leapfrog_stepsapplies to HMC.step_size=0.0means auto-tune.target_acceptcontrols dual-averaging during warmup and must be between 0 and 1.
rmc.batch_sample()
results = rmc.batch_sample(
models, # list[(ModelSpec, data_dict)]
chains=1,
draws=500,
warmup=300,
seed=42,
sampler="nuts",
step_size=0.0,
target_accept=0.8,
max_tree_depth=8,
num_leapfrog_steps=15,
show_progress=True,
metric="auto",
)
Returns a list of BatchResult, one per model.
Unlike the original throughput-only path, batch sampling now supports multiple chains per
model and both NUTS and fixed-trajectory HMC. Use chains > 1 when reliability matters more
than absolute batch throughput.
FitResult
| Method | Returns | Description |
|---|---|---|
summary() |
str |
Formatted diagnostics table |
mean() |
dict[str, float] |
Posterior mean per parameter |
std() |
dict[str, float] |
Posterior std per parameter |
get_samples() |
dict[str, np.ndarray] |
Flattened samples across chains |
get_samples_2d() |
dict[str, np.ndarray] |
Samples shaped (chains, draws) |
diagnostics() |
list[dict] |
Per-parameter diagnostics; a value that cannot be computed is None |
transition_diagnostics() |
dict |
Per-chain and aggregate energy, tree-depth, and leapfrog telemetry |
accept_rates() |
list[float] |
Per-chain accept rates |
step_sizes() |
list[float] |
Per-chain adapted step sizes |
divergences() |
list[int] |
Per-chain divergence counts |
posterior_predictive(n_samples=None, seed=42, data=None, expected=False, sizes=None) |
dict[str, np.ndarray] |
Posterior predictive samples shaped (n_samples, n_obs) per likelihood. data substitutes new predictors; expected=True returns conditional means instead of sampled draws |
predict(data=None, seed=42, expected=False, sizes=None) |
dict[str, np.ndarray] |
Predictive draws on (chain, draw, obs) axes |
deterministics(data=None, sizes=None) |
dict[str, np.ndarray] |
Draws of each declared deterministic(), on (chain, draw) or (chain, draw, obs) axes |
log_likelihood() |
dict[str, np.ndarray] |
Pointwise log-likelihood shaped (chain, draw, obs) per likelihood |
to_arviz(include_ppc=False, ppc_samples=None, ppc_seed=42, include_log_likelihood=True) |
ArviZ inference container | Convert to ArviZ's version-native container (InferenceData on 0.x, DataTree on 1.x) with observed data, optionally including predictive draws and pointwise log-likelihood |
log_likelihood() is the intended bridge for az.loo(...) and az.waic(...).
to_arviz(include_ppc=True) writes the predictive group with real (chain, draw, obs)
axes that line up with the posterior group, rather than flattening the draws into a
single synthetic chain. Predictive draw (c, d) is the one generated from posterior
draw (c, d). ppc_samples thins the draw axis rather than a flattened pool: the same
ppc_samples // n_chains draw indices are kept in every chain, and those indices are
written onto the predictive group's draw coordinate, so
idata.posterior.sel(draw=idata.posterior_predictive.draw) recovers the parameter draws
that produced each predictive draw. fit.posterior_predictive() is unaffected and still
returns (n_samples, n_obs).
rmc.sample_prior_predictive()
Returns dict[str, np.ndarray] containing:
- one 1-D array per parameter with
n_samplesprior draws - one 2-D array per likelihood with shape
(n_samples, n_obs) - one array per declared
deterministic(): 1-D when the expression is scalar, and(n_samples, n)when it is vector-valued
For automatically non-centered scalar hierarchical normals, the returned parameter draws use the logical parameter name, not the hidden raw latent.
A potential() term is a bare log-density with no generator behind it, so a model
declaring one cannot be simulated forward. This call raises ValueError for such a
model. Bernoulli and Poisson priors, by contrast, are supported here and only here.
BatchResult
Each element returned by rmc.batch_sample() is a BatchResult.
| Method / property | Returns | Description |
|---|---|---|
mean() |
dict[str, float] |
Posterior mean per parameter |
std() |
dict[str, float] |
Posterior std per parameter |
get_samples() |
dict[str, np.ndarray] |
Flattened samples across all chains and draws |
get_samples_2d() |
dict[str, np.ndarray] |
Samples shaped (chains, draws) |
chains |
int |
Number of chains run for this model |
draws |
int |
Number of post-warmup draws per chain |
accept_rate |
float |
Mean accept rate across chains |
accept_rates |
list[float] |
Per-chain accept rates |
divergences |
int |
Total divergences across chains |
divergences_per_chain |
list[int] |
Per-chain divergence counts |
ParamRef and Expr operators
beta * "x" # elementwise scalar predictor
alpha + beta * "x" # additive linear predictor
beta @ "X" # matrix-vector regression
beta + 1.0 # additive constant
1.0 + beta * "x" # constant plus expression
Direct use as the likelihood expression is also valid:
mu_global = builder.normal_prior("mu_global", mu=0.0, sigma=5.0)
sigma_group = builder.half_normal_prior("sigma_group", sigma=2.0)
mu_group = builder.normal_prior("mu_group", mu=mu_global, sigma=sigma_group)
builder.normal_likelihood("obs", mu_expr=mu_group, sigma=1.0, observed_key="y")
That scalar hierarchical pattern compiles to the non-centered form described under
hierarchical priors: the sampled
coordinate is a standard normal raw, and the value reported under the declared name is
mu + sigma * raw. Vector priors are not rewritten this way, because
vector_normal_prior takes constant hyperparameters; write a pooled vector block
explicitly as sigma * z[key].
Exceptions
All three rustmc exception classes subclass ValueError, so except ValueError
catches any of them.
rustmc.InferenceError: a Bayesian model refused its priors, configuration or data, or failed numerically. This covers every forecasting model (local level, seasonal, trend, AR, hierarchical mean, hurdle, regression, structural fitting, dynamic GLM and runoff), their priors, theirfit,forecastandfit_batchcells, and the accessors of the fits and forecasts they return.rustmc.StateSpaceError: the fixed-parameterLinearGaussianStateSpacelayer and structural model specifications (VarianceParameter,StructuralComponent,StructuralModeland its JSON).rustmc.ParameterError: an invalid parameter or expression inModelBuilder, including mixing references from two builders.- Plain
ValueError: argument checks every model shares, such as array conversion, interval levels, quantile probabilities, batch options andfourier_design.
Forecasting models accept any real numeric array-like for observations, exog and
priors: float or integer NumPy arrays in any memory layout, or lists. They follow the
same exact-conversion rule as ModelBuilder data above, so boolean, complex, string
and object arrays, masked entries, values float64 would round, ragged lists and the
wrong number of dimensions raise a ValueError naming the argument.
Result types
Fitting and forecasting calls return named types, and each guide describes the members
of the types it returns. FitResult, BatchResult, BatchFit,
StructuralFit/StructuralForecast, RunoffFit,
ForecastBatchFit/ForecastBatchForecast, DynamicGLMForecast,
KalmanFilterResult/KalmanSmootherResult, and one fit type plus one forecast type
per specialized model come from those calls and are not constructed directly. The
forecast type is not reliably named after the fit type:
BayesianLocalLevelFit.forecast() returns BayesianForecastResult,
BayesianLocalLinearTrendFit.forecast() returns BayesianTrendForecast,
BayesianSeasonalLocalLevelFit.forecast() returns BayesianSeasonalForecast, and
BayesianHierarchicalMeanFit.forecast() returns BayesianHierarchicalForecast. Others
do follow the pattern — BayesianARFit → BayesianARForecast,
BayesianHurdleLogNormalFit → BayesianHurdleLogNormalForecast, and
BayesianRegressionFit → BayesianRegressionForecast — so the name cannot be guessed
either way. Check the fit's own page. ForecastDraws, NamedDesign, ScenarioForecast,
BacktestResult and BacktestFold are ordinary dataclasses you may also construct
yourself, which is how you score draws that rustmc did not produce.
Not everything returns a wrapper. fit.predict(), fit.deterministics(),
fit.get_samples(), fit.get_samples_2d(), fit.log_likelihood() and
fit.posterior_predictive() return plain dicts of NumPy arrays, and the evaluation
helpers return NumPy arrays or dicts of them.