PyMCStateSpace#
- class pymc_extras.statespace.core.PyMCStateSpace(k_endog: int, k_states: int, k_posdef: int, filter_type: str = 'standard', verbose: bool = True, measurement_error: bool = False, mode: str | None = None)[source]#
Base class for Linear Gaussian Statespace models in PyMC.
Holds a
PytensorRepresentationandKalmanFilter, and provides a mapping between a PyMC model and the statespace model.- Parameters:
k_endog (int) – The number of endogenous variables (observed time series).
k_states (int) – The number of state variables.
k_posdef (int) – The number of shocks in the model
filter_type (str, optional) – The type of Kalman filter to use. Valid options are “standard”, “univariate”, “single”, “cholesky”, and “steady_state”. For more information, see the docs for each filter. Default is “standard”.
verbose (bool, optional) – If True, displays information about the initialized model. Defaults to True.
measurement_error (bool, optional) – If true, the model contains measurement error. Needed by post-estimation sampling methods to decide how to compute the observation errors. If False, these errors are deterministically zero; if True, they are sampled from a multivariate normal.
mode (str or Mode, optional) –
Pytensor compile mode, used in auxiliary sampling methods such as
sample_conditional_posteriorandforecast. The mode does not effect calls topm.sample.Regardless of whether a mode is specified, it can always be overwritten via the
compile_kwargsargument to all sampling methods.
Notes
Based on the statsmodels statespace implementation statsmodels/statsmodels, described in [1].
All statespace models inherit from this base class, which is responsible for providing an interface between a PyMC model and a PytensorRepresentation of a linear statespace model. This is done via the
updatemethod, which takes as input a vector of PyMC random variables and assigns them to their correct positions inside the underlyingPytensorRepresentation. Construction of the parameter vector, calledtheta, is done automatically, but depend on the names provided in theparam_namesproperty.To implement a new statespace model, one needs to:
Overload the
param_namesproperty to return a list of parameter names.Overload the
updatemethod to put these parameters into their respective statespace matrices
In addition, a number of additional properties can be overloaded to provide users with additional resources when writing their PyMC models. For details, see the attributes section of the docs for this class.
Finally, this class holds post-estimation methods common to all statespace models, which do not need to be overloaded when writing a custom statespace model.
Examples
The local level model is a simple statespace model. It is a Gaussian random walk with a drift term that itself also follows a Gaussian random walk, as described by the following two equations:
\[\begin{split}\begin{align} y_{t} &= y_{t-1} + x_t + \nu_t \tag{1} \\ x_{t} &= x_{t-1} + \eta_t \tag{2} \end{align}\end{split}\]Where \(y_t\) is the observed data, and \(x_t\) is an unobserved trend term. The model has two unknown parameters, the variances on the two innovations, \(sigma_\nu\) and \(sigma_\eta\). Take the hidden state vector to be \(\begin{bmatrix} y_t & x_t \end{bmatrix}^T\) and the shock vector \(\varepsilon_t = \begin{bmatrix} \nu_t & \eta_t \end{bmatrix}^T\). Then this model can be cast into state-space form with the following matrices:
\[\begin{split}\begin{align} T &= \begin{bmatrix}1 & 1 \\ 0 & 1 \end{bmatrix} & R &= \begin{bmatrix}1 & 0 \\ 0 & 1 \end{bmatrix} & Q &= \begin{bmatrix} \sigma_\nu & 0 \\ 0 & \sigma_\eta \end{bmatrix} & Z &= \begin{bmatrix} 1 & 0 \end{bmatrix} \end{align}\end{split}\]With the remaining statespace matrices as zero matrices of the appropriate sizes. The model has two states, two shocks, and one observed state. Knowing all this, a very simple local level model can be implemented as follows:
from pymc_extras.statespace.core import PyMCStateSpace import numpy as np class LocalLevel(PyMCStateSpace): def __init__(): # Initialize the superclass. This creates the PytensorRepresentation and the Kalman Filter super().__init__(k_endog=1, k_states=2, k_posdef=2) # Declare the non-zero, non-parameterized matrices self.ssm['transition', :, :] = np.array([[1.0, 1.0], [0.0, 1.0]]) self.ssm['selection', :, :] = np.eye(2) self.ssm['design', :, :] = np.array([[1.0, 0.0]]) @property def param_names(self): return ['x0', 'P0', 'sigma_nu', 'sigma_eta'] def make_symbolic_graph(self): # Declare symbolic variables that represent parameters of the model # In this case, we have 4: x0 (initial state), P0 (initial state covariance), sigma_nu, and sigma_eta x0 = self.make_and_register_variable('x0', shape=(2,)) P0 = self.make_and_register_variable('P0', shape=(2,2)) sigma_mu = self.make_and_register_variable('sigma_nu') sigma_eta = self.make_and_register_variable('sigma_eta') # Next, use these symbolic variables to build the statespace matrices by assigning each parameter # to its correct location in the correct matrix self.ssm['initial_state', :] = x0 self.ssm['initial_state_cov', :, :] = P0 self.ssm['state_cov', 0, 0] = sigma_nu self.ssm['state_cov', 1, 1] = sigma_eta
After defining priors over the named parameters
P0,x0,sigma_eta, andsigma_nu, we can sample from this model:import pymc as pm ll = LocalLevel() with pm.Model() as mod: x0 = pm.Normal('x0', shape=(2,)) P0_diag = pm.Exponential('P0_diag', 1, shape=(2,)) P0 = pm.Deterministic('P0', pt.diag(P0_diag)) sigma_nu = pm.Exponential('sigma_nu', 1) sigma_eta = pm.Exponential('sigma_eta', 1) ll.build_statespace_graph(data = data) idata = pm.sample()
References
- __init__(k_endog: int, k_states: int, k_posdef: int, filter_type: str = 'standard', verbose: bool = True, measurement_error: bool = False, mode: str | None = None)[source]#
Methods
__init__(k_endog, k_states, k_posdef[, ...])add_default_priors()Add default priors to the active PyMC model context
build_statespace_graph(data[, ...])Given a parameter vector theta, constructs the full computational graph describing the state space model and the associated log probability of the data.
default_coords()forecast(idata[, start, periods, end, ...])Generate forecasts of state space model trajectories into the future.
impulse_response_function(idata[, n_steps, ...])Generate impulse response functions (IRF) from state space model dynamics.
make_and_register_data(name, shape[, dtype])Helper function to create a pytensor symbolic variable and register it in the _name_to_data dictionary
make_and_register_variable(name[, shape, dtype])Helper function to create a pytensor symbolic variable and register it in the _name_to_variable dictionary
make_symbolic_graph()The purpose of the make_symbolic_graph function is to hide tedious parameter allocations from the user.
sample_conditional_posterior(idata[, ...])Sample from the conditional posterior; that is, given parameter draws from the posterior distribution, compute Kalman filtered trajectories.
sample_conditional_prior(idata[, ...])Sample from the conditional prior; that is, given parameter draws from the prior distribution, compute Kalman filtered trajectories.
sample_filter_outputs(idata[, ...])sample_statespace_matrices(idata, matrix_names)Draw samples of requested statespace matrices from provided idata
sample_unconditional_posterior(idata[, ...])Draw unconditional sample trajectories according to state space dynamics, using random samples from the posterior distribution over model parameters.
sample_unconditional_prior(idata[, steps, ...])Draw unconditional sample trajectories according to state space dynamics, using random samples from the prior distribution over model parameters.
set_coords()Provide coordinates to the model.
set_data_info()Provide data_info metadata to the model.
set_parameters()Provides parameter metadata to the model.
set_shocks()Provide shock metadata to the model.
set_states()Provide state metadata to the model.
unpack_statespace()Helper function to quickly obtain all statespace matrices in the standard order.
Attributes
coordsPyMC model coordinates
data_infoInformation about Data variables that need to be declared in the PyMC model block.
data_namesNames of data variables expected by the model.
default_priorsDictionary of parameter names and callable functions to construct default priors for the model
n_timestepsSymbolic placeholder for the number of time steps in the data.
observed_statesA k_endog length list of strings, associated with the model's observed states
param_dimsDictionary of named dimensions for each model parameter
param_infoInformation about parameters needed to declare priors
param_namesNames of model parameters
shock_namesA k_posdef length list of strings, associated with the model's shock processes
state_namesA k_states length list of strings, associated with the model's hidden states