数据

我们将使用 Walmart 提供的M5 竞赛数据集。该数据集的有趣之处在于其规模庞大,并且包含许多发生频率较低的时间序列。这类时间序列在零售场景中很常见,传统的时间序列预测技术很难处理。

数据可从以下 URL 下载

  • 训练集:https://m5-benchmarks.s3.amazonaws.com/data/train/target.parquet
  • 时间外部变量(供 AmazonForecast 使用):https://m5-benchmarks.s3.amazonaws.com/data/train/temporal.parquet
  • 静态外部变量(供 AmazonForecast 使用):https://m5-benchmarks.s3.amazonaws.com/data/train/static.parquet

有关数据的更详细描述,请参见此处

警告

M5 竞赛具有层级结构。也就是说,需要针对不同聚合级别(国家、州、商店等)进行预测。在本实验中,我们仅使用底层数据生成预测。评估通过自下而上的协调方法进行,以获得更高层级的预测。

Amazon Forecast

Amazon Forecast 是一个全自动时间序列预测解决方案。该解决方案可以接收待预测的时间序列和外部变量(时间性和静态性)。在本实验中,我们按照本教程的步骤使用了 Amazon Forecast 的 AutoPredict 功能。关于该数据集的具体步骤的详细描述,请参见此处

Amazon Forecast 使用 AutoPredictor 创建预测器,它会将最优算法组合应用于数据集中每个时间序列。预测器是 Amazon Forecast 模型,使用您的目标时间序列、相关时间序列、项目元数据以及您包含的任何其他数据集进行训练。

包含的算法范围广泛,从常用的统计算法(如自回归积分移动平均 (ARIMA))到复杂的神经网络算法(如 CNN-QR 和 DeepAR+)。包括:CNN-QR、DeepAR+、Prophet、NPTS、ARIMA 和 ETS。

为了利用 Amazon Forecast 的概率特性并启用置信区间进行进一步分析,我们预测了以下分位数:0.1 | 0.5 | 0.9。

Amazon Forecast 的完整管道耗时 4.1 小时,结果可在以下位置找到:s3://m5-benchmarks/forecasts/amazonforecast-m5.parquet

Nixtla 的 StatsForecast

安装必要的库

我们假设您已经安装了 StatsForecast。有关如何安装 StatsForecast的说明,请参阅本指南。

此外,我们将安装 s3fs 以从 AWS 的 S3 文件系统读取数据。(如果您不想使用云存储提供商,可以使用 pandas 在本地读取文件)

!pip install statsforecast s3fs

输入格式

我们将使用 pandas 读取存储在 parquet 文件中的数据集以提高效率。您可以使用普通的 pandas 操作读取 .csv 等其他格式的数据。

StatsForecast 的输入始终是长格式的数据帧,包含三列:unique_iddsy

  • unique_id(字符串、整数或类别)表示序列的标识符。

  • ds(日期戳)列应采用 Pandas 期望的格式,日期格式最好是 YYYY-MM-DD,时间戳格式最好是 YYYY-MM-DD HH:MM:SS。

  • y(数值型)表示我们希望预测的测量值。我们将重命名

因此,我们将重命名原始列,使其与 StatsForecast 兼容。

根据您的互联网连接速度,此步骤大约需要 20 秒。

警告

我们正在从 S3 读取文件,因此您需要安装 s3fs 库。要安装它,请运行 ! pip install s3fs

读取数据

import pandas as pd

Y_df_m5 = pd.read_parquet('https://m5-benchmarks.s3.amazonaws.com/data/train/target.parquet') 

Y_df_m5 = Y_df_m5.rename(columns={
    'item_id': 'unique_id', 
    'timestamp': 'ds', 
    'demand': 'y'
}) 

Y_df_m5.head()
unique_iddsy
0FOODS_1_001_CA_12011-01-293.0
1FOODS_1_001_CA_12011-01-300.0
2FOODS_1_001_CA_12011-01-310.0
3FOODS_1_001_CA_12011-02-011.0
4FOODS_1_001_CA_12011-02-024.0

训练统计模型

我们通过实例化一个新的 StatsForecast 对象并传入以下参数来拟合模型:

  • models: 模型列表。从模型中选择您想要的模型并导入。在本例中,我们将使用AutoETSDynamicOptimizedTheta。我们将 season_length 设置为 7,因为我们期望每周都有季节性效应。(参见:季节周期

  • freq: 一个字符串,指示数据的频率。(参见 pandas 可用的频率。)

  • n_jobs: n_jobs: int,并行处理中使用的作业数量,使用 -1 表示所有核心。

  • fallback_model: 如果某个模型失败时使用的备用模型。

任何设置都通过构造函数传入。然后调用其 fit 方法并传入历史数据帧。

注意

StatsForecast 通过 Numba 进行 JIT 编译实现极快的速度。第一次调用 statsforecast 类时,fit 方法大约需要 5 秒。第二次——一旦 Numba 编译了您的设置——应该不到 0.2 秒。

from statsforecast import StatsForecast
from statsforecast.models import (
    AutoETS,
    DynamicOptimizedTheta,
    SeasonalNaive
)

# Create list of models
models = [
    AutoETS(season_length=7),
    DynamicOptimizedTheta(season_length=7),
]

# Instantiate StatsForecast class
sf = StatsForecast( 
    models=models,
    freq='D', 
    n_jobs=-1,
    fallback_model=SeasonalNaive(season_length=7)
)
/home/ubuntu/fede/statsforecast/statsforecast/core.py:21: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)
  from tqdm.autonotebook import tqdm

forecast 方法接受两个参数:预测接下来的 h 步(horizon)和 level

  • h (int): 表示未来 h 步的预测。在本例中,是未来 12 个月。

  • level (list of floats): 此可选参数用于概率预测。设置预测区间的 level(或置信度百分位数)。例如,level=[90] 意味着模型期望实际值在 90% 的时间内落在此区间内。

这里的预测对象是一个新的数据帧,包含模型的名称列、y hat 值列以及不确定性区间的列。

注意

forecast 方法旨在与分布式集群兼容,因此它不存储任何模型参数。如果您想为每个模型存储参数,可以使用 fitpredict 方法。但是,这些方法并未为 Spark、Ray 或 Dask 等分布式引擎定义。

from time import time
init = time()
forecasts_df = sf.forecast(df=Y_df_m5, h=28)
end = time()
print(f'Statsforecast time M5 {(end - init) / 60}')
Statsforecast time M5 14.274124479293823

存储结果以进行进一步评估。

forecasts_df['ThETS'] = forecasts_df[['DynamicOptimizedTheta', 'AutoETS']].clip(0).median(axis=1, numeric_only=True)
forecasts_df.to_parquet('s3://m5-benchmarks/forecasts/statsforecast-m5.parquet')

评估

本节评估 StatsForecastAmazonForecast 的性能。为此,我们首先需要安装 datasetsforecast,这是一个由 Nixtla 开发的 Python 库,包含大量基准数据集和评估工具。该库将使我们能够使用竞赛中使用的原始评估方法计算模型的性能。

!pip install datasetsforecast
from datasetsforecast.m5 import M5, M5Evaluation

以下函数将允许我们评估输入数据帧中包含的特定模型。该函数对于评估不同模型很有用。

from datasetsforecast.m5 import M5, M5Evaluation
from statsforecast import StatsForecast

### Evaluator
def evaluate_forecasts(df, model, model_name):
    Y_hat = df.set_index('ds', append=True)[model].unstack()
    *_, S_df = M5.load('data')
    Y_hat = S_df.merge(Y_hat, how='left', on=['unique_id'])
    eval_ = M5Evaluation.evaluate(y_hat=Y_hat, directory='./data')
    eval_ = eval_.rename(columns={'wrmsse': f'{model_name}_{model}_wrmsse'})
    return eval_

现在让我们读取为每个解决方案生成的预测。

### Read Forecasts
statsforecasts_df = pd.read_parquet('s3://m5-benchmarks/forecasts/statsforecast-m5.parquet')
amazonforecasts_df = pd.read_parquet('s3://m5-benchmarks/forecasts/amazonforecast-m5.parquet')

### Amazon Forecast wrangling
amazonforecasts_df = amazonforecasts_df.rename(columns={'item_id': 'unique_id', 'date': 'ds'})
# amazon forecast returns the unique_id column in lower case
# we need to transform it to upper case to ensure proper merging
amazonforecasts_df['unique_id'] = amazonforecasts_df['unique_id'].str.upper()
amazonforecasts_df = amazonforecasts_df.set_index('unique_id')
# parse datestamp
amazonforecasts_df['ds'] = pd.to_datetime(amazonforecasts_df['ds']).dt.tz_localize(None)

最后,让我们使用预定义的函数计算每个模型的性能。

### Evaluate performances
m5_eval_df = pd.concat([
    evaluate_forecasts(statsforecasts_df, 'ThETS', 'StatsForecast'),
    evaluate_forecasts(statsforecasts_df, 'AutoETS', 'StatsForecast'),
    evaluate_forecasts(statsforecasts_df, 'DynamicOptimizedTheta', 'StatsForecast'),
    evaluate_forecasts(amazonforecasts_df, 'p50', 'AmazonForecast'),
], axis=1)
m5_eval_df.T
总计层级 1层级 2层级 3层级 4层级 5层级 6层级 7层级 8层级 9层级 10层级 11层级 12
StatsForecast_ThETS_wrmsse0.6696060.4243310.5157770.5806700.4740980.5524590.5780920.6510790.6424460.7253241.0093900.9675370.914068
StatsForecast_AutoETS_wrmsse0.6724040.4304740.5163400.5807360.4820900.5597210.5799390.6553620.6436380.7279671.0105960.9681680.913820
StatsForecast_DynamicOptimizedTheta_wrmsse0.6753330.4296700.5216400.5892780.4787300.5575200.5842780.6562830.6506130.7317351.0139100.9717580.918576
AmazonForecast_p50_wrmsse1.6178151.9121441.7869911.7363821.9726582.0104981.8059261.8193291.6672251.6192161.1564321.0129420.914040

结果(包括处理时间和成本)可总结在下表中。