Skip to main content
Geographical and Temporal Hierarchical Forecasting on Australian Tourism Data
In many applications, a set of time series is hierarchically organized. Examples include the presence of geographic levels, products, or categories that define different types of aggregations. In such scenarios, forecasters are often required to provide predictions for all disaggregate and aggregate series. A natural desire is for those predictions to be “coherent”, that is, for the bottom series to add up precisely to the forecasts of the aggregated series. In this notebook we present an example on how to use HierarchicalForecast to produce coherent forecasts between both geographical levels and temporal levels. We will use the classic Australian Domestic Tourism (Tourism) dataset, which contains monthly time series of the number of visitors to each state of Australia. We will first load the Tourism data and produce base forecasts using an AutoETS model from StatsForecast. Then, we reconciliate the forecasts with several reconciliation algorithms from HierarchicalForecast according to the cross-sectional geographical hierarchies. Finally, we reconciliate the forecasts in the temporal dimension according to a temporal hierarchy. You can run these experiments using CPU or GPU with Google Colab. Open In Colab

1. Load and Process Data

In this example we will use the Tourism dataset from the Forecasting: Principles and Practice book. The dataset only contains the time series at the lowest level, so we need to create the time series for all hierarchies.

2. Cross-sectional reconciliation

2a. Aggregating the dataset according to cross-sectional hierarchy

The dataset can be grouped in the following non-strictly hierarchical structure.
Using the aggregate function from HierarchicalForecast we can get the full set of time series.

2b. Split Train/Test sets

We use the final two years (8 quarters) as test set. Consequently, our forecast horizon=8.

2c. Computing base forecasts

The following cell computes the base forecasts for each time series in Y_df using the AutoETS model. Observe that Y_hat_df contains the forecasts but they are not coherent.

2d. Reconcile forecasts

The following cell makes the previous forecasts coherent using the HierarchicalReconciliation class. Since the hierarchy structure is not strict, we can’t use methods such as TopDown or MiddleOut. In this example we use BottomUp and MinTrace.
The dataframe Y_rec_df contains the reconciled forecasts.

3. Temporal reconciliation

Next, we aim to reconcile our forecasts also in the temporal domain.

3a. Aggregating the dataset according to temporal hierarchy

We first define the temporal aggregation spec. The spec is a dictionary in which the keys are the name of the aggregation and the value is the amount of bottom-level timesteps that should be aggregated in that aggregation. For example, year consists of 12 months, so we define a key, value pair "yearly":12. We can do something similar for other aggregations that we are interested in. In this example, we choose a temporal aggregation of year, semiannual and quarter. The bottom level timesteps have a quarterly frequency.
We next compute the temporally aggregated train- and test sets using the aggregate_temporal function. Note that we have different aggregation matrices S for the train- and test set, as the test set contains temporal hierarchies that are not included in the train set.
If you don’t have a test set available, as is usually the case when you’re making forecasts, it is necessary to create a future dataframe that holds the correct bottom-level unique_ids and timestamps so that they can be temporally aggregated. We can use the make_future_dataframe helper function for that.
Y_test_df_te_new can be then used in aggregate_temporal to construct the temporally aggregated structures:
And we can verify that we have the same temporally aggregated test set, except that Y_test_df_te_new doesn’t contain the ground truth values y.

3b. Computing base forecasts

Now, we need to compute base forecasts for each temporal aggregation. The following cell computes the base forecasts for each temporal aggregation in Y_train_df_te using the AutoETS model. Observe that Y_hat_df_te contains the forecasts but they are not coherent. Note also that both frequency and horizon are different for each temporal aggregation. In this example, the lowest level has a quarterly frequency, and a horizon of 8 (constituting 2 years). The year aggregation thus has a yearly frequency with a horizon of 2. It is of course possible to choose a different model for each level in the temporal aggregation - you can be as creative as you like!

3c. Reconcile forecasts

We can again use the HierarchicalReconciliation class to reconcile the forecasts. In this example we use BottomUp and MinTrace. Note that we have to set temporal=True in the reconcile function. Note that temporal reconcilation currently isn’t supported for insample reconciliation methods, such as MinTrace(method='mint_shrink').

4. Evaluation

The HierarchicalForecast package includes the evaluate function to evaluate the different hierarchies.

4a. Cross-sectional evaluation

We first evaluate the forecasts across all cross-sectional aggregations.
As can be seen MinTrace(ols) seems to be the best forecasting method across each cross-sectional aggregation.

4b. Temporal evaluation

We then evaluate the temporally aggregated forecasts across all temporal aggregations.
Again, MinTrace(ols) is the best overall method, scoring the lowest rmse on the quarter aggregated forecasts, and being slightly worse than the Base forecasts on the year aggregated forecasts.

4c. Cross-temporal evaluation

Finally, we evaluate cross-temporally. To do so, we first need to obtain the combination of cross-sectional and temporal hierarchies, for which we can use the get_cross_temporal_tags helper function.
As we can see, we now have a tag Country//year that contains Australia//year-1 and Australia//year-2, indicating the cross-sectional hierarchy Australia at the temporal hierarchies 2016 and 2017.
We now have our dataset and cross-temporal tags ready for evaluation. We define a set of eval_tags, and now we split each cross-sectional aggregation also by each temporal aggregation. Note that we skip the semiannual temporal aggregation in the below overview.
We find that the best method is the cross-temporally reconciled method AutoETS/MinTrace_method-ols, which achieves overall lowest RMSE.

References