{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Hierarchical Forecast"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"This notebook offers a step by step guide to create a hierarchical forecasting pipeline.\n",
"\n",
"In the pipeline we will use `NeuralForecast` and `HINT` class, to create fit, predict and reconcile forecasts.\n",
"\n",
"We will use the TourismL dataset that summarizes large Australian national visitor survey.\n",
"\n",
"Outline \n",
"1. Installing packages \n",
"2. Load hierarchical dataset \n",
"3. Fit and Predict HINT \n",
"4. Forecast Evaluation"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"You can run these experiments using GPU with Google Colab.\n",
"\n",
""
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Installing packages"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%capture\n",
"!pip install datasetsforecast hierarchicalforecast\n",
"!pip install git+https://github.com/Nixtla/neuralforecast.git"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Load hierarchical dataset"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"This detailed Australian Tourism Dataset comes from the National Visitor Survey, managed by the Tourism Research Australia, it is composed of 555 monthly series from 1998 to 2016, it is organized geographically, and purpose of travel. The natural geographical hierarchy comprises seven states, divided further in 27 zones and 76 regions. The purpose of travel categories are holiday, visiting friends and relatives (VFR), business and other. The MinT (Wickramasuriya et al., 2019), among other hierarchical forecasting studies has used the dataset it in the past. The dataset can be accessed in the [MinT reconciliation webpage](https://robjhyndman.com/publications/mint/), although other sources are available.\n",
"\n",
"| Geographical Division | Number of series per division | Number of series per purpose | Total |\n",
"| --- | --- | --- | --- |\n",
"| Australia | 1 | 4 | 5 |\n",
"| States | 7 | 28 | 35 |\n",
"| Zones | 27 | 108 | 135 |\n",
"| Regions | 76 | 304 | 380 |\n",
"| Total | 111 | 444 | 555 |\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"\n",
"from datasetsforecast.hierarchical import HierarchicalData\n",
"from hierarchicalforecast.utils import aggregate, HierarchicalPlot\n",
"\n",
"from neuralforecast.utils import augment_calendar_df\n",
"\n",
"def sort_df_hier(Y_df, S):\n",
" # NeuralForecast core, sorts unique_id lexicographically\n",
" # by default, this method matches S_df and Y_hat_df hierarchical order.\n",
" Y_df.unique_id = Y_df.unique_id.astype('category')\n",
" Y_df.unique_id = Y_df.unique_id.cat.set_categories(S.index)\n",
" Y_df = Y_df.sort_values(by=['unique_id', 'ds'])\n",
" return Y_df\n",
"\n",
"# Load hierarchical dataset\n",
"Y_df, S_df, tags = HierarchicalData.load('./data', 'TourismLarge')\n",
"Y_df['ds'] = pd.to_datetime(Y_df['ds'])\n",
"Y_df = sort_df_hier(Y_df, S_df)\n",
"\n",
"Y_df, _ = augment_calendar_df(df=Y_df, freq='M')"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Mathematically a hierarchical multivariate time series can be denoted by the vector $\\mathbf{y}_{[a,b],t}$ defined by the following aggregation constraint:\n",
"\n",
"$$\n",
"\\mathbf{y}_{[a,b],t} = \\mathbf{S}_{[a,b][b]} \\mathbf{y}_{[b],t} \\quad \\Leftrightarrow \\quad \n",
"\\begin{bmatrix}\\mathbf{y}_{[a],t}\n",
"\\\\ %\\hline\n",
"\\mathbf{y}_{[b],t}\\end{bmatrix} \n",
"= \\begin{bmatrix}\n",
"\\mathbf{A}_{[a][b]}\\\\ %\\hline\n",
"\\mathbf{I}_{[b][b]}\n",
"\\end{bmatrix}\n",
"\\mathbf{y}_{[b],t}\n",
"$$\n",
"\n",
"where $\\mathbf{y}_{[a],t}$ are the aggregate series, $\\mathbf{y}_{[b],t}$ are the bottom level series and $\\mathbf{S}_{[a,b][b]}$ are the hierarchical aggregation constraints."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
"