地理和时间聚合(旅游)
在澳大利亚旅游数据上进行地理和时间分层预测
在许多应用中,一组时间序列被组织成层级结构。例子包括地理层级、产品或类别,它们定义了不同类型的聚合。在这种情况下,预测者通常需要为所有分解和聚合的序列提供预测。一个自然的期望是这些预测是“一致的”,也就是说,底层序列的预测值精确地加总等于聚合序列的预测值。
在本笔记本中,我们展示一个如何使用 HierarchicalForecast 来生成地理层级和时间层级之间一致预测的示例。我们将使用经典的澳大利亚国内旅游 (Tourism) 数据集,它包含澳大利亚每个州的月度游客数量时间序列。
我们将首先加载 Tourism 数据,并使用 StatsForecast 中的 AutoETS 模型生成基础预测。然后,我们根据跨部门地理层级,使用 HierarchicalForecast 中的几种协调算法来协调这些预测。最后,我们根据时间层级在时间维度上协调预测。
您可以使用 CPU 或 GPU 在 Google Colab 上运行这些实验。
1. 加载和处理数据
在本例中,我们将使用《预测:原理与实践》书中的 Tourism 数据集。
数据集仅包含最低层级的时间序列,因此我们需要为所有层级创建时间序列。
| 国家 | 区域 | 州 | 目的 | ds | y | |
|---|---|---|---|---|---|---|
| 0 | 澳大利亚 | 阿德莱德 | 南澳大利亚 | 商务 | 1998-01-01 | 135.077690 |
| 1 | 澳大利亚 | 阿德莱德 | 南澳大利亚 | 商务 | 1998-04-01 | 109.987316 |
| 2 | 澳大利亚 | 阿德莱德 | 南澳大利亚 | 商务 | 1998-07-01 | 166.034687 |
| 3 | 澳大利亚 | 阿德莱德 | 南澳大利亚 | 商务 | 1998-10-01 | 127.160464 |
| 4 | 澳大利亚 | 阿德莱德 | 南澳大利亚 | 商务 | 1999-01-01 | 137.448533 |
2. 跨部门协调
2a. 根据跨部门层级聚合数据集
数据集可以按以下非严格的层级结构进行分组。
使用 HierarchicalForecast 中的 aggregate 函数,我们可以获得完整的时间序列集。
| unique_id | ds | y | |
|---|---|---|---|
| 0 | 澳大利亚 | 1998-01-01 | 23182.197269 |
| 1 | 澳大利亚 | 1998-04-01 | 20323.380067 |
| 2 | 澳大利亚 | 1998-07-01 | 19826.640511 |
| 3 | 澳大利亚 | 1998-10-01 | 20830.129891 |
| 4 | 澳大利亚 | 1999-01-01 | 22087.353380 |
| ... | ... | ... | ... |
| 33995 | 澳大利亚/西澳大利亚/珀斯体验/V... | 2016-10-01 | 439.699451 |
| 33996 | 澳大利亚/西澳大利亚/珀斯体验/V... | 2017-01-01 | 356.867038 |
| 33997 | 澳大利亚/西澳大利亚/珀斯体验/V... | 2017-04-01 | 302.296119 |
| 33998 | 澳大利亚/西澳大利亚/珀斯体验/V... | 2017-07-01 | 373.442070 |
| 33999 | 澳大利亚/西澳大利亚/珀斯体验/V... | 2017-10-01 | 455.316702 |
| unique_id | 澳大利亚/ACT/堪培拉/商务 | 澳大利亚/ACT/堪培拉/度假 | 澳大利亚/ACT/堪培拉/其他 | 澳大利亚/ACT/堪培拉/探亲访友 | |
|---|---|---|---|---|---|
| 0 | 澳大利亚 | 1.0 | 1.0 | 1.0 | 1.0 |
| 1 | 澳大利亚/ACT | 1.0 | 1.0 | 1.0 | 1.0 |
| 2 | 澳大利亚/新南威尔士 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3 | 澳大利亚/北领地 | 0.0 | 0.0 | 0.0 | 0.0 |
| 4 | 澳大利亚/昆士兰 | 0.0 | 0.0 | 0.0 | 0.0 |
2b. 拆分训练/测试集
我们使用最后两年(8个季度)作为测试集。因此,我们的预测 horizon=8。
2c. 计算基础预测
以下单元格使用 AutoETS 模型为 Y_df 中的每个时间序列计算基础预测。请注意,Y_hat_df 包含预测值,但它们并不一致。
2d. 协调预测
以下单元格使用 HierarchicalReconciliation 类使先前的预测保持一致。由于层级结构不是严格的,我们无法使用 TopDown 或 MiddleOut 等方法。在本例中,我们使用 BottomUp 和 MinTrace。
数据框 Y_rec_df 包含协调后的预测值。
| unique_id | ds | AutoETS | AutoETS/BottomUp | AutoETS/MinTrace_method-mint_shrink | AutoETS/MinTrace_method-ols | |
|---|---|---|---|---|---|---|
| 0 | 澳大利亚 | 2016-01-01 | 25990.068004 | 24381.911737 | 25428.089783 | 25894.399067 |
| 1 | 澳大利亚 | 2016-04-01 | 24458.490282 | 22903.895964 | 23914.271400 | 24357.301898 |
| 2 | 澳大利亚 | 2016-07-01 | 23974.055984 | 22412.265739 | 23428.462394 | 23865.910647 |
| 3 | 澳大利亚 | 2016-10-01 | 24563.454495 | 23127.349578 | 24089.845955 | 24470.782393 |
| 4 | 澳大利亚 | 2017-01-01 | 25990.068004 | 24518.118006 | 25545.358678 | 25901.362283 |
3. 时间协调
接下来,我们旨在在时间域上也协调我们的预测。
3a. 根据时间层级聚合数据集
我们首先定义时间聚合规范。规范是一个字典,其中键是聚合的名称,值是该聚合中应聚合的底层时间步长的数量。例如,year 包含 12 个月,因此我们定义一个键值对 "yearly":12。我们可以对我们感兴趣的其他聚合进行类似操作。
在此示例中,我们选择 year、semiannual 和 quarter 的时间聚合。底层时间步长是季度频率的。
接下来,我们使用 aggregate_temporal 函数计算时间聚合的训练集和测试集。请注意,由于测试集包含训练集中未包含的时间层级,因此训练集和测试集的聚合矩阵 S 不同。
| temporal_id | quarter-1 | quarter-2 | quarter-3 | quarter-4 | |
|---|---|---|---|---|---|
| 0 | year-1 | 1.0 | 1.0 | 1.0 | 1.0 |
| 1 | year-2 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2 | year-3 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3 | year-4 | 0.0 | 0.0 | 0.0 | 0.0 |
| 4 | year-5 | 0.0 | 0.0 | 0.0 | 0.0 |
| temporal_id | quarter-1 | quarter-2 | quarter-3 | quarter-4 | |
|---|---|---|---|---|---|
| 0 | year-1 | 1.0 | 1.0 | 1.0 | 1.0 |
| 1 | year-2 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2 | semiannual-1 | 1.0 | 1.0 | 0.0 | 0.0 |
| 3 | semiannual-2 | 0.0 | 0.0 | 1.0 | 1.0 |
| 4 | semiannual-3 | 0.0 | 0.0 | 0.0 | 0.0 |
如果您没有可用的测试集,通常是进行预测时的情况,则需要创建一个未来数据框,其中包含正确的底层 unique_ids 和时间戳,以便可以进行时间聚合。我们可以使用 make_future_dataframe 辅助函数来完成此操作。
Y_test_df_te_new 然后可以在 aggregate_temporal 中使用,以构建时间聚合结构。
我们可以验证我们是否拥有相同的时间聚合测试集,只是 Y_test_df_te_new 不包含真实值 y。
| temporal_id | unique_id | ds | y | |
|---|---|---|---|---|
| 0 | year-1 | 澳大利亚 | 2016-10-01 | 101484.586551 |
| 1 | year-2 | 澳大利亚 | 2017-10-01 | 107709.864650 |
| 2 | year-1 | 澳大利亚/ACT | 2016-10-01 | 2457.401367 |
| 3 | year-2 | 澳大利亚/ACT | 2017-10-01 | 2734.748452 |
| 4 | year-1 | 澳大利亚/ACT/商务 | 2016-10-01 | 754.139245 |
| ... | ... | ... | ... | ... |
| 5945 | quarter-4 | 澳大利亚/西澳大利亚/探亲访友 | 2016-10-01 | 787.030391 |
| 5946 | quarter-5 | 澳大利亚/西澳大利亚/探亲访友 | 2017-01-01 | 702.777251 |
| 5947 | quarter-6 | 澳大利亚/西澳大利亚/探亲访友 | 2017-04-01 | 642.516090 |
| 5948 | quarter-7 | 澳大利亚/西澳大利亚/探亲访友 | 2017-07-01 | 646.521395 |
| 5949 | quarter-8 | 澳大利亚/西澳大利亚/探亲访友 | 2017-10-01 | 813.184778 |
| temporal_id | unique_id | ds | |
|---|---|---|---|
| 0 | year-1 | 澳大利亚 | 2016-10-01 |
| 1 | year-2 | 澳大利亚 | 2017-10-01 |
| 2 | year-1 | 澳大利亚/ACT | 2016-10-01 |
| 3 | year-2 | 澳大利亚/ACT | 2017-10-01 |
| 4 | year-1 | 澳大利亚/ACT/商务 | 2016-10-01 |
| ... | ... | ... | ... |
| 5945 | quarter-4 | 澳大利亚/西澳大利亚/探亲访友 | 2016-10-01 |
| 5946 | quarter-5 | 澳大利亚/西澳大利亚/探亲访友 | 2017-01-01 |
| 5947 | quarter-6 | 澳大利亚/西澳大利亚/探亲访友 | 2017-04-01 |
| 5948 | quarter-7 | 澳大利亚/西澳大利亚/探亲访友 | 2017-07-01 |
| 5949 | quarter-8 | 澳大利亚/西澳大利亚/探亲访友 | 2017-10-01 |
3b. 计算基础预测
现在,我们需要为每个时间聚合计算基础预测。以下单元格使用 AutoETS 模型为 Y_train_df_te 中的每个时间聚合计算基础预测。请注意,Y_hat_df_te 包含预测值,但它们并不一致。
另请注意,每个时间聚合的频率和 horizon 都不同。在此示例中,最低层级具有季度频率,horizon 为 8(构成 2 年)。因此,year 聚合具有年度频率,horizon 为 2。
当然,可以为时间聚合中的每个层级选择不同的模型 - 您可以随心所欲地创新!
3c. 协调预测
我们可以再次使用 HierarchicalReconciliation 类来协调预测。在此示例中,我们使用 BottomUp 和 MinTrace。请注意,我们必须在 reconcile 函数中设置 temporal=True。
请注意,时间协调目前不支持样本内(insample)协调方法,例如 MinTrace(method='mint_shrink')。
4. 评估
HierarchicalForecast 包包括用于评估不同层级的 evaluate 函数。
4a. 跨部门评估
我们首先评估所有跨部门聚合的预测。
| level | metric | Base | BottomUp | MinTrace(ols) | |
|---|---|---|---|---|---|
| 0 | Total | rmse | 4249.25 | 4461.95 | 4234.55 |
| 1 | 目的 | rmse | 1222.57 | 1273.48 | 1137.57 |
| 2 | 州 | rmse | 635.78 | 546.02 | 611.32 |
| 3 | Regions | rmse | 103.67 | 107.00 | 99.23 |
| 4 | Bottom | rmse | 33.15 | 33.98 | 32.30 |
| 5 | Overall | rmse | 81.89 | 82.41 | 78.97 |
可以看出,MinTrace(ols) 似乎是每个跨部门聚合的最佳预测方法。
4b. 时间评估
然后,我们评估所有时间聚合的时间聚合预测。
| level | metric | Base | BottomUp | MinTrace(ols) | |
|---|---|---|---|---|---|
| 0 | year | rmse | 480.85 | 581.18 | 515.32 |
| 1 | semiannual | rmse | 312.33 | 304.98 | 275.30 |
| 2 | quarter | rmse | 168.02 | 168.02 | 155.61 |
| 3 | Overall | rmse | 253.94 | 266.17 | 241.19 |
同样,MinTrace(ols) 是总体最佳方法,在 quarter 聚合预测上得分最低的 rmse,而在 year 聚合预测上略差于 Base 预测。
4c. 跨时间评估
最后,我们进行跨时间评估。为此,我们首先需要获取跨部门层级和时间层级的组合,我们可以使用 get_cross_temporal_tags 辅助函数来完成。
正如我们所见,我们现在有一个标签 Country//year,其中包含 Australia//year-1 和 Australia//year-2,表示跨部门层级 Australia 在时间层级 2016 和 2017 下的聚合。
我们现在的数据集和跨时间标签已准备好进行评估。
我们定义一组 eval_tags,现在我们将每个跨部门聚合也按每个时间聚合进行拆分。请注意,我们在下面的概述中跳过了 semiannual 时间聚合。
| level | metric | Base | BottomUp | MinTrace(ols) | |
|---|---|---|---|---|---|
| 0 | TotalByYear | rmse | 7148.99 | 8243.06 | 7748.40 |
| 1 | RegionsByYear | rmse | 151.96 | 175.69 | 158.48 |
| 2 | BottomByYear | rmse | 46.98 | 50.78 | 46.72 |
| 3 | TotalByQuarter | rmse | 2060.77 | 2060.77 | 1942.32 |
| 4 | RegionsByQuarter | rmse | 57.07 | 57.07 | 54.12 |
| 5 | BottomByQuarter | rmse | 19.42 | 19.42 | 18.69 |
| 6 | Overall | rmse | 43.14 | 45.27 | 42.49 |
我们发现最佳方法是跨时间协调方法 AutoETS/MinTrace_method-ols,它实现了总体最低的 RMSE。
参考文献
- Hyndman, R.J., & Athanasopoulos, G. (2021). “Forecasting: principles and practice, 3rd edition: Chapter 11: Forecasting hierarchical and grouped series.”. OTexts: Melbourne, Australia. OTexts.com/fpp3 Accessed on July 2022.
- Rob Hyndman, Alan Lee, Earo Wang, Shanika Wickramasuriya, and Maintainer Earo Wang (2021). “hts: Hierarchical and Grouped Time Series”. URL https://cran.r-project.cn/package=hts. R package version 0.3.1.
- Mitchell O’Hara-Wild, Rob Hyndman, Earo Wang, Gabriel Caceres, Tim-Gunnar Hensel, and Timothy Hyndman (2021). “fable: Forecasting Models for Tidy Time Series”. URL https://cran.r-project.cn/package=fable. R package version 6.0.2.
- Athanasopoulos, G, Hyndman, Rob J., Kourentzes, N., Petropoulos, Fotios (2017). Forecasting with temporal hierarchies. European Journal of Operational Research, 262, 60-74

