使用TFT进行预测:时间融合变换器

时间融合变换器(TFT)由Lim等人提出,是一种用于时间序列预测的最流行的基于变换器的模型之一。总之,TFT将门控层、LSTM递归编码器与多头注意力层结合,用于多步预测策略的解码器。有关Nixtla的TFT实现的更多详细信息,请访问这个链接

在这个笔记本中,我们展示了如何在德克萨斯州电力市场负载数据(ERCOT)上训练TFT模型。准确预测电力市场非常重要,因为这对规划分配和消费非常有用。

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

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

在Colab中打开

1. 库

%%capture
!pip install neuralforecast
import torch
import numpy as np
import pandas as pd
torch.cuda.is_available()
True

2. 加载ERCOT数据

NeuralForecast的输入始终是一个具有三列的长格式的数据框:unique_iddsy

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

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

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

我们将重命名这个数据框。

首先,读取2022年ERCOT市场的历史总需求数据。我们对原始数据进行了处理(可在这里获取),通过添加因夏令时缺失的小时,解析日期为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_id ds y
0 ERCOT 2021-01-01 00:00:00 43719.849616
1 ERCOT 2021-01-01 01:00:00 43321.050347
2 ERCOT 2021-01-01 02:00:00 43063.067063
3 ERCOT 2021-01-01 03:00:00 43090.059203
4 ERCOT 2021-01-01 04:00:00 43486.590073

3. 模型训练与预测

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

要实例化 AutoTFT,您需要定义:

  • h:预测时间范围
  • loss:训练损失
  • config:超参数搜索空间。如果为 NoneAutoTFT 类将使用预定义的建议超参数空间。
  • 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)
Tip

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

使用 num_samples=3,此示例的运行时间应在约 20 分钟左右。

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

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

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

以下是所有配置参数:

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类具有内置方法,可以简化预测管道,例如fitpredictcross_validation。使用以下必需参数实例化NeuralForecast对象:

  • models: 模型列表。

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

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

%%capture
nf = NeuralForecast(
    models=models,
    freq='H')

nf.fit(df=Y_df)

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

Y_hat_df = nf.predict()
Y_hat_df.head()
ds AutoTFT
unique_id
ERCOT 2022-10-01 00:00:00 38644.019531
ERCOT 2022-10-01 01:00:00 36833.121094
ERCOT 2022-10-01 02:00:00 35698.265625
ERCOT 2022-10-01 03:00:00 35065.148438
ERCOT 2022-10-01 04:00:00 34788.566406

使用matplotlib绘制结果

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') # 连接训练和预测数据框
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,以便一天只生成一个预测。

%%capture
val_size  = 90*24 # 90天 x 24小时
test_size = 30*24 # 30天 x 24小时
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模型的表现比最新的变换器高出20%以上,而计算量减少了50倍。

本教程中学习如何使用N-HiTS和NeuralForecast库。

参考文献

[1] Lim, B., Arık, S. Ö., Loeff, N., & Pfister, T. (2021). 可解释的多时期时间序列预测的时间融合变换器。《国际预测期刊》,37(4),1748-1764。

[2] Cristian Challu, Kin G. Olivares, Boris N. Oreshkin, Federico Garza, Max Mergenthaler-Canseco, Artur Dubrawski (2021). N-HiTS:用于时间序列预测的神经层次插值。被AAAI 2023接受。

Give us a ⭐ on Github