在本教程中,我们将展示如何在有许多零值的间歇性序列上使用 TimeGPT。在这里,我们使用 M5 数据集的一个子集,该数据集跟踪加州一家商店食品项目的需求。该数据集还包括外部变量,如销售价格和特定日期发生的事件类型。

TimeGPT 在平均绝对误差 (MAE) 为 0.49 时达到最佳性能,这比专门用于处理间歇性时间序列数据的最佳统计模型提高了 14%

使用 TimeGPT 进行预测耗时 6.8 秒,而使用统计模型进行拟合和预测耗时 5.2 秒。从技术上讲,TimeGPT 速度较慢,但仅约 1 秒的时间差,我们使用 TimeGPT 获得了更好的预测结果。

初始设置

我们首先导入本教程所需的包,并创建 NixtlaClient 的实例。

import time
import pandas as pd
import numpy as np

from nixtla import NixtlaClient

from utilsforecast.losses import mae
from utilsforecast.evaluation import evaluate
nixtla_client = NixtlaClient(
    # defaults to os.environ.get("NIXTLA_API_KEY")
    api_key = 'my_api_key_provided_by_nixtla'
)

👍 使用 Azure AI 端点

要使用 Azure AI 端点,请记住也要设置 base_url 参数

nixtla_client = NixtlaClient(base_url="you azure ai endpoint", api_key="your api_key")

现在我们读取数据集并进行绘制。

df = pd.read_csv("https://raw.githubusercontent.com/Nixtla/transfer-learning-time-series/main/datasets/m5_sales_exog_small.csv")
df['ds'] = pd.to_datetime(df['ds'])

df.head()
unique_iddsysell_priceevent_type_Culturalevent_type_Nationalevent_type_Religiousevent_type_Sporting
0FOODS_1_0012011-01-2932.00000
1FOODS_1_0012011-01-3002.00000
2FOODS_1_0012011-01-3102.00000
3FOODS_1_0012011-02-0112.00000
4FOODS_1_0012011-02-0242.00000
nixtla_client.plot(
    df, 
    max_insample_length=365, 
)

在上图中,我们可以看到该数据集的间歇性特征,许多时期需求为零。

现在,让我们使用 TimeGPT 来预测每种产品的需求。

有界预测

为了避免模型产生负面预测,我们对数据使用对数变换。这样,模型将被迫只预测正值。

请注意,由于数据集中存在零值,我们在取对数之前对所有点都加一。

df_transformed = df.copy()

df_transformed['y'] = np.log(df_transformed['y']+1)

df_transformed.head()
unique_iddsysell_priceevent_type_Culturalevent_type_Nationalevent_type_Religiousevent_type_Sporting
0FOODS_1_0012011-01-291.3862942.00000
1FOODS_1_0012011-01-300.0000002.00000
2FOODS_1_0012011-01-310.0000002.00000
3FOODS_1_0012011-02-010.6931472.00000
4FOODS_1_0012011-02-021.6094382.00000

现在,我们保留最后 28 个时间步作为测试集,其余部分用作模型的输入。

test_df = df_transformed.groupby('unique_id').tail(28)                                                      

input_df = df_transformed.drop(test_df.index).reset_index(drop=True)

使用 TimeGPT 进行预测

start = time.time()

fcst_df = nixtla_client.forecast(
    df=input_df,
    h=28,                            
    level=[80],                        # Generate a 80% confidence interval
    finetune_steps=10,                 # Specify the number of steps for fine-tuning
    finetune_loss='mae',               # Use the MAE as the loss function for fine-tuning
    model='timegpt-1-long-horizon',    # Use the model for long-horizon forecasting
    time_col='ds',
    target_col='y',
    id_col='unique_id'
)

end = time.time()

timegpt_duration = end - start

print(f"Time (TimeGPT): {timegpt_duration}")
INFO:nixtla.nixtla_client:Validating inputs...
INFO:nixtla.nixtla_client:Preprocessing dataframes...
INFO:nixtla.nixtla_client:Inferred freq: D
INFO:nixtla.nixtla_client:Calling Forecast Endpoint...
Time (TimeGPT): 6.164413213729858

📘 Azure AI 中的可用模型

如果您使用的是 Azure AI 端点,请务必设置 model="azureai"

nixtla_client.forecast(..., model="azureai")

对于公共 API,我们支持两种模型:timegpt-1timegpt-1-long-horizon

默认情况下,使用 timegpt-1。请参阅本教程,了解如何以及何时使用 timegpt-1-long-horizon

太好了!TimeGPT 在 5.8 秒内完成,现在我们有了预测结果。然而,这些预测结果是经过转换的,因此我们需要进行逆转换以恢复到原始比例。因此,我们对每个数据点取指数并减去一。

cols = [col for col in fcst_df.columns if col not in ['ds', 'unique_id']]

for col in cols:
    fcst_df[col] = np.exp(fcst_df[col])-1

fcst_df.head()
unique_iddsTimeGPTTimeGPT-lo-80TimeGPT-hi-80
0FOODS_1_0012016-05-230.286841-0.2671011.259465
1FOODS_1_0012016-05-240.320482-0.2412361.298046
2FOODS_1_0012016-05-250.287392-0.3622501.598791
3FOODS_1_0012016-05-260.295326-0.1454890.963542
4FOODS_1_0012016-05-270.315868-0.1665161.077437

评估

在衡量性能指标之前,让我们绘制预测值与实际值的对比图。

nixtla_client.plot(test_df, fcst_df, models=['TimeGPT'], level=[80], time_col='ds', target_col='y')

最后,我们可以衡量模型的平均绝对误差 (MAE)。

fcst_df['ds'] = pd.to_datetime(fcst_df['ds'])

test_df = pd.merge(test_df, fcst_df, 'left', ['unique_id', 'ds'])
evaluation = evaluate(
    test_df,
    metrics=[mae],
    models=["TimeGPT"],
    target_col="y",
    id_col='unique_id'
)

average_metrics = evaluation.groupby('metric')['TimeGPT'].mean()
average_metrics
metric
mae    0.492559
Name: TimeGPT, dtype: float64

使用统计模型进行预测

Nixtla 的 statsforecast 库提供了一系列专门为间歇性预测构建的统计模型,例如 Croston、IMAPA 和 TSB。让我们使用这些模型,看看它们与 TimeGPT 的性能对比如何。

from statsforecast import StatsForecast
from statsforecast.models import CrostonClassic, CrostonOptimized, IMAPA, TSB

在这里,我们使用四种模型:两个版本的 Croston、IMAPA 和 TSB。

models = [CrostonClassic(), CrostonOptimized(), IMAPA(), TSB(0.1, 0.1)]

sf = StatsForecast(
    models=models,
    freq='D',
    n_jobs=-1
)

然后,我们可以在数据上拟合模型。

start = time.time()

sf.fit(df=input_df)

sf_preds = sf.predict(h=28)

end = time.time()

sf_duration = end - start

print(f"Statistical models took :{sf_duration}s")

在这里,使用四种统计模型进行拟合和预测耗时 5.2 秒,而 TimeGPT 耗时 5.8 秒,因此 TimeGPT 仅慢了 0.6 秒。

同样,我们需要进行逆转换。请记住,训练数据之前已使用对数函数进行转换。

cols = [col for col in sf_preds.columns if col not in ['ds', 'unique_id']]

for col in cols:
    sf_preds[col] = np.exp(sf_preds[col])-1

sf_preds.head()
dsCrostonClassicCrostonOptimizedIMAPATSB
unique_id
FOODS_1_0012016-05-230.5990930.5990930.4457790.396258
FOODS_1_0012016-05-240.5990930.5990930.4457790.396258
FOODS_1_0012016-05-250.5990930.5990930.4457790.396258
FOODS_1_0012016-05-260.5990930.5990930.4457790.396258
FOODS_1_0012016-05-270.5990930.5990930.4457790.396258

评估

现在,让我们结合所有方法的预测结果,看看哪种方法表现最好。

test_df = pd.merge(test_df, sf_preds, 'left', ['unique_id', 'ds'])
test_df.head()
unique_iddsysell_priceevent_type_Culturalevent_type_Nationalevent_type_Religiousevent_type_SportingTimeGPTTimeGPT-lo-80TimeGPT-hi-80CrostonClassicCrostonOptimizedIMAPATSB
0FOODS_1_0012016-05-231.3862942.2400000.286841-0.2671011.2594650.5990930.5990930.4457790.396258
1FOODS_1_0012016-05-240.0000002.2400000.320482-0.2412361.2980460.5990930.5990930.4457790.396258
2FOODS_1_0012016-05-250.0000002.2400000.287392-0.3622501.5987910.5990930.5990930.4457790.396258
3FOODS_1_0012016-05-260.0000002.2400000.295326-0.1454890.9635420.5990930.5990930.4457790.396258
4FOODS_1_0012016-05-271.9459102.2400000.315868-0.1665161.0774370.5990930.5990930.4457790.396258
evaluation = evaluate(
    test_df,
    metrics=[mae],
    models=["TimeGPT", "CrostonClassic", "CrostonOptimized", "IMAPA", "TSB"],
    target_col="y",
    id_col='unique_id'
)

average_metrics = evaluation.groupby('metric')[["TimeGPT", "CrostonClassic", "CrostonOptimized", "IMAPA", "TSB"]].mean()
average_metrics
TimeGPTCrostonClassicCrostonOptimizedIMAPATSB
metric
mae0.4925590.5645630.5809220.5719430.567178

在上表中,我们可以看到 TimeGPT 实现了最低的平均绝对误差 (MAE),比性能最佳的统计模型提高了 12.8%。

目前,这是在未使用任何可用外部特征的情况下完成的。虽然统计模型不支持这些特征,但我们尝试将它们包含在 TimeGPT 中。

使用 TimeGPT 和外部变量进行预测

要使用外部变量进行预测,我们需要指定它们在预测范围内的未来值。因此,我们只需选取事件类型,因为这些日期是提前已知的。

futr_exog_df = test_df.drop(["TimeGPT", "CrostonClassic", "CrostonOptimized", "IMAPA", "TSB", "y", "TimeGPT-lo-80", "TimeGPT-hi-80", "sell_price"], axis=1)
futr_exog_df.head()
unique_iddsevent_type_Culturalevent_type_Nationalevent_type_Religiousevent_type_Sporting
0FOODS_1_0012016-05-230000
1FOODS_1_0012016-05-240000
2FOODS_1_0012016-05-250000
3FOODS_1_0012016-05-260000
4FOODS_1_0012016-05-270000

然后,我们只需调用 forecast 方法,并在 X_df 参数中传入 futr_exog_df

start = time.time()

fcst_df = nixtla_client.forecast(
    df=input_df,
    X_df=futr_exog_df,
    h=28,                            
    level=[80],                        # Generate a 80% confidence interval
    finetune_steps=10,                 # Specify the number of steps for fine-tuning
    finetune_loss='mae',               # Use the MAE as the loss function for fine-tuning
    model='timegpt-1-long-horizon',    # Use the model for long-horizon forecasting
    time_col='ds',
    target_col='y',
    id_col='unique_id'
)

end = time.time()

timegpt_duration = end - start

print(f"Time (TimeGPT): {timegpt_duration}")
INFO:nixtla.nixtla_client:Validating inputs...
INFO:nixtla.nixtla_client:Preprocessing dataframes...
INFO:nixtla.nixtla_client:Inferred freq: D
INFO:nixtla.nixtla_client:Using the following exogenous variables: event_type_Cultural, event_type_National, event_type_Religious, event_type_Sporting
INFO:nixtla.nixtla_client:Calling Forecast Endpoint...
Time (TimeGPT): 7.173351287841797

📘 Azure AI 中的可用模型

如果您使用的是 Azure AI 端点,请务必设置 model="azureai"

nixtla_client.forecast(..., model="azureai")

对于公共 API,我们支持两种模型:timegpt-1timegpt-1-long-horizon

默认情况下,使用 timegpt-1。请参阅本教程,了解如何以及何时使用 timegpt-1-long-horizon

太好了!请记住预测结果是经过转换的,因此我们必须再次进行逆转换。

fcst_df.rename(columns={
    'TimeGPT': 'TimeGPT_ex',
}, inplace=True)

cols = [col for col in fcst_df.columns if col not in ['ds', 'unique_id']]

for col in cols:
    fcst_df[col] = np.exp(fcst_df[col])-1

fcst_df.head()
unique_iddsTimeGPT_exTimeGPT-lo-80TimeGPT-hi-80
0FOODS_1_0012016-05-230.281922-0.2699021.250828
1FOODS_1_0012016-05-240.313774-0.2450911.286372
2FOODS_1_0012016-05-250.285639-0.3631191.595252
3FOODS_1_0012016-05-260.295037-0.1456790.963104
4FOODS_1_0012016-05-270.315484-0.1667601.076830

评估

最后,让我们评估使用外部特征的 TimeGPT 的性能。

test_df['TimeGPT_ex'] = fcst_df['TimeGPT_ex'].values
test_df.head()
unique_iddsysell_priceevent_type_Culturalevent_type_Nationalevent_type_Religiousevent_type_SportingTimeGPTTimeGPT-lo-80TimeGPT-hi-80CrostonClassicCrostonOptimizedIMAPATSBTimeGPT_ex
0FOODS_1_0012016-05-231.3862942.2400000.286841-0.2671011.2594650.5990930.5990930.4457790.3962580.281922
1FOODS_1_0012016-05-240.0000002.2400000.320482-0.2412361.2980460.5990930.5990930.4457790.3962580.313774
2FOODS_1_0012016-05-250.0000002.2400000.287392-0.3622501.5987910.5990930.5990930.4457790.3962580.285639
3FOODS_1_0012016-05-260.0000002.2400000.295326-0.1454890.9635420.5990930.5990930.4457790.3962580.295037
4FOODS_1_0012016-05-271.9459102.2400000.315868-0.1665161.0774370.5990930.5990930.4457790.3962580.315484
evaluation = evaluate(
    test_df,
    metrics=[mae],
    models=["TimeGPT", "CrostonClassic", "CrostonOptimized", "IMAPA", "TSB", "TimeGPT_ex"],
    target_col="y",
    id_col='unique_id'
)

average_metrics = evaluation.groupby('metric')[["TimeGPT", "CrostonClassic", "CrostonOptimized", "IMAPA", "TSB", "TimeGPT_ex"]].mean()
average_metrics
TimeGPTCrostonClassicCrostonOptimizedIMAPATSBTimeGPT_ex
metric
mae0.4925590.5645630.5809220.5719430.5671780.485352

从上表中可以看出,使用外部特征提高了 TimeGPT 的性能。现在,它比最佳统计模型提高了 14%。

使用带外部特征的 TimeGPT 耗时 6.8 秒。这比统计模型慢 1.6 秒,但获得了更好的预测结果。