Skip to content

Commit 61e021c

Browse files
committed
updated the way in which we sample filter_outputs using the sample_filter_outputs method
1 parent 05dc393 commit 61e021c

File tree

2 files changed

+293
-122
lines changed

2 files changed

+293
-122
lines changed

examples/case_studies/ssm_hurricane_tracking.ipynb

Lines changed: 254 additions & 107 deletions
Large diffs are not rendered by default.

examples/case_studies/ssm_hurricane_tracking.myst.md

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,6 @@ with pm.Model(coords=n_ssm.coords) as newtonian:
964964
965965
n_ssm.build_statespace_graph(
966966
data=fiona_df.select("longitude", "latitude").to_numpy(),
967-
save_kalman_filter_outputs_in_idata=True,
968967
)
969968
newtonian_idata = pm.sample(
970969
nuts_sampler="nutpie", nuts_sampler_kwargs={"backend": "jax", "gradient_backend": "jax"}
@@ -976,11 +975,21 @@ az.summary(newtonian_idata, var_names="acceleration_innovations", kind="stats")
976975
```
977976

978977
```{code-cell} ipython3
979-
predicted_covs = newtonian_idata.posterior["predicted_covariance"].mean(("chain", "draw"))
978+
n_ssm_filter_outputs = n_ssm.sample_filter_outputs(
979+
newtonian_idata, filter_output_names=["predicted_covariances", "predicted_observed_states"]
980+
)
981+
```
982+
983+
```{code-cell} ipython3
984+
predicted_covs = n_ssm_filter_outputs.posterior_predictive["predicted_covariances"].mean(
985+
("chain", "draw")
986+
)
980987
```
981988

982989
```{code-cell} ipython3
983-
post_mean = newtonian_idata.posterior["predicted_observed_state"].mean(("chain", "draw"))
990+
post_mean = n_ssm_filter_outputs.posterior_predictive["predicted_observed_states"].mean(
991+
("chain", "draw")
992+
)
984993
```
985994

986995
Not bad for a model with only one parameter. We can see that the forecast gets wonky in the middle where the trajectory of the Hurricane changes directions over short time periods. Again, it is important to keep in mind that what we are plotting are the one-step/period ahead forecast. In our case, our periods are six hours apart. Unfortunately, a 6-hour ahead hurricane forecast is not very practical. Let's see what we get when we generate a 4-period (24-hour) ahead forecast.
@@ -1343,10 +1352,7 @@ with pm.Model(coords=exog_ssm.coords) as exogenous:
13431352
13441353
acceleration_innovations = pm.Gamma("acceleration_innovations", 0.1, 5, shape=(1,))
13451354
1346-
exog_ssm.build_statespace_graph(
1347-
data=fiona_df.select("longitude", "latitude").to_numpy(),
1348-
save_kalman_filter_outputs_in_idata=True,
1349-
)
1355+
exog_ssm.build_statespace_graph(data=fiona_df.select("longitude", "latitude").to_numpy())
13501356
exogenous_idata = pm.sample(
13511357
nuts_sampler="nutpie", nuts_sampler_kwargs={"backend": "jax", "gradient_backend": "jax"}
13521358
)
@@ -1367,8 +1373,18 @@ az.plot_forest(
13671373
### Make in-sample forecasts with new exogenous model
13681374

13691375
```{code-cell} ipython3
1370-
predicted_covs = exogenous_idata.posterior["predicted_covariance"].mean(("chain", "draw"))
1371-
post_mean = exogenous_idata.posterior["predicted_observed_state"].mean(("chain", "draw"))
1376+
exog_ssm_filter_outputs = exog_ssm.sample_filter_outputs(
1377+
exogenous_idata, filter_output_names=["predicted_covariances", "predicted_observed_states"]
1378+
)
1379+
```
1380+
1381+
```{code-cell} ipython3
1382+
predicted_covs = exog_ssm_filter_outputs.posterior_predictive["predicted_covariances"].mean(
1383+
("chain", "draw")
1384+
)
1385+
post_mean = exog_ssm_filter_outputs.posterior_predictive["predicted_observed_states"].mean(
1386+
("chain", "draw")
1387+
)
13721388
```
13731389

13741390
Our one-period ahead forecasts seem to be slightly worse than our Newtonian model. You will notice that at the end of the forecast we see that our trajectory is erroneously more north rather than north-east. Since the exogenous variables we added to the model don't carry additional information with respect to the hurricane's trajectory, this results are expected.
@@ -1805,10 +1821,7 @@ with pm.Model(coords=spline_ssm.coords) as spline_model:
18051821
18061822
acceleration_innovations = pm.Gamma("acceleration_innovations", 0.1, 5, shape=(1,))
18071823
1808-
spline_ssm.build_statespace_graph(
1809-
data=fiona_df.select("longitude", "latitude").to_numpy(),
1810-
save_kalman_filter_outputs_in_idata=True,
1811-
)
1824+
spline_ssm.build_statespace_graph(data=fiona_df.select("longitude", "latitude").to_numpy())
18121825
spline_idata = pm.sample(
18131826
nuts_sampler="nutpie", nuts_sampler_kwargs={"backend": "jax", "gradient_backend": "jax"}
18141827
)
@@ -1831,8 +1844,18 @@ az.plot_trace(spline_idata, var_names=["beta_exog"], compact=True, figsize=(20,
18311844
Our one-period ahead forecasts, look better than the ones we generated from the Exogenous covariates model, but worse than the original model that purely follows Newtonian kinematics.
18321845

18331846
```{code-cell} ipython3
1834-
predicted_covs = spline_idata.posterior["predicted_covariance"].mean(("chain", "draw"))
1835-
post_mean = spline_idata.posterior["predicted_observed_state"].mean(("chain", "draw"))
1847+
spline_ssm_filter_outputs = spline_ssm.sample_filter_outputs(
1848+
spline_idata, filter_output_names=["predicted_covariances", "predicted_observed_states"]
1849+
)
1850+
```
1851+
1852+
```{code-cell} ipython3
1853+
predicted_covs = spline_ssm_filter_outputs.posterior_predictive["predicted_covariances"].mean(
1854+
("chain", "draw")
1855+
)
1856+
post_mean = spline_ssm_filter_outputs.posterior_predictive["predicted_observed_states"].mean(
1857+
("chain", "draw")
1858+
)
18361859
```
18371860

18381861
```{code-cell} ipython3
@@ -1941,6 +1964,7 @@ fig.show(width=1000, renderer="png", config={"displayModeBar": False})
19411964
```
19421965

19431966
## Authors
1967+
* Updated by Jonathan Dekermanjian in August, 2025 to use the `sample_filter_outputs` method
19441968
* Authored by Jonathan Dekermanjian in June, 2025
19451969

19461970
+++

0 commit comments

Comments
 (0)