时间聚合 (旅游业)
澳大利亚旅游数据的分层时间预测
在许多应用中,时间序列集合是按层级组织的。例如,存在地理层级、产品或类别,它们定义了不同类型的聚合。在这种情况下,预测者通常需要为所有分解和聚合序列提供预测。一个自然的需求是这些预测应是“一致的”,也就是说,底层序列的预测值精确地加总等于聚合序列的预测值。
在本 notebook 中,我们将展示如何使用 HierarchicalForecast
在时间层级之间生成一致的预测。我们将使用经典的澳大利亚国内旅游 (Tourism
) 数据集,该数据集包含澳大利亚各州游客数量的月度时间序列。
我们将首先加载 Tourism
数据,并使用 StatsForecast
中的 AutoETS
模型生成基础预测。然后,我们根据时间层级,使用 HierarchicalForecast
中的几种协调算法协调预测结果。
您可以使用 Google Colab,通过 CPU 或 GPU 运行这些实验。
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. 时间协调
首先,我们向数据添加一个 unique_id
。
2a. 划分训练/测试集
我们使用最后两年(8 个季度)作为测试集。因此,我们的预测范围 horizon=8。
2a. 根据时间层级聚合数据集
我们首先定义时间聚合规范。该规范是一个字典,其中键是聚合的名称,值是在该聚合中应聚合的底层时间步长的数量。例如,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 |
如果您的测试集不可用(这在进行预测时通常是这种情况),则需要创建一个 future dataframe,其中包含正确的底层 unique_ids 和时间戳,以便它们可以进行时间聚合。我们可以使用 make_future_dataframe
辅助函数来完成此操作。
然后可以在 aggregate_temporal
中使用 Y_test_df_new
来构建时间聚合的结构。
并且我们可以验证我们拥有相同的时间聚合测试集,只是 Y_test_df_new
不包含地面真值 y
。
temporal_id | quarter-1 | quarter-2 | quarter-3 | quarter-4 | quarter-5 | quarter-6 | quarter-7 | quarter-8 | |
---|---|---|---|---|---|---|---|---|---|
0 | year-1 | 1.0 | 1.0 | 1.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 |
1 | year-2 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 1.0 | 1.0 |
2 | semiannual-1 | 1.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
3 | semiannual-2 | 0.0 | 0.0 | 1.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 |
4 | semiannual-3 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 0.0 | 0.0 |
5 | semiannual-4 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 |
6 | quarter-1 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
7 | quarter-2 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
8 | quarter-3 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
9 | quarter-4 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 |
10 | quarter-5 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 |
11 | quarter-6 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 |
12 | quarter-7 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 |
13 | quarter-8 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 |
temporal_id | unique_id | ds | y | |
---|---|---|---|---|
0 | year-1 | Australia/ACT/Canberra/Business | 2016-10-01 | 754.139245 |
1 | year-2 | Australia/ACT/Canberra/Business | 2017-10-01 | 809.950839 |
2 | year-1 | Australia/ACT/Canberra/Holiday | 2016-10-01 | 735.365896 |
3 | year-2 | Australia/ACT/Canberra/Holiday | 2017-10-01 | 834.717900 |
4 | year-1 | Australia/ACT/Canberra/Other | 2016-10-01 | 175.239916 |
… | … | … | … | … |
4251 | quarter-4 | Australia/Western Australia/Experience Perth/V… | 2016-10-01 | 439.699451 |
4252 | quarter-5 | Australia/Western Australia/Experience Perth/V… | 2017-01-01 | 356.867038 |
4253 | quarter-6 | Australia/Western Australia/Experience Perth/V… | 2017-04-01 | 302.296119 |
4254 | quarter-7 | Australia/Western Australia/Experience Perth/V… | 2017-07-01 | 373.442070 |
4255 | quarter-8 | Australia/Western Australia/Experience Perth/V… | 2017-10-01 | 455.316702 |
temporal_id | unique_id | ds | |
---|---|---|---|
0 | year-1 | Australia/ACT/Canberra/Business | 2016-10-01 |
1 | year-2 | Australia/ACT/Canberra/Business | 2017-10-01 |
2 | year-1 | Australia/ACT/Canberra/Holiday | 2016-10-01 |
3 | year-2 | Australia/ACT/Canberra/Holiday | 2017-10-01 |
4 | year-1 | Australia/ACT/Canberra/Other | 2016-10-01 |
… | … | … | … |
4251 | quarter-4 | Australia/Western Australia/Experience Perth/V… | 2016-10-01 |
4252 | quarter-5 | Australia/Western Australia/Experience Perth/V… | 2017-01-01 |
4253 | quarter-6 | Australia/Western Australia/Experience Perth/V… | 2017-04-01 |
4254 | quarter-7 | Australia/Western Australia/Experience Perth/V… | 2017-07-01 |
4255 | quarter-8 | Australia/Western Australia/Experience Perth/V… | 2017-10-01 |
3b. 计算基础预测
现在,我们需要计算每个时间聚合的基础预测。以下单元格使用 AutoETS
模型计算 Y_train_df
中每个时间聚合的 基础预测。请注意,Y_hat_df
包含预测结果,但它们不一致。
另请注意,每个时间聚合的频率和范围都不同。在本例中,最低层级的频率是季度,范围为 8
(构成 2
年)。因此,year
聚合的频率是年度,范围为 2
。
当然,您也可以为时间聚合中的每个层级选择不同的模型 - 您可以尽情发挥创意!
3c. 协调预测结果
我们可以使用 HierarchicalReconciliation
类来协调预测结果。在本例中,我们使用 BottomUp
和 MinTrace
。请注意,我们必须在 reconcile
函数中设置 temporal=True
。
请注意,时间协调目前不支持样本内协调方法,例如 MinTrace(method='mint_shrink')
。
4. 评估
HierarchicalForecast
包包含 evaluate
函数,用于评估不同的层级。
我们评估 所有时间聚合 的时间聚合预测结果。
层级 | 指标 | 基础 | BottomUp | MinTrace(ols) | |
---|---|---|---|---|---|
0 | 年 | mae | 47.0000 | 50.8000 | 46.7000 |
1 | 年 | scaled_crps | 0.0562 | 0.0620 | 0.0666 |
2 | 半年 | mae | 29.5000 | 30.5000 | 29.1000 |
3 | 半年 | scaled_crps | 0.0643 | 0.0681 | 0.0727 |
4 | 季度 | mae | 19.4000 | 19.4000 | 18.7000 |
5 | 季度 | scaled_crps | 0.0876 | 0.0876 | 0.0864 |
6 | 总计 | mae | 26.2000 | 27.1000 | 25.7000 |
7 | 总计 | scaled_crps | 0.0765 | 0.0784 | 0.0797 |
MinTrace(ols)
是整体最佳的点方法,在 year
和 semiannual
聚合预测以及 quarter
底层聚合预测上得分最低的 mae
。然而,Base
方法在概率指标 crps
方面整体更好,其得分最低,这表明在此示例中,使用 Base
方法预测的不确定性水平更好。
附录:绘制 S 矩阵
我们绘制了测试集的求和矩阵。它相当直观:测试集中有两年,每年包含 4 个季度。* S
矩阵的第一行显示聚合 2016
如何通过对 2016 年的 4 个季度求和得到。* S
矩阵的第二行显示聚合 2017
如何通过对 2017 年的 4 个季度求和得到。* 接下来的 4 行显示如何获得半年聚合。* 最后几行是每个季度的单位矩阵,表示底部时间层级(每个季度)。