pymc_forecast.statespace#
Interop with pymc_extras.statespace models.
Statespace structural models (level/trend, seasonality, cycles, AR, regression;
SARIMAX; VARMAX) cover the linear-Gaussian slice of what
markov_series() is used for — with
Kalman-filter marginalization instead of sampling per-step latents, which
usually gives better posteriors and faster sampling.
Their lifecycle differs from this package’s model functions: components are
combined and .build() into a PyMCStateSpace, parameter priors are
declared inside a pm.Model carrying the statespace coords, and
build_statespace_graph inserts the Kalman-filter likelihood. The
StatespaceForecaster adapter maps that lifecycle onto the package’s
fit + forecast(horizon) protocol, so a statespace model drops into
backtest() and the metrics layer wherever a
hand-written forecasting model is accepted.
Coords stay this package’s responsibility: the statespace internals only ever
see positional (integer-indexed) data, and real time coordinates are stamped
onto the outputs — "time_future" on forecasts, "time" on in-sample
predictions — exactly like the core forecasters.
- class pymc_forecast.statespace.StatespaceForecaster(model_fn, data=None, covariates=None, *, draws=1000, tune=1000, chains=2, nuts_sampler='pymc', random_seed=None, progressbar=None, sample_kwargs=None, build_kwargs=None, forecast_kwargs=None)[source]#
Bases:
HMCForecasterFit and forecast a pymc-extras statespace model behind the forecaster protocol.
An
HMCForecasterwhose training model is built through the statespace lifecycle instead ofbuild_model(): fit on construction with NUTS,draw_posterior,forecast()returning a labeledpredictionsgroup,predict_in_sample()— so it drops intobacktest()viaforecaster_cls=StatespaceForecaster.pymc-extras is imported on construction, so constructing this class is the opt-in that requires it.
- Parameters:
model_fn (
StatespaceModel) – The model definition, aStatespaceModel(or any object with itsstatespace/priorsmethods).data (
xarray.DataArray,pandas.Series,pandas.DataFrameorarray_like, optional) – Observed training series (univariate or 2-D with a named series dim), normalized withas_dataarray(), orNoneto construct unfitted and callfitlater.covariates (
xarray.DataArray,pandas.Series,pandas.DataFrameorarray_like, optional) – Covariates on the same"time"coordinate asdata, covering (at least) the training window, passed through to the model definition; rows past the training window are dropped during fitting.Nonefor models without covariates.draws (
int, default1000) – Number of posterior draws per chain.tune (
int, default1000) – Number of tuning steps per chain.chains (
int, default2) – Number of chains.nuts_sampler (
{"pymc", "nutpie", "numpyro", "blackjax"}, default"pymc") – NUTS backend, forwarded topm.sample.random_seed (
intornumpy.random.Generator, optional) – Seed for the fit, forwarded topm.sample; also the default seed for laterfitcalls.progressbar (
bool, optional) – Show the sampling progress bar;Nonemeans off. May instead be given insample_kwargs, but not both.sample_kwargs (
mapping, optional) – Extra keyword arguments forpm.sample.progressbaris accepted here for compatibility, but the direct argument is preferred (passing both raises).build_kwargs (
mapping, optional) – Extra keyword arguments forwarded tobuild_statespace_graph; which keywords exist depends on the installed pymc-extras release.forecast_kwargs (
mapping, optional) – Extra keyword arguments forwarded toPyMCStateSpace.forecast(not applied topredict_in_sample()).start,periods,end,scenario,random_seed,verboseandprogressbarare managed by the adapter and cannot be given here.
- model_fn#
The model definition passed to the constructor.
- Type:
- model#
The
pm.Modelholding priors and the Kalman-filter likelihood;Nonebefore the first fit.- Type:
pymc.ModelorNone
- idata#
The full MCMC result, as returned by
pm.sample(set by fitting).- Type:
xarray.DataTreeorarviz.InferenceData
- Raises:
pymc_forecast.exceptions.OptionalDependencyError – If
pymc_extras.statespacecannot be imported.ValueError – If
forecast_kwargscontains an adapter-managed key,progressbaris given both directly and insample_kwargs, orcovariatesis given withoutdata.pymc_forecast.exceptions.AlignmentError – If (when fitting)
dataorcovariatescannot be normalized, the data has more than two dims, the covariates do not align with it, orss_mod.k_endogdoes not match the data width.
- forecast(covariates=None, num_samples=None, *, horizon=None, future_index=None, future_covariates=None, posterior=None, var_names=None, random_seed=None, progressbar=False)[source]#
Sample forecasts beyond the training window.
The horizon is supplied at forecast time, in one of four mutually exclusive ways: pass
covariatesspanning the training window plus the forecast steps,future_covariatescovering only the forecast steps, or — for a model without exogenous inputs — passhorizon=Nto forecastNsteps past the training data (its time coord is extended at the inferred spacing) orfuture_index=to forecast over an arbitrary later time index (strictly increasing values lying after the training window; the horizon length is derived from it). Forecast steps are always iterated consecutively from the end of training and labeled with the supplied coordinates.The forecast draws the terminal state from its smoothed posterior and iterates the statespace forward — the Kalman analogue of the core mechanism of seeding
*_futurelatents from the in-sample state. For a model with ast.Regressioncomponent, the future slice of the covariates is fed through as the scenario.- Parameters:
covariates (
xarray.DataArray,pandas.Series,pandas.DataFrameorarray_like, optional) – Covariates spanning training window + forecast horizon (time coords must extend the training data’s), normalized withas_dataarray(); the steps past the training window define the horizon. Non-time dimensions and coordinate names/order must match the training covariates.Nonewhen the horizon comes from another argument.num_samples (
int, optional) – Number of posterior draws (and forecast samples) to sample whenposterioris not given;Nonemeans 100. Mutually exclusive withposterior.horizon (
int, optional) – Number of steps to forecast past the training data (must be at least 1). Rejected for models with exogenous inputs.future_index (
array_like, optional) – Time coordinate values of the forecast horizon, supplied at forecast time (rejected for models with exogenous inputs) — the covariate-free half of the predict-time horizon capability;future_covariatesis the with-exogenous half.future_covariates (
xarray.DataArray,pandas.DataFrameorarray_like, optional) – Covariates (any inputas_dataarray()accepts, including apandas.Series) covering only the forecast horizon, with a time index lying after the training window; fed through as the forecast scenario. Structure (dims, covariate names and order) must match the training covariates.posterior (
xarray.Dataset,xarray.DataTreeorarviz.InferenceData, optional) – A fixed posterior to condition on: a posterior Dataset or any object with aposteriorgroup (posterior_dataset()), typically fromdraw_posterior; used as given, not thinned. Passing the same posterior topredict_in_sampleandforecastmakes the calls draw-coherent. Mutually exclusive withnum_samples.var_names (
sequenceofstr, optional) – Subset of{"forecast", "forecast_latent"}to keep (a bare string is not accepted as a single name);Nonekeeps both.random_seed (
intornumpy.random.Generator, optional) – Seeds both the posterior draws (whenposterioris not given) andPyMCStateSpace.forecast.progressbar (
bool, defaultFalse) – Show the sampling progress bar (forwarded toPyMCStateSpace.forecast).
- Returns:
xarray.DataTree– Always a DataTree, with apredictionsgroup holding"forecast"(dims(chain, draw, time_future), plus the series dim for 2-D data) and the latent state trajectories as"forecast_latent"(dims(chain, draw, time_future, state)).- Raises:
pymc_forecast.exceptions.NotFittedError – If the forecaster has not been fitted.
ValueError – If not exactly one of
covariates,horizon,future_indexandfuture_covariatesis given, if bothposteriorandnum_samplesare given, or if a posterior draw count is not positive.pymc_forecast.exceptions.AlignmentError – If the horizon arguments or covariates are invalid or misaligned (see
extend_time_index,concat_time_index,concat_covariates), or ifhorizon/future_indexis used with a model that has an exogenous input.pymc_forecast.exceptions.HorizonError – If the resulting horizon is empty (e.g.
horizon=0).NotImplementedError – If the model has more than one exogenous input.
KeyError – If
var_namescontains an unknown name.TypeError – If
posteriorhas noposteriorgroup.
- predict_in_sample(num_samples=None, *, posterior=None, random_seed=None, progressbar=False)[source]#
Sample the in-sample predictive of the observed series.
Draws observations from the smoothed state posterior (conditioned on the full training window) — the statespace analogue of replaying in-sample latents and resampling the observation noise.
- Parameters:
num_samples (
int, optional) – Number of posterior draws to sample whenposterioris not given;Nonemeans 100. Mutually exclusive withposterior.posterior (
xarray.Dataset,xarray.DataTreeorarviz.InferenceData, optional) – A fixed posterior to condition on: a posterior Dataset or any object with aposteriorgroup (posterior_dataset()); used as given, not thinned (seeforecast()for the draw-coherence semantics). Mutually exclusive withnum_samples.random_seed (
intornumpy.random.Generator, optional) – Seeds both the posterior draws (whenposterioris not given) and the conditional posterior sampling.progressbar (
bool, defaultFalse) – Show the sampling progress bar.
- Returns:
xarray.DataTree– Always a DataTree, with aposterior_predictivegroup holding only"obs"(dims(chain, draw, time), plus the series dim for 2-D data).- Raises:
pymc_forecast.exceptions.NotFittedError – If the forecaster has not been fitted.
ValueError – If both
posteriorandnum_samplesare given, or a posterior draw count is not positive.TypeError – If
posteriorhas noposteriorgroup.
- class pymc_forecast.statespace.StatespaceModel(priors=None)[source]#
Bases:
PriorConfig,ABCA pymc-extras statespace model definition for
StatespaceForecaster.The statespace lifecycle is two-phase — the component graph must exist before its coords can be registered on the
pm.Modelthat holds the parameter priors — so the definition is split accordingly. Example:import pymc as pm import pytensor.tensor as pt from pymc_extras.statespace import structural as st class LocalLinearTrend(StatespaceModel): def statespace(self, data, covariates): trend = st.LevelTrend(order=2, innovations_order=[0, 1]) return (trend + st.MeasurementError()).build(verbose=False) def priors(self, ss_mod, data, covariates): P0_diag = pm.Gamma("P0_diag", alpha=2, beta=5, dims="state") pm.Deterministic("P0", pt.diag(P0_diag), dims=("state", "state_aux")) pm.Normal("initial_level_trend", float(data[0]), 1, dims="state_level_trend") pm.Gamma("sigma_level_trend", alpha=2, beta=10, dims="shock_level_trend") pm.Gamma("sigma_MeasurementError", alpha=2, beta=10)
Both phases receive the normalized training
dataandcovariatesas labeled DataArrays —statespaceso the component graph can be sized from them (series count, regression features),priorsso priors can be informed by them (as withinitial_level_trendabove). For a fit without covariates,covariatesis a zero-width DataArray with dims("time", "covariate"), neverNone. A model with ast.Regressioncomponent registers its feature matrix withpm.Data(name, ...)insidepriors, wherenameis the entry inss_mod.data_names; at forecast time the adapter feeds the future covariate values through as the scenario.Priors are user-injectable here too (see
PriorConfig): declare named defaults indefault_priors, create them insidepriors()withself.create_prior(name), and let callers override any subset withpriors=when constructing the model object.- Parameters:
priors (
mapping, optional) – Prior specs by name, merged overdefault_priors(seePriorConfig);Nonekeeps the defaults.
- abstractmethod statespace(data, covariates)[source]#
Build and return the
PyMCStateSpace(component sum +.build()).- Parameters:
data (
xarray.DataArray) – Normalized training data,"time"first.covariates (
xarray.DataArray) – Training-window covariates (zero-width for a covariate-free fit).
- Returns:
object– A builtpymc_extrasPyMCStateSpacewhosek_endogequals the data width (1 for 1-D data, else the size of the non-time dim).
- abstractmethod priors(ss_mod, data, covariates)[source]#
Declare the parameter priors listed by
ss_mod.param_info.Called inside a
pm.Modelwhose coords aress_mod.coords; the adapter callsbuild_statespace_graphafterwards.- Parameters:
ss_mod (
object) – ThePyMCStateSpacereturned bystatespace().data (
xarray.DataArray) – Normalized training data,"time"first.covariates (
xarray.DataArray) – Training-window covariates (zero-width for a covariate-free fit).