15
15
def test_autoregressive_model (order , rng ):
16
16
ar = st .AutoregressiveComponent (order = order ).build (verbose = False )
17
17
18
- # Check coords
19
18
_assert_basic_coords_correct (ar )
20
19
21
20
lags = np .arange (len (order ) if isinstance (order , list ) else order , dtype = "int" ) + 1
@@ -25,34 +24,34 @@ def test_autoregressive_model(order, rng):
25
24
26
25
27
26
def test_autoregressive_multiple_observed_build (rng ):
28
- ar = st .AutoregressiveComponent (order = 3 , observed_state_names = ["data_1" , "data_2" ])
27
+ ar = st .AutoregressiveComponent (order = 3 , name = "ar" , observed_state_names = ["data_1" , "data_2" ])
29
28
mod = ar .build (verbose = False )
30
29
31
30
assert mod .k_endog == 2
32
31
assert mod .k_states == 6
33
32
assert mod .k_posdef == 2
34
33
35
34
assert mod .state_names == [
36
- "L1 [data_1]" ,
37
- "L2 [data_1]" ,
38
- "L3 [data_1]" ,
39
- "L1 [data_2]" ,
40
- "L2 [data_2]" ,
41
- "L3 [data_2]" ,
35
+ "L1_ar [data_1]" ,
36
+ "L2_ar [data_1]" ,
37
+ "L3_ar [data_1]" ,
38
+ "L1_ar [data_2]" ,
39
+ "L2_ar [data_2]" ,
40
+ "L3_ar [data_2]" ,
42
41
]
43
42
44
- assert mod .shock_names == ["auto_regressive [data_1]" , "auto_regressive [data_2]" ]
43
+ assert mod .shock_names == ["ar [data_1]" , "ar [data_2]" ]
45
44
46
45
params = {
47
- "params_auto_regressive " : np .full (
46
+ "params_ar " : np .full (
48
47
(
49
48
2 ,
50
49
sum (ar .order ),
51
50
),
52
51
0.5 ,
53
52
dtype = config .floatX ,
54
53
),
55
- "sigma_auto_regressive " : np .array ([0.05 , 0.12 ]),
54
+ "sigma_ar " : np .array ([0.05 , 0.12 ]),
56
55
}
57
56
_ , _ , _ , _ , T , Z , R , _ , Q = mod ._unpack_statespace_with_placeholders ()
58
57
input_vars = explicit_graph_inputs ([T , Z , R , Q ])
@@ -89,6 +88,33 @@ def test_autoregressive_multiple_observed_build(rng):
89
88
np .testing .assert_allclose (Q , np .diag ([0.05 ** 2 , 0.12 ** 2 ]))
90
89
91
90
91
+ def test_autoregressive_multiple_observed_shared ():
92
+ ar = st .AutoregressiveComponent (
93
+ order = 1 ,
94
+ name = "latent" ,
95
+ observed_state_names = ["data_1" , "data_2" , "data_3" ],
96
+ share_states = True ,
97
+ )
98
+ mod = ar .build (verbose = False )
99
+
100
+ assert mod .k_endog == 3
101
+ assert mod .k_states == 1
102
+ assert mod .k_posdef == 1
103
+
104
+ assert mod .state_names == ["L1_latent[shared]" ]
105
+ assert mod .shock_names == ["latent[shared]" ]
106
+ assert mod .coords ["lag_latent" ] == [1 ]
107
+ assert "endog_latent" not in mod .coords
108
+
109
+ outputs = [mod .ssm ["transition" ], mod .ssm ["design" ]]
110
+ params = {"params_latent" : np .array ([0.9 ])}
111
+ T , Z = pytensor .function (list (explicit_graph_inputs (outputs )), outputs )(** params )
112
+
113
+ np .testing .assert_allclose (np .array ([[1.0 ], [1.0 ], [1.0 ]]), Z )
114
+
115
+ np .testing .assert_allclose (np .array ([[0.9 ]]), T )
116
+
117
+
92
118
def test_autoregressive_multiple_observed_data (rng ):
93
119
ar = st .AutoregressiveComponent (order = 1 , observed_state_names = ["data_1" , "data_2" , "data_3" ])
94
120
mod = ar .build (verbose = False )
@@ -112,21 +138,130 @@ def test_add_autoregressive_different_observed():
112
138
113
139
mod = (mod_1 + mod_2 ).build (verbose = False )
114
140
115
- print (mod .coords )
116
-
117
141
assert mod .k_endog == 2
118
142
assert mod .k_states == 7
119
143
assert mod .k_posdef == 2
120
144
assert mod .state_names == [
121
- "L1 [data_1]" ,
122
- "L1 [data_2]" ,
123
- "L2 [data_2]" ,
124
- "L3 [data_2]" ,
125
- "L4 [data_2]" ,
126
- "L5 [data_2]" ,
127
- "L6 [data_2]" ,
145
+ f"L1_ { mod_1 . name } [data_1]" ,
146
+ f"L1_ { mod_2 . name } [data_2]" ,
147
+ f"L2_ { mod_2 . name } [data_2]" ,
148
+ f"L3_ { mod_2 . name } [data_2]" ,
149
+ f"L4_ { mod_2 . name } [data_2]" ,
150
+ f"L5_ { mod_2 . name } [data_2]" ,
151
+ f"L6_ { mod_2 . name } [data_2]" ,
128
152
]
129
153
130
154
assert mod .shock_names == ["ar1[data_1]" , "ar6[data_2]" ]
131
155
assert mod .coords ["lag_ar1" ] == [1 ]
132
156
assert mod .coords ["lag_ar6" ] == [1 , 2 , 3 , 4 , 5 , 6 ]
157
+
158
+
159
+ def test_autoregressive_shared_and_not_shared ():
160
+ shared = st .AutoregressiveComponent (
161
+ order = 3 ,
162
+ name = "shared_ar" ,
163
+ observed_state_names = ["data_1" , "data_2" , "data_3" ],
164
+ share_states = True ,
165
+ )
166
+ individual = st .AutoregressiveComponent (
167
+ order = 3 ,
168
+ name = "individual_ar" ,
169
+ observed_state_names = ["data_1" , "data_2" , "data_3" ],
170
+ share_states = False ,
171
+ )
172
+
173
+ mod = (shared + individual ).build (verbose = False )
174
+
175
+ assert mod .k_endog == 3
176
+ assert mod .k_states == 3 + 3 * 3
177
+ assert mod .k_posdef == 4
178
+
179
+ assert mod .state_names == [
180
+ "L1_shared_ar[shared]" ,
181
+ "L2_shared_ar[shared]" ,
182
+ "L3_shared_ar[shared]" ,
183
+ "L1_individual_ar[data_1]" ,
184
+ "L2_individual_ar[data_1]" ,
185
+ "L3_individual_ar[data_1]" ,
186
+ "L1_individual_ar[data_2]" ,
187
+ "L2_individual_ar[data_2]" ,
188
+ "L3_individual_ar[data_2]" ,
189
+ "L1_individual_ar[data_3]" ,
190
+ "L2_individual_ar[data_3]" ,
191
+ "L3_individual_ar[data_3]" ,
192
+ ]
193
+
194
+ assert mod .shock_names == [
195
+ "shared_ar[shared]" ,
196
+ "individual_ar[data_1]" ,
197
+ "individual_ar[data_2]" ,
198
+ "individual_ar[data_3]" ,
199
+ ]
200
+ assert mod .coords ["lag_shared_ar" ] == [1 , 2 , 3 ]
201
+ assert mod .coords ["lag_individual_ar" ] == [1 , 2 , 3 ]
202
+
203
+ outputs = [mod .ssm ["transition" ], mod .ssm ["design" ], mod .ssm ["selection" ], mod .ssm ["state_cov" ]]
204
+ T , Z , R , Q = pytensor .function (
205
+ list (explicit_graph_inputs (outputs )),
206
+ outputs ,
207
+ )(
208
+ ** {
209
+ "params_shared_ar" : np .array ([0.9 , 0.8 , 0.7 ]),
210
+ "params_individual_ar" : np .full ((3 , 3 ), 0.5 ),
211
+ "sigma_shared_ar" : np .array (0.1 ),
212
+ "sigma_individual_ar" : np .array ([0.05 , 0.12 , 0.22 ]),
213
+ }
214
+ )
215
+
216
+ np .testing .assert_allclose (
217
+ T ,
218
+ np .array (
219
+ [
220
+ [0.9 , 0.8 , 0.7 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ],
221
+ [1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ],
222
+ [0.0 , 1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ],
223
+ [0.0 , 0.0 , 0.0 , 0.5 , 0.5 , 0.5 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ],
224
+ [0.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ],
225
+ [0.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ],
226
+ [0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.5 , 0.5 , 0.5 , 0.0 , 0.0 , 0.0 ],
227
+ [0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ],
228
+ [0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 0.0 , 0.0 ],
229
+ [0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.5 , 0.5 , 0.5 ],
230
+ [0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 ],
231
+ [0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.0 ],
232
+ ]
233
+ ),
234
+ )
235
+
236
+ np .testing .assert_allclose (
237
+ Z ,
238
+ np .array (
239
+ [
240
+ [1.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ],
241
+ [1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ],
242
+ [1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 ],
243
+ ]
244
+ ),
245
+ )
246
+
247
+ np .testing .assert_allclose (
248
+ R ,
249
+ np .array (
250
+ [
251
+ [1.0 , 0.0 , 0.0 , 0.0 ],
252
+ [0.0 , 0.0 , 0.0 , 0.0 ],
253
+ [0.0 , 0.0 , 0.0 , 0.0 ],
254
+ [0.0 , 1.0 , 0.0 , 0.0 ],
255
+ [0.0 , 0.0 , 0.0 , 0.0 ],
256
+ [0.0 , 0.0 , 0.0 , 0.0 ],
257
+ [0.0 , 0.0 , 1.0 , 0.0 ],
258
+ [0.0 , 0.0 , 0.0 , 0.0 ],
259
+ [0.0 , 0.0 , 0.0 , 0.0 ],
260
+ [0.0 , 0.0 , 0.0 , 1.0 ],
261
+ [0.0 , 0.0 , 0.0 , 0.0 ],
262
+ [0.0 , 0.0 , 0.0 , 0.0 ],
263
+ ]
264
+ ),
265
+ )
266
+
267
+ np .testing .assert_allclose (Q , np .diag ([0.1 , 0.05 , 0.12 , 0.22 ]) ** 2 )
0 commit comments