Temporal Fusion Transformer (TFT) 模型由 Lim 等人 [1] 提出,是时间序列预测中最流行的基于 Transformer 的模型之一。总而言之,TFT 结合了门控层、LSTM 循环编码器以及多头注意力层,用于多步预测策略的解码器。有关 Nixtla 的 TFT 实现的更多详细信息,请访问此链接

在本 Notebook 中,我们将展示如何在德州电力市场负荷数据 (ERCOT) 上训练 TFT 模型。准确预测电力市场具有重要意义,因为它对于规划电力分配和消费非常有用。

我们将向您展示如何加载数据、训练 TFT 并进行自动超参数调整以及生成预测。然后,我们将向您展示如何执行多次历史预测以进行交叉验证。

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

1. 库

!pip install neuralforecast
import pandas as pd

2. 加载 ERCOT 数据

NeuralForecast 的输入始终是一个采用长格式的数据框,包含三列:unique_iddsy

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

  • ds(日期戳或整数)列应为索引时间的整数,或理想情况下为 YYYY-MM-DD 格式的日期戳或 YYYY-MM-DD HH:MM:SS 格式的时间戳。

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

首先,读取 ERCOT 市场的 2022 年历史总需求数据。我们处理了原始数据(可在此处获取),通过添加因夏令时缺失的小时数据,将日期解析为 datetime 格式,并筛选出感兴趣的列。

Y_df = pd.read_csv('https://datasets-nixtla.s3.amazonaws.com/ERCOT-clean.csv')
Y_df['ds'] = pd.to_datetime(Y_df['ds'])
Y_df.head()
unique_iddsy
0ERCOT2021-01-01 00:00:0043719.849616
1ERCOT2021-01-01 01:00:0043321.050347
2ERCOT2021-01-01 02:00:0043063.067063
3ERCOT2021-01-01 03:00:0043090.059203
4ERCOT2021-01-01 04:00:0043486.590073

3. 模型训练和预测

首先,实例化 AutoTFT 模型。 AutoTFT 类将使用 Tune 库自动执行超参数调优,探索用户定义或默认的搜索空间。模型根据在验证集上的误差进行选择,然后存储最佳模型并在推理时使用。

要实例化 AutoTFT,您需要定义

  • h: 预测范围
  • loss: 训练损失
  • config: 超参数搜索空间。如果为 None,则 AutoTFT 类将使用预定义的建议超参数空间。
  • num_samples: 探索的配置数量。
from ray import tune

from neuralforecast.auto import AutoTFT
from neuralforecast.core import NeuralForecast
from neuralforecast.losses.pytorch import MAE

import logging
logging.getLogger("pytorch_lightning").setLevel(logging.WARNING)

提示

增加 num_samples 参数以探索所选模型的更广泛配置集。根据经验法则,选择大于 15 的值。

num_samples=3 时,此示例应在约 20 分钟内运行完成。

horizon = 24
models = [AutoTFT(h=horizon,
                  loss=MAE(),
                  config=None,
                  num_samples=3)]

提示

我们所有的模型都可以用于点预测和概率预测。要生成概率输出,只需将损失函数修改为我们的 DistributionLoss 之一。完整的损失函数列表可在此链接中找到

重要提示

TFT 是一个非常大的模型,可能需要大量内存!如果您遇到 GPU 内存不足的问题,请尝试声明您的配置搜索空间并减小 hidden_sizen_headswindows_batch_size 参数。

这些是 config 的所有参数

config = {
      "input_size": tune.choice([horizon]),
      "hidden_size": tune.choice([32]),
      "n_head": tune.choice([2]),
      "learning_rate": tune.loguniform(1e-4, 1e-1),
      "scaler_type": tune.choice(['robust', 'standard']),
      "max_steps": tune.choice([500, 1000]),
      "windows_batch_size": tune.choice([32]),
      "check_val_every_n_epoch": tune.choice([100]),
      "random_seed": tune.randint(1, 20),
}

NeuralForecast 类具有内置方法来简化预测流程,例如 fitpreditcross_validation。使用以下必需参数实例化一个 NeuralForecast 对象

然后,使用 fit 方法在 ERCOT 数据上训练 AutoTFT 模型。总训练时间将取决于硬件和探索的配置,应在 10 到 30 分钟之间。

nf = NeuralForecast(
    models=models,
    freq='h')

nf.fit(df=Y_df)

最后,使用 predict 方法预测训练数据后未来 24 小时的数据并绘制预测结果。

Y_hat_df = nf.predict()
Y_hat_df.head()
c:\Users\ospra\miniconda3\envs\neuralforecast\lib\site-packages\utilsforecast\processing.py:384: FutureWarning: 'H' is deprecated and will be removed in a future version, please use 'h' instead.
  freq = pd.tseries.frequencies.to_offset(freq)
c:\Users\ospra\miniconda3\envs\neuralforecast\lib\site-packages\utilsforecast\processing.py:440: FutureWarning: 'H' is deprecated and will be removed in a future version, please use 'h' instead.
  freq = pd.tseries.frequencies.to_offset(freq)
Predicting: |          | 0/? [00:00<?, ?it/s]
unique_iddsAutoTFT
0ERCOT2022-10-01 00:00:0038600.757812
1ERCOT2022-10-01 01:00:0036871.199219
2ERCOT2022-10-01 02:00:0035505.500000
3ERCOT2022-10-01 03:00:0034781.691406
4ERCOT2022-10-01 04:00:0034647.484375

使用 matplot lib 绘制结果

import matplotlib.pyplot as plt

fig, ax = plt.subplots(1, 1, figsize = (10, 3))
plot_df = pd.concat([Y_df.tail(24*5).reset_index(drop=True), Y_hat_df]).set_index('ds') # Concatenate the train and forecast dataframes
plot_df[['y', 'AutoTFT']].plot(ax=ax, linewidth=2)

ax.set_title('Load [MW]', fontsize=12)
ax.set_ylabel('Monthly Passengers', fontsize=12)
ax.set_xlabel('Date', fontsize=12)
ax.legend(prop={'size': 10})
ax.grid()

4. 对多次历史预测进行交叉验证

cross_validation 方法允许您模拟多次历史预测,通过用 fitpredict 方法替换 for 循环来大大简化流程。请参阅此教程以查看如何定义窗口的动画演示。

对于时间序列数据,交叉验证是通过在历史数据上定义一个滑动窗口并预测其后续周期来完成的。这种形式的交叉验证使我们能够在更广泛的时间实例范围内更好地估计模型的预测能力,同时保持训练集中的数据是连续的,这是我们的模型所要求的。cross_validation 方法将使用验证集进行超参数选择,然后为测试集生成预测结果。

使用 cross_validation 方法生成九月份的所有每日预测。设置验证集和测试集的大小。要生成每日预测,请将窗口之间的步长设置为 24,以便每天只生成一个预测。

val_size  = 90*24 # 90 days x 24 hours
test_size = 30*24 # 30 days x 24 hours
fcst_df = nf.cross_validation(df=Y_df, val_size=val_size, test_size=test_size,
                                n_windows=None, step_size=horizon)

最后,我们将预测结果与 Y_df 数据集合并并绘制预测图。

Y_hat_df = fcst_df.reset_index(drop=True)
Y_hat_df = Y_hat_df.drop(columns=['y','cutoff'])
plot_df = Y_df.merge(Y_hat_df, on=['unique_id','ds'], how='outer').tail(test_size+24*7)

plt.figure(figsize=(20,5))
plt.plot(plot_df['ds'], plot_df['y'], c='black', label='True')
plt.plot(plot_df['ds'], plot_df['AutoTFT'], c='blue', label='Forecast')
plt.axvline(pd.to_datetime('2022-09-01'), color='red', linestyle='-.')
plt.legend()
plt.grid()
plt.plot()

后续步骤

在 Challu 等人 [2] 的工作中,我们证明 N-HiTS 模型以少 50 倍的计算量,性能优于最新的 Transformer 模型 20% 以上。

在此教程中了解如何使用 N-HiTS 和 NeuralForecast 库。

参考文献

[1] Lim, B., Arık, S. Ö., Loeff, N., & Pfister, T. (2021). Temporal fusion transformers for interpretable multi-horizon time series forecasting. International Journal of Forecasting, 37(4), 1748-1764..

[2] Cristian Challu, Kin G. Olivares, Boris N. Oreshkin, Federico Garza, Max Mergenthaler-Canseco, Artur Dubrawski (2021). N-HiTS: Neural Hierarchical Interpolation for Time Series Forecasting. Accepted at AAAI 2023.