PytensorRepresentation#

class pymc_extras.statespace.core.PytensorRepresentation(k_endog: int, k_states: int, k_posdef: int | None = None, design: ndarray | TensorVariable | None = None, obs_intercept: ndarray | TensorVariable | None = None, obs_cov: ndarray | TensorVariable | None = None, transition: ndarray | TensorVariable | None = None, state_intercept: ndarray | TensorVariable | None = None, selection: ndarray | TensorVariable | None = None, state_cov: ndarray | TensorVariable | None = None, initial_state: ndarray | TensorVariable | None = None, initial_state_cov: ndarray | TensorVariable | None = None)[source]#

Container for the nine state-space matrices of a linear Gaussian model.

Each matrix is stored in its natural shape: core_shape if static, or (time, *core_shape) if time-varying. Optional leading batch dims are accepted and propagate untouched – use vectorize_graph if a downstream consumer needs to lift over them.

Parameters:
  • k_endog (int) – Number of observed states.

  • k_states (int) – Number of hidden states.

  • k_posdef (int, optional) – Rank of the selection matrix \(R\); also the number of stochastic shocks. Default k_states.

  • design (array_like, optional) – Initial value for the design matrix \(Z\).

  • obs_intercept (array_like, optional) – Initial value for \(d\).

  • obs_cov (array_like, optional) – Initial value for the observation noise covariance \(H\).

  • transition (array_like, optional) – Initial value for the transition matrix \(T\).

  • state_intercept (array_like, optional) – Initial value for \(c\).

  • selection (array_like, optional) – Initial value for the selection matrix \(R\).

  • state_cov (array_like, optional) – Initial value for the state innovation covariance \(Q\).

  • initial_state (array_like, optional) – Initial value for \(\bar x_0\).

  • initial_state_cov (array_like, optional) – Initial value for \(P_0\).

Notes

A linear state-space system has

\[\begin{split}\begin{align} x_t &= T_t x_{t-1} + c_t + R_t \varepsilon_t \\ y_t &= Z_t x_t + d_t + \eta_t \\ \varepsilon_t &\sim N(0, Q_t) \\ \eta_t &\sim N(0, H_t) \\ x_0 &\sim N(\bar x_0, P_0) \end{align}\end{split}\]

with hidden state size \(m = k_{\text{states}}\), observed size \(p = k_{\text{endog}}\), and shock rank \(r = k_{\text{posdef}}\). The natural per-matrix shapes are

Matrix

Natural shape

initial_state

(m,)

initial_state_cov | (m, m)

state_intercept

(m,)

obs_intercept

(p,)

transition

(m, m)

design

(p, m)

selection

(m, r)

obs_cov

(p, p)

state_cov

(r, r)

Any matrix may carry a leading dim of length n (the number of observations) to make it time-varying. The model is responsible for declaring which matrices vary over time via declare_time_varying(); downstream consumers (filter, smoother, etc.) read time_varying_names to dispatch.

Warning

The time dim must always be the leftmost axis of a time-varying matrix. The Kalman filter scan iterates over axis 0, pm.Deterministic registration prepends a TIME_DIM coord to the dim list, and forecast slicing reads matrix[n_train:] — all of these assume the time axis sits in front of the core dims. Optional batch dims may sit even further left ((*batch, time, *core)).

Examples

Store and retrieve a transition matrix:

from pymc_extras.statespace.core.representation import PytensorRepresentation
ssm = PytensorRepresentation(k_endog=1, k_states=3, k_posdef=1)
ssm["transition"].type.shape
# (3, 3)

Set individual entries:

ssm["design", 0, 0] = 1.0

Replace an entire matrix, optionally with a time dim:

import numpy as np
ssm["obs_intercept"] = np.arange(10)[:, None]    # 10 timesteps, k_endog=1
ssm["obs_intercept"].type.shape
# (10, 1)

References

__init__(k_endog: int, k_states: int, k_posdef: int | None = None, design: ndarray | TensorVariable | None = None, obs_intercept: ndarray | TensorVariable | None = None, obs_cov: ndarray | TensorVariable | None = None, transition: ndarray | TensorVariable | None = None, state_intercept: ndarray | TensorVariable | None = None, selection: ndarray | TensorVariable | None = None, state_cov: ndarray | TensorVariable | None = None, initial_state: ndarray | TensorVariable | None = None, initial_state_cov: ndarray | TensorVariable | None = None) None[source]#

Methods

__init__(k_endog, k_states[, k_posdef, ...])

copy()

declare_time_varying(*names)

Mark matrices as time-varying.

Attributes

design

initial_state

initial_state_cov

k_endog

k_posdef

k_states

obs_cov

obs_intercept

selection

state_cov

state_intercept

transition

time_varying_names

Names of matrices the model declared as time-varying.