在本 Notebook 中,我们将演示如何使用 TimeGPT 进行时间层次预测。我们将使用一个具有小时频率的数据集,并使用 TimeGPT 创建小时和 2 小时频率级别的预测。后者是通过将时间序列按 2 小时窗口聚合而形成的。随后,我们可以使用时间协调技术来提高 TimeGPT 的预测性能。

1. 加载和处理数据

import numpy as np
import pandas as pd

from utilsforecast.evaluation import evaluate
from utilsforecast.plotting import plot_series
from utilsforecast.losses import mae, rmse
from nixtla import NixtlaClient
nixtla_client = NixtlaClient(
    # api_key = 'my_api_key_provided_by_nixtla'
)
df = pd.read_csv('https://raw.githubusercontent.com/Nixtla/transfer-learning-time-series/main/datasets/electricity-short-with-ex-vars.csv')
df['ds'] = pd.to_datetime(df['ds'])
df_sub = df.query('unique_id == "DE"')
df_train = df_sub.query('ds < "2017-12-29"')
df_test = df_sub.query('ds >= "2017-12-29"')
df_train.shape, df_test.shape
((1632, 12), (48, 12))
plot_series(df_train[['unique_id','ds','y']][-200:], forecasts_df= df_test[['unique_id','ds','y']].rename(columns={'y': 'test'}))

2. 时间聚合

我们有兴趣为小时和 2 小时窗口生成预测。我们可以使用 TimeGPT 生成这些预测。生成这些预测后,我们将利用层次预测技术来提高每个预测的准确性。

我们首先定义时间聚合规范。规范是一个字典,其中键是聚合的名称,值是在该聚合中应该聚合的最低级别时间步长数量。

在此示例中,我们选择 2 小时周期和 1 小时周期(最低级别)的时间聚合。

spec_temporal = { "2-hour-period": 2, "1-hour-period": 1}

接下来,我们使用 hierarchicalforecast 中的 aggregate_temporal 函数计算时间聚合的训练集和测试集。请注意,训练集和测试集的聚合矩阵 S 不同,因为测试集包含训练集中未包含的时间层次结构。

from hierarchicalforecast.utils import aggregate_temporal
Y_train, S_train, tags_train = aggregate_temporal(df=df_train[['unique_id','ds','y']], spec=spec_temporal)
Y_test, S_test, tags_test = aggregate_temporal(df=df_test[['unique_id','ds','y']],  spec=spec_temporal)

Y_train 包含我们的训练数据,涵盖 1 小时和 2 小时周期。例如,如果我们查看训练数据的前两个时间戳,我们有一个结束于 2017-10-22 01:00 的 2 小时周期,以及两个 1 小时周期,第一个结束于 2017-10-22 00:00,第二个结束于 2017-10-22 01:00,后一个与第一个 2 小时周期结束的时间相对应。

此外,第一个 2 小时周期的真实值 y 是 38.13,等于前两个 1 小时周期的总和 (19.10 + 19.03)。这展示了如何将较高频率的 1-hour-period 聚合到 2-hour-period 频率中。

Y_train.query("ds <= '2017-10-22 01:00:00'")
temporal_idunique_iddsy
02-hour-period-1DE2017-10-22 01:00:0038.13
8161-hour-period-1DE2017-10-22 00:00:0019.10
8171-hour-period-2DE2017-10-22 01:00:0019.03

聚合矩阵 S_trainS_test 详细说明了如何将最低时间粒度(小时)聚合成 2 小时周期。例如,第一个 2 小时周期,命名为 2-hour-period-1,可以通过求和前两个小时周期 1-hour-period-11-hour-period-2 来构建——这我们在上面检查 Y_train 时也验证过了。

S_train.iloc[:5, :5]
temporal_id1-hour-period-11-hour-period-21-hour-period-31-hour-period-4
02-hour-period-11.01.00.00.0
12-hour-period-20.00.01.01.0
22-hour-period-30.00.00.00.0
32-hour-period-40.00.00.00.0
42-hour-period-50.00.00.00.0

3b. 计算基础预测

现在,我们需要为每个时间聚合计算基础预测。以下单元格使用 TimeGPT 计算 Y_train 中每个时间聚合的 基础预测

请注意,每个时间聚合的频率和预测范围(horizon)都不同。在此示例中,最低级别的频率是每小时,预测范围为 48。因此,2-hourly-period 聚合的频率是每 2 小时,预测范围为 24

Y_hats = []
id_cols = ["unique_id", "temporal_id", "ds", "y"]
# We will train a model for each temporal level
for level, temporal_ids_train in tags_train.items():
    # Filter the data for the level
    Y_level_train = Y_train.query("temporal_id in @temporal_ids_train")
    temporal_ids_test = tags_test[level]
    Y_level_test = Y_test.query("temporal_id in @temporal_ids_test")
    # For each temporal level we have a different frequency and forecast horizon
    freq_level = pd.infer_freq(Y_level_train["ds"].unique())
    horizon_level = Y_level_test["ds"].nunique()
    # Train a model and create forecasts
    Y_hat_level = nixtla_client.forecast(df=Y_level_train[["ds", "unique_id", "y"]], h=horizon_level)
    # Add the test set to the forecast
    Y_hat_level = Y_hat_level.merge(Y_level_test, on=["ds", "unique_id"], how="left")
    # Put cols in the right order (for readability)
    Y_hat_cols = id_cols + [col for col in Y_hat_level.columns if col not in id_cols]
    Y_hat_level = Y_hat_level[Y_hat_cols]
    # Append the forecast to the list
    Y_hats.append(Y_hat_level)

Y_hat = pd.concat(Y_hats, ignore_index=True)

请注意,Y_hat 包含所有预测,但它们彼此不一致。例如,考虑这两种频率的第一个时间段的预测。

Y_hat.query("temporal_id in ['2-hour-period-1', '1-hour-period-1', '1-hour-period-2']")
unique_idtemporal_iddsyTimeGPT
0DE2-hour-period-12017-12-29 01:00:0010.4516.949448
24DE1-hour-period-12017-12-29 00:00:009.73-0.241489
25DE1-hour-period-22017-12-29 01:00:000.72-3.456482

第一个 2 小时周期的真实值 y 是 10.45,前两个 1 小时周期的真实值之和是 (9.73 + 0.72) = 10.45。因此,这些值彼此一致。

然而,第一个 2 小时周期的预测值是 16.95,而前两个 1 小时周期的预测值之和是 -3.69。因此,这些预测显然彼此不一致。

我们将使用协调技术使这些预测更好地彼此一致并提高其准确性。

3c. 协调预测

我们可以使用 HierarchicalReconciliation 类来协调预测。在此示例中,我们使用 MinTrace。请注意,我们需要在 reconcile 函数中设置 temporal=True

from hierarchicalforecast.methods import MinTrace
from hierarchicalforecast.core import HierarchicalReconciliation
reconcilers = [
    MinTrace(method="wls_struct"),
]
hrec = HierarchicalReconciliation(reconcilers=reconcilers)
Y_rec = hrec.reconcile(Y_hat_df=Y_hat, S=S_test, tags=tags_test, temporal=True)

4. 评估

HierarchicalForecast 包包含 evaluate 函数用于评估不同的层次结构。

我们评估所有时间聚合级别的时间聚合预测。

import hierarchicalforecast.evaluation as hfe
from utilsforecast.losses import mae
evaluation = hfe.evaluate(df = Y_rec.drop(columns = 'unique_id'),
                      tags = tags_test,
                      metrics = [mae],
                      id_col='temporal_id')

numeric_cols = evaluation.select_dtypes(include="number").columns
evaluation[numeric_cols] = evaluation[numeric_cols].map('{:.3}'.format).astype(np.float64)
evaluation
级别指标TimeGPTTimeGPT/MinTrace_method-wls_struct
02 小时周期mae25.212.00
11 小时周期mae18.56.16
2总体mae20.88.12

正如我们所见,我们提高了 TimeGPT 在 2 小时周期和 1 小时周期上的预测性能,因为这两个级别在 MAE 和 RMSE 上都有显著降低。

从视觉上看,我们也可以验证在使用协调技术后预测效果更好。对于 1 小时周期的预测

plot_series(Y_train.query("temporal_id in @tags_train['1-hour-period']")[["y", "ds", "unique_id"]].iloc[-100:], forecasts_df=Y_rec.query("temporal_id in @tags_test['1-hour-period']").drop(columns=["temporal_id"]))

以及 2 小时周期的预测

plot_series(Y_train.query("temporal_id in @tags_train['2-hour-period']")[["y", "ds", "unique_id"]].iloc[-50:], forecasts_df=Y_rec.query("temporal_id in @tags_test['2-hour-period']").drop(columns=["temporal_id"]))

此外,我们现在可以验证预测彼此之间更好地一致。对于第一个 2 小时周期,协调后的预测值为 6.63,前两个 1 小时周期的预测值之和为 1.7 + 4.92 = 6.63。因此,我们现在在不同频率上拥有更准确和一致的预测。

Y_rec.query("temporal_id in ['2-hour-period-1', '1-hour-period-1', '1-hour-period-2']")
unique_idtemporal_iddsyTimeGPTTimeGPT/MinTrace_method-wls_struct
0DE2-hour-period-12017-12-29 01:00:0010.4516.9494486.625738
24DE1-hour-period-12017-12-29 00:00:009.73-0.2414894.920365
25DE1-hour-period-22017-12-29 01:00:000.72-3.4564821.705373

结论

在本 Notebook 中,我们展示了: - 如何使用 TimeGPT 为同一数据集创建多种频率的预测 - 如何使用时间协调技术提高这些预测的准确性

请注意,即使我们创建了两种不同频率的预测,也并非“必须”使用 2 小时周期的预测。您也可以仅使用此技术来改进 1 小时周期的预测。