|
7 | 7 |
|
8 | 8 |
|
9 | 9 | class RegressionComponent(Component):
|
| 10 | + r""" |
| 11 | + Regression component for exogenous variables in a structural time series model |
| 12 | +
|
| 13 | + Parameters |
| 14 | + ---------- |
| 15 | + k_exog : int | None, default None |
| 16 | + Number of exogenous variables to include in the regression. Must be specified if |
| 17 | + state_names is not provided. |
| 18 | +
|
| 19 | + name : str | None, default "regression" |
| 20 | + A name for this regression component. Used to label dimensions and coordinates. |
| 21 | +
|
| 22 | + state_names : list[str] | None, default None |
| 23 | + List of strings for regression coefficient labels. If provided, must be of length |
| 24 | + k_exog. If None and k_exog is provided, coefficients will be named |
| 25 | + "{name}_1, {name}_2, ...". |
| 26 | +
|
| 27 | + observed_state_names : list[str] | None, default None |
| 28 | + List of strings for observed state labels. If None, defaults to ["data"]. |
| 29 | +
|
| 30 | + innovations : bool, default False |
| 31 | + Whether to include stochastic innovations in the regression coefficients, |
| 32 | + allowing them to vary over time. If True, coefficients follow a random walk. |
| 33 | +
|
| 34 | + Notes |
| 35 | + ----- |
| 36 | + This component implements regression with exogenous variables in a structural time series |
| 37 | + model. The regression component can be expressed as: |
| 38 | +
|
| 39 | + .. math:: |
| 40 | + y_t = \beta_t^T x_t + \epsilon_t |
| 41 | +
|
| 42 | + Where :math:`y_t` is the dependent variable, :math:`x_t` is the vector of exogenous |
| 43 | + variables, :math:`\beta_t` is the vector of regression coefficients, and :math:`\epsilon_t` |
| 44 | + is the error term. |
| 45 | +
|
| 46 | + When ``innovations=False`` (default), the coefficients are constant over time: |
| 47 | + :math:`\beta_t = \beta_0` for all t. |
| 48 | +
|
| 49 | + When ``innovations=True``, the coefficients follow a random walk: |
| 50 | + :math:`\beta_{t+1} = \beta_t + \eta_t`, where :math:`\eta_t \sim N(0, \Sigma_\beta)`. |
| 51 | +
|
| 52 | + The component supports both univariate and multivariate regression. In the multivariate |
| 53 | + case, separate coefficients are estimated for each endogenous variable (i.e time series). |
| 54 | +
|
| 55 | + Examples |
| 56 | + -------- |
| 57 | + Simple regression with constant coefficients: |
| 58 | +
|
| 59 | + .. code:: python |
| 60 | +
|
| 61 | + from pymc_extras.statespace import structural as st |
| 62 | + import pymc as pm |
| 63 | + import pytensor.tensor as pt |
| 64 | +
|
| 65 | + trend = st.LevelTrendComponent(order=1, innovations_order=1) |
| 66 | + regression = st.RegressionComponent(k_exog=2, state_names=['intercept', 'slope']) |
| 67 | + ss_mod = (trend + regression).build() |
| 68 | +
|
| 69 | + with pm.Model(coords=ss_mod.coords) as model: |
| 70 | + # Prior for regression coefficients |
| 71 | + betas = pm.Normal('betas', dims=ss_mod.param_dims['beta_regression']) |
| 72 | +
|
| 73 | + # Prior for trend innovations |
| 74 | + sigma_trend = pm.Exponential('sigma_trend', 1) |
| 75 | +
|
| 76 | + ss_mod.build_statespace_graph(data) |
| 77 | + idata = pm.sample() |
| 78 | +
|
| 79 | + Multivariate regression with time-varying coefficients: |
| 80 | + - There are 2 exogenous variables (price and income effects) |
| 81 | + - There are 2 endogenous variables (sales and revenue) |
| 82 | + - The regression coefficients are allowed to vary over time (`innovations=True`) |
| 83 | +
|
| 84 | + .. code:: python |
| 85 | +
|
| 86 | + regression = st.RegressionComponent( |
| 87 | + k_exog=2, |
| 88 | + state_names=['price_effect', 'income_effect'], |
| 89 | + observed_state_names=['sales', 'revenue'], |
| 90 | + innovations=True |
| 91 | + ) |
| 92 | +
|
| 93 | + with pm.Model(coords=ss_mod.coords) as model: |
| 94 | + betas = pm.Normal('betas', dims=ss_mod.param_dims['beta_regression']) |
| 95 | +
|
| 96 | + # Innovation variance for time-varying coefficients |
| 97 | + sigma_beta = pm.Exponential('sigma_beta', 1, dims=ss_mod.param_dims['sigma_beta_regression']) |
| 98 | +
|
| 99 | + ss_mod.build_statespace_graph(data) |
| 100 | + idata = pm.sample() |
| 101 | + """ |
| 102 | + |
10 | 103 | def __init__(
|
11 | 104 | self,
|
12 | 105 | k_exog: int | None = None,
|
|
0 commit comments