先决条件

本教程假设您对 StatsForecast 有基本了解。有关极简示例,请访问快速入门

引言

时间序列交叉验证是一种评估模型在过去表现如何的方法。其工作原理是在历史数据上定义一个滑动窗口,并预测其后续周期。

Statsforecast 提供了一种快速易用的时间序列交叉验证实现。该实现将交叉验证变成分布式操作,从而减少了时间消耗。在本 Notebook 中,我们将在 M4 竞赛每小时数据集的子集上使用它。

大纲

  1. 安装库
  2. 加载和探索数据
  3. 训练模型
  4. 执行时间序列交叉验证
  5. 评估结果

提示

您可以使用 Colab 以交互方式运行此 Notebook

安装库

我们假设您已经安装了 StatsForecast。如果尚未安装,请查阅本指南了解如何安装 StatsForecast 的说明。

使用 pip install statsforecast 安装必要的软件包

pip install statsforecast
from statsforecast import StatsForecast # required to instantiate StastForecast object and use cross-validation method

加载和探索数据

如引言所述,我们将使用 M4 竞赛的每小时数据集。首先,我们将使用 pandas 从 URL 导入数据。

import pandas as pd
Y_df = pd.read_parquet('https://datasets-nixtla.s3.amazonaws.com/m4-hourly.parquet') # load the data 
Y_df.head()
unique_iddsy
0H11605.0
1H12586.0
2H13586.0
3H14559.0
4H15511.0

StatsForecast 的输入是长格式的数据框,包含三列:unique_idds 和 y。

  • unique_id(字符串、整数或类别)表示时间序列的标识符。
  • ds(日期戳或整数)列应为索引时间的整数或格式为 YYYY-MM-DD 或 YYYY-MM-DD HH:MM:SS 的日期戳。
  • y(数值)表示我们希望预测的测量值。

此示例中的数据已采用此格式,因此无需更改。

为了最大程度地缩短执行此 Notebook 所需的时间,我们将仅使用数据中的一个时间序列,即 unique_id == 'H1' 的那个。但是,您可以根据需要使用任意数量的时间序列,无需对代码进行额外更改。

df = Y_df[Y_df['unique_id'] == 'H1'] # select time series

我们可以使用 StatsForecast.plot 方法绘制我们将处理的时间序列。

StatsForecast.plot(df)

训练模型

在此示例中,我们将使用 StastForecast 的 AutoETS 模型。首先需要从 statsforecast.models 导入它,然后需要实例化一个新的 StatsForecast 对象。

StatsForecast 对象具有以下参数:

  • models: 模型列表。从模型中选择您想要的模型并导入它们。
  • freq: 指示数据频率的字符串。请参阅panda 可用的频率。
  • n_jobs: n_jobs: int,并行处理中使用的作业数,使用 -1 表示所有核心。

任何设置都会传递给构造函数。然后您调用其 fit 方法并传入历史数据框 df

from statsforecast.models import AutoETS
models = [AutoETS(season_length = 24)]

sf = StatsForecast(
    models = models, 
    freq = 1, 
    n_jobs = 1
)

执行时间序列交叉验证

StatsForecast 对象实例化后,我们可以使用 cross_validation 方法,该方法接受以下参数:

  • df: 采用 StatsForecast 格式的训练数据框
  • h (int): 表示将预测的未来 h 步长
  • step_size (int): 每个窗口之间的步长,表示您希望多久运行一次预测过程。
  • n_windows (int): 用于交叉验证的窗口数量,表示您希望评估过去预测过程的数量。

对于本示例,我们将使用 3 个 24 小时的窗口。

cv_df = sf.cross_validation(
    df = df,
    h = 24,
    step_size = 24,
    n_windows = 3
  )

cv_df 对象是一个新的数据框,包含以下列:

  • unique_id: 时间序列标识符
  • ds: 日期戳或时间索引
  • cutoff: n_windows 的最后一个日期戳或时间索引。
  • y: 真实值
  • "model": 包含模型名称和拟合值的列。
cv_df.head()
unique_iddscutoffyAutoETS
0H1677676691.0677.761053
1H1678676618.0607.817879
2H1679676563.0569.437729
3H1680676529.0537.340007
4H1681676504.0515.571123

现在我们将绘制每个截止周期的预测结果。为了使图表更清晰,我们将重命名每个周期中的实际值。

from IPython.display import display
cv_df.rename(columns = {'y' : 'actual'}, inplace = True) # rename actual values 

cutoff = cv_df['cutoff'].unique()

for k in range(len(cutoff)): 
    cv = cv_df[cv_df['cutoff'] == cutoff[k]]
    display(StatsForecast.plot(df, cv.loc[:, cv.columns != 'cutoff']))

请注意,在每个截止周期中,我们仅使用该周期之前的数据 y 生成了未来 24 小时的预测结果。

评估结果

现在我们可以使用适当的准确性指标计算预测的准确性。这里我们将使用均方根误差 (RMSE)。

from utilsforecast.losses import rmse

计算 RMSE 的函数接受两个参数:

  1. 实际值。
  2. 预测值,在本例中为 AutoETS
cv_rmse = rmse(cv_df, models=['AutoETS'], target_col='actual')['AutoETS'].item()
print(f"RMSE using cross-validation: {cv_rmse:.2f}")
RMSE using cross-validation: 33.90

此度量标准应能更好地反映我们模型的预测能力,因为它使用了不同的时间段来测试其准确性。

提示

交叉验证在比较多个模型时特别有用。这里有一个包含多个模型和时间序列的示例

参考文献

Rob J. Hyndman 和 George Athanasopoulos (2018)。“预测原理与实践,时间序列交叉验证”.