外生变量可以提供额外信息,极大地提高预测准确性。一些例子包括用于需求预测的价格或未来促销变量,以及用于电力负荷预测的天气数据。在本笔记本中,我们将展示一个示例,说明如何向 NeuralForecast 模型添加不同类型的外生变量,以便对法国和比利时市场的次日小时电力价格进行预测 (EPF)。

所有 NeuralForecast 模型都能够纳入外生变量来建模以下条件预测分布:P(yt+1:t+H    y[:t],  x[:t](h),  x[:t+H](f),  x(s))\mathbb{P}(\mathbf{y}_{t+1:t+H} \;|\; \mathbf{y}_{[:t]},\; \mathbf{x}^{(h)}_{[:t]},\; \mathbf{x}^{(f)}_{[:t+H]},\; \mathbf{x}^{(s)} )

其中回归量包括静态外生变量 x(s)\mathbf{x}^{(s)},历史外生变量 x[:t](h)\mathbf{x}^{(h)}_{[:t]},预测时可用的外生变量 x[:t+H](f)\mathbf{x}^{(f)}_{[:t+H]} 和自回归特征 y[:t]\mathbf{y}_{[:t]}。根据训练损失,模型输出可以是点预测(位置估计量)或不确定性区间(分位数)。

我们将向您展示如何在数据中包含外生变量,为模型指定变量,以及使用未来外生变量进行预测。

重要

本指南假设您对 NeuralForecast 库有基本了解。有关一个最小示例,请访问入门指南。

您可以使用 Google Colab 的 GPU 运行这些实验。

1. 库

!pip install neuralforecast

2. 加载数据

df 数据框包含用于训练模型的目标变量和外生变量的过去信息。unique_id 列标识市场,ds 包含日期戳,y 表示电价。

将历史和未来时间变量都作为列包含进来。在本例中,我们将系统负荷 (system_load) 作为历史数据添加。对于未来变量,我们包含了电力产量预测 (gen_forecast) 和星期几 (week_day)。电力系统需求和供应都会显著影响价格,将这些变量包含到模型中可以极大地提高性能,如 Olivares et al. (2022) 中所示。

历史变量和未来变量的区别将在后面作为模型的参数进行区分。

import pandas as pd
from utilsforecast.plotting import plot_series
df = pd.read_csv(
    'https://datasets-nixtla.s3.amazonaws.com/EPF_FR_BE.csv',
    parse_dates=['ds'],
)
df.head()
unique_iddsygen_forecastsystem_loadweek_day
0FR2015-01-01 00:00:0053.4876905.074812.03
1FR2015-01-01 01:00:0051.9375492.071469.03
2FR2015-01-01 02:00:0048.7674394.069642.03
3FR2015-01-01 03:00:0042.2772639.066704.03
4FR2015-01-01 04:00:0038.4169347.065051.03

提示

日历变量,例如星期几、月份和年份,对于捕捉长周期季节性非常有用。

plot_series(df)

在单独的 static_df 数据框中添加静态变量。在本例中,我们使用电力市场的独热编码。static_df 必须包含 df 数据框中每个 unique_id 的一个观测(行),并将不同的静态变量作为列。

static_df = pd.read_csv('https://datasets-nixtla.s3.amazonaws.com/EPF_FR_BE_static.csv')
static_df.head()
unique_idmarket_0market_1
0FR10
1BR01

3. 使用外生变量进行训练

我们根据外生变量是否反映建模数据的静态或时间依赖性方面来区分它们。

  • 静态外生变量:静态外生变量为每个时间序列携带不随时间变化的信息。当模型使用全局参数来预测多个时间序列时,这些变量允许在具有相似静态变量水平的时间序列组之间共享信息。静态变量的例子包括区域、产品组等标识符。

  • 历史外生变量:这类时间依赖性外生变量仅限于过去观测到的值。其预测能力取决于格兰杰因果关系,因为其过去值可以提供关于目标变量 y\mathbf{y} 未来值的显著信息。

  • 未来外生变量:与历史外生变量不同,未来外生变量的值在预测时是已知的。例子包括日历变量、天气预报以及可能导致大幅波动(如计划促销)的已知事件。

要向模型添加外生变量,首先在初始化期间将每个变量的名称从之前的数据框指定给相应的模型超参数:futr_exog_listhist_exog_liststat_exog_list。我们还将 horizon 设置为 24 以生成次日小时预测,并将 input_size 设置为使用过去 5 天的数据作为输入。

import logging

from neuralforecast.auto import NHITS, BiTCN
from neuralforecast.core import NeuralForecast
logging.getLogger("pytorch_lightning").setLevel(logging.WARNING)
horizon = 24 # day-ahead daily forecast
models = [NHITS(h = horizon,
                max_steps=100,
                input_size = 5*horizon,
                futr_exog_list = ['gen_forecast', 'week_day'], # <- Future exogenous variables
                hist_exog_list = ['system_load'], # <- Historical exogenous variables
                stat_exog_list = ['market_0', 'market_1'], # <- Static exogenous variables
                scaler_type = 'robust'),
          BiTCN(h = horizon,
                input_size = 5*horizon,
                max_steps=100,
                futr_exog_list = ['gen_forecast', 'week_day'], # <- Future exogenous variables
                hist_exog_list = ['system_load'], # <- Historical exogenous variables
                stat_exog_list = ['market_0', 'market_1'], # <- Static exogenous variables
                scaler_type = 'robust',
                ),                
                ]
Seed set to 1
Seed set to 1

提示

包含外生变量时,务必通过设置 scaler_type 超参数来使用缩放器。缩放器将缩放所有时间特征:目标变量 y、历史变量和未来变量。

重要

确保未来变量和历史变量被正确放置。将历史变量定义为未来变量将导致数据泄漏。

接下来,将数据集作为 fit 方法的 dfstatic_df 输入进行传递。

nf = NeuralForecast(models=models, freq='h')
nf.fit(df=df, static_df=static_df)

4. 使用外生变量进行预测

在预测价格之前,我们需要收集我们想要预测的那一天的未来外生变量。定义一个新的数据框 (futr_df),其中包含 unique_idds 和未来外生变量。无需添加目标变量 y 和历史变量,因为模型不会使用它们。

futr_df = pd.read_csv(
    'https://datasets-nixtla.s3.amazonaws.com/EPF_FR_BE_futr.csv',
    parse_dates=['ds'],
)
futr_df.head()
unique_iddsgen_forecastweek_day
0FR2016-11-01 00:00:0049118.01
1FR2016-11-01 01:00:0047890.01
2FR2016-11-01 02:00:0047158.01
3FR2016-11-01 03:00:0045991.01
4FR2016-11-01 04:00:0045378.01

重要

确保 futr_df 包含整个预测范围的信息。在本例中,我们预测未来 24 小时,因此 futr_df 必须为每个时间序列包含 24 行。

最后,使用 predict 方法预测次日价格。

Y_hat_df = nf.predict(futr_df=futr_df)
Y_hat_df.head()
Predicting: |          | 0/? [00:00<?, ?it/s]
Predicting: |          | 0/? [00:00<?, ?it/s]
unique_iddsNHITSBiTCN
0BE2016-11-01 00:00:0035.29705041.957176
1BE2016-11-01 01:00:0032.35004439.419579
2BE2016-11-01 02:00:0030.09170236.313972
3BE2016-11-01 03:00:0027.31776434.002922
4BE2016-11-01 04:00:0024.31648835.002541
plot_series(df, Y_hat_df, max_insample_length=24*5)

总而言之,要向模型添加外生变量,请确保遵循以下步骤

  1. 将时间外生变量作为列添加到主数据框 (df)。
  2. 使用 static_df 数据框添加静态外生变量。
  3. 在相应的模型超参数中指定每个变量的名称。
  4. 如果模型使用未来外生变量,请将未来数据框 (futr_df) 传递给 predict 方法。

参考文献