pymc_forecast.priors#

Interop with the pymc-extras Prior API: declarative, user-injectable priors.

innovations and predict accept a pymc-extras pymc_extras.prior.Prior, so priors live as inspectable data on the model object instead of inside lambdas:

from pymc_extras.prior import Prior

drift = innovations(h, "drift", Prior("Normal", mu=0, sigma=0.1))
predict(h, Prior("Normal", sigma=Prior("HalfNormal", sigma=1)), pt.cumsum(drift))

The adapters preserve the package’s replay mechanism: nested hyper-priors (Prior-valued parameters) are materialized once per base name as {base_name}_{param} — e.g. obs_sigma above, or drift_mu if the drift prior had a Prior-valued mu — and shared between the in-sample and *_future segments, so pm.sample_posterior_predictive replays them from the posterior while the future latents are drawn conditional on them. A naive per-segment create_variable would instead give the forecast segment fresh hyper-priors silently drawn from the prior.

On model objects, PriorConfig turns those specifications into a named, overridable configuration: subclasses declare default_priors and callers replace any subset with priors={...} at construction time.

pymc-extras is never imported here — Prior objects are recognized structurally — so the core package keeps that dependency optional.

class pymc_forecast.priors.PriorConfig(priors=None)[source]#

Bases: object

Mixin: named, user-overridable priors on a model object.

Subclasses declare their defaults in default_priors; callers override any subset with the priors= constructor argument, and the model body reads the effective mapping from prior_config — e.g. self.innovations("drift", self.prior_config["drift"]) — or creates a standalone variable with create_prior(). Mixed into ForecastingModel and StatespaceModel.

Parameters:

priors (mapping, optional) – Named overrides merged over default_priors (None keeps the defaults); values are pymc-extras Prior objects, the factory callables the model primitives accept, or — for create_prior() — any name -> RV callable. Values are not validated.

default_priors = {}#

Class-level default priors, overridable per instance via priors=.

property prior_config#

The effective priors, default_priors merged with overrides.

A dict mapping names to specifications. This is the instance’s live mapping, not a copy, so mutating it changes the configuration. Falls back to a fresh copy of the defaults when a subclass __init__ does not call super().__init__().

create_prior(name)[source]#

Create the model variable name from its configured prior.

Must run inside a pm.Model context. The configured specification either exposes create_variable(name) (a pymc-extras Prior, created with its own dims) or is a callable name -> RV, e.g. lambda name: pm.Normal(name, 0, 1).

Parameters:

name (str) – Key of prior_config and name of the created variable.

Returns:

pytensor.tensor.TensorVariable – Whatever the specification creates, normally the registered model random variable.

Raises:
  • KeyError – If no prior is configured for name.

  • TypeError – If the specification neither exposes create_variable nor is callable.

pymc_forecast.priors.is_prior_like(obj)[source]#

Whether obj structurally matches the pymc-extras Prior API.

Parameters:

obj (object) – Any object.

Returns:

bool – True if obj has all of create_variable, create_likelihood_variable, deepcopy, parameters and dims.

pymc_forecast.priors.prior_obs_factory(prior, base_name)[source]#

Adapt a Prior to the pymc_forecast.model.ObsFactory protocol.

The prior’s distribution becomes the likelihood: its location (mu) is the latent predictor handed in by predict(), and nested hyper-priors — e.g. the noise scale — are materialized once under base_name and shared by the observed and forecast segments.

The likelihood is built directly from the materialized parameters rather than through Prior.create_likelihood_variable, which deep-copies the prior and would clone the shared hyper-prior variables out of the model graph.

Parameters:
  • prior (pymc_extras.prior.Prior) – The observation prior; mu must be unset and its distribution must accept a mu keyword.

  • base_name (str) – Prefix for the hyper-prior variables, named {base_name}_{param}.

Returns:

callable – A factory obs_fn(name, latent, dims, observed) that registers and returns the likelihood variable in the active pm.Model. Its first call raises HorizonError if a nested hyper-prior has a "time" or "time_future" dim.

Raises:

ValueError – If prior sets mu (checked immediately).

pymc_forecast.priors.prior_rv_factory(prior, base_name)[source]#

Adapt a Prior to the pymc_forecast.model.RVFactory protocol.

The returned factory creates whatever variable name it is called with (e.g. base_name and {base_name}_future) from prior with the dims it is handed, materializing nested hyper-priors once under base_name on first use. It is stateful, so build a new factory for each model.

Parameters:
  • prior (pymc_extras.prior.Prior) – The prior to adapt; it is deep-copied, not mutated.

  • base_name (str) – Prefix for the hyper-prior variables, named {base_name}_{param}.

Returns:

callable – A factory rv_fn(name, dims) that registers and returns the variable in the active pm.Model. Its first call raises HorizonError if a nested hyper-prior has a "time" or "time_future" dim.