Hello,
How do I set a time-varying observation intercept in a state-space model? According to the comments on this question, it’s supported. I want to do this instead of using the RegressionComponent
because I have a fairly complex deterministic function that I want to subtract off from the endogenous variable. The example below is substantially simplified. Are there any examples of 2d time-varying parameters I can look at?
If I understand this correctly you should it should be possible to add it by specifying a two-dimensional observation intercept with the first-dimension being time. Originally, I was trying to modify with the structural class. I was able to get a time-varying observation covariance to work by adding a third dimension. To simplify the code, I modified the the example notebook AutoRegressiveThree(PyMCStateSpace)
.
class AutoRegressiveThree(PyMCStateSpace):
def __init__(self):
k_states = 3 # size of the state vector x
k_posdef = 1 # number of shocks (size of the state covariance matrix Q)
k_endog = 1 # number of observed states
self.time_dim = 100
super().__init__(k_endog=k_endog, k_states=k_states, k_posdef=k_posdef)
def make_symbolic_graph(self):
x0 = self.make_and_register_variable("x0", shape=(3,))
P0 = self.make_and_register_variable("P0", shape=(3, 3))
ar_params = self.make_and_register_variable("ar_params", shape=(3,))
sigma_x = self.make_and_register_variable("sigma_x", shape=())
beta = self.make_and_register_variable("beta", shape=())
time_trend = self.make_and_register_variable('time_trend', shape=(self.time_dim,))
self.ssm["transition", :, :] = np.eye(3, k=-1)
self.ssm["selection", 0, 0] = 1
self.ssm["design", 0, 0] = 1
self.ssm["initial_state", :] = x0
self.ssm["initial_state_cov", :, :] = P0
self.ssm["transition", 0, :] = ar_params
self.ssm["state_cov", :, :] = sigma_x
self.ssm['obs_cov', :, :] = beta * time_trend
@property
def param_names(self):
return ["x0", "P0", "ar_params", "sigma_x", 'beta', 'time_trend']
The model is here
ar3 = AutoRegressiveThree()
with pm.Model() as mod:
x0 = pm.Deterministic("x0", pt.arange(3, dtype="float"))
P0 = pm.Deterministic("P0", pt.eye(3) * 10.0)
ar_params = pm.Deterministic("ar_params", pt.as_tensor_variable([10.0, 11.0, 12.0]))
sigma_x = pm.Deterministic("sigma_x", pt.as_tensor_variable(13.0, dtype="float64"))
beta = pm.Deterministic("beta", pt.as_tensor_variable(14.0, dtype='float64'))
time_trend = pm.Deterministic("time_trend", pt.arange(100).astype('float64'))
ar3._insert_random_variables()
``
Looking at the shape `ar3.unpack_statespace()[-2].shape.eval()` we get `array([1, 1])` instead of `array([100, 1])` as expected. Any help would be great appreciated.
@