pymc_forecast.markov#

Scan-based state latents are markov_series. There is no advance argument.

Markov (state-space) time-series latents via pytensor.scan.

The scan analogue of innovations(): in-sample steps run in one scan-backed pm.CustomDist under the base name; when forecasting, horizon steps run in a second scan-backed CustomDist named {name}_future whose initial state is the final in-sample value — so under posterior replay the forecast is conditioned through the state, exactly upstream’s “seeded by the final carry” invariant.

This follows PyMC’s documented pattern for time series derived from a generative graph (CustomDist + scan + collect_default_updates), which is also what makes the in-sample latent’s logp derivable for NUTS/ADVI. Two constraints follow from it:

  • every random parameter used by the transition must be passed via params= (PyMC needs them as explicit inputs of the generative graph);

  • the transition returns a distribution for the next step (pm.Normal.dist(...)), not a sample — the wrapper owns the randomness, so the Markov structure cannot be broken by user resampling.

pymc_forecast.markov.markov_series(h, name, init, transition, *, params=(), xs=None, dims=())[source]#

Sample a Markov latent over the full horizon.

Parameters:
  • h (pymc_forecast.model.Horizon) – The horizon of the current model build.

  • name (str) – Base variable name of the in-sample latent; the forecast segment is named f"{name}_future".

  • init (float, array_like or pytensor.tensor.TensorVariable) – Initial state fed to the first transition — a constant or a model variable (e.g. pm.Normal("z0", 0, 1)). Cast to float64 inside the scan.

  • transition (callable) – (z_prev, *params) -> dist (with xs: (z_prev, x_t, *params) -> dist). Must return a .dist() distribution for the next step.

  • params (sequence, default ()) – Every random variable the transition uses (beyond the state), passed as explicit generative-graph inputs. Deterministic constants may be closed over freely.

  • xs (array_like, optional) – Exogenous inputs, purely positional: time on axis 0 (any array-like, or an object with .values such as a DataArray, whose dim names and coords are ignored), cast to float64. Must have at least h.duration rows; extra rows are ignored. None means no inputs.

  • dims (tuple of str, default ()) – Extra (non-time) dims of the per-step state, e.g. ("series",).

Returns:

pytensor.tensor.TensorVariable – The latent over the full horizon, time on axis 0. When h.future == 0 this is the registered model variable name itself; otherwise it is an unnamed concatenation of name and {name}_future.

Raises:

pymc_forecast.exceptions.HorizonError – If forecasting (h.future > 0) without observed data, or if xs has fewer than h.duration rows along axis 0.