预测领域在基础模型领域开展了大量活动,自 2024 年初以来就提出了Lag-LLaMA 、Time-LLM 、Chronos和 Moirai 等模型。
然而,它们的性能有点令人印象深刻(对于可重复的基准,请参见此处 ),并且我相信特定于数据的模型仍然是目前的最佳解决方案。
为此,Transformer 架构已以多种形式应用于时间序列预测,其中PatchTST 实现了长期预测的最先进性能。
具有挑战性的 PatchTST 是iTransformer 模型,该模型于 2024 年 3 月在论文iTransformer:Inverted Transformers Are effective for Time Series Forecasting 中提出。
在本文中,我们发现 iTransformer 背后极其简单的概念并探索其架构。然后,我们将该模型应用到一个小型实验中,并将其性能与TSMixer 、N-HiTS 和 PatchTST 进行比较。
欲了解更多详细信息,请务必阅读原始论文 。
让我们开始吧!
iTransformer 背后的想法来自于对普通 Transformer 模型使用时间_标记_的认识。
这意味着该模型会在单个时间步长中查看所有特征。因此,模型在一次查看一个时间步骤时学习时间依赖性是一项挑战。
该问题的解决方案是修补,这是通过 PatchTST 模型提出的。通过修补,我们只需将时间点分组在一起,然后再对其进行标记和嵌入,如下所示。
可视化修补。在这里,我们有一个包含 15 个时间步长的序列,补丁长度为 5,步幅也为 5,从而产生三个补丁。图片由作者提供。
在 iTransformer 中,我们通过简单地将模型应用到反转维度上,将修补推向了极致。
iTransformer应用在系列的倒立形状上。这样,跨时间的整个功能就被标记化和嵌入了。图片由 Y. Liu、T. Hu、H. Zhang、H. Wu、S. Wang、L. Ma、M. Long 提供,来自iTransformer:反向变压器对于时间序列预测非常有效 。
在上图中,我们可以看到 iTransformer 与普通 Transformer 的不同之处。它不是在一个时间步长中查看所有特征,而是在多个时间步长中查看一个特征。这只需通过反转输入的形状即可完成。
这样,注意力层可以学习多元相关性,前馈网络对整个输入序列的表示进行编码。
现在我们已经掌握了 iTransformer 背后的总体思路,让我们更详细地了解一下它的架构。
iTransformer 采用带有嵌入、投影和 Transformer 块的普通编码器-解码器架构,最初是在 2017 年的开创性论文《Attention Is All You Need》 中提出的。
iTransformer 的架构。图片由 Y. Liu、T. Hu、H. Zhang、H. Wu、S. Wang、L. Ma、M. Long 提供,来自iTransformer:反向变压器对于时间序列预测非常有效 。
从上图中我们可以看出,构建块是相同的,但功能却完全不同。让我们仔细看看。
嵌入层
首先,输入序列作为标记独立嵌入。同样,这就像修补的极端情况,模型不是对输入的子序列进行标记,而是对整个输入序列进行标记。
多变量注意力
然后,嵌入被发送到注意力层,在那里它将学习多元相关图。
这是可能的,因为倒置模型将每个特征视为一个独立的过程。因此,注意力机制可以学习特征对之间的相关性,使 iTransformer 特别适合多元预测任务。
层归一化
注意力层的输出被发送到归一化层。
在传统的 Transformer 架构中,所有特征都在固定的时间戳上完成归一化。这可能会引入交互噪声,这意味着模型正在学习无用的关系。另外,它可能会导致信号过于平滑。
相比之下,由于 iTransformer 反转了维度,因此标准化是跨时间戳完成的。这有助于模型处理非平稳序列,并减少序列中的噪声。
前馈网络
最后,前馈网络(FFN)学习传入令牌的深度表示。
同样,由于形状是倒置的,多层感知器 (MLP) 可以学习不同的时间属性,例如周期性和幅度。这模仿了基于 MLP 的模型的功能,例如N-BEATS 、N-HiTS 和 TSMixer。
投影
从这里开始,只需堆叠许多由以下组成的块即可:
每个块学习输入序列的不同表示。然后,通过线性投影步骤发送块堆栈的输出以获得最终预测。
综上所述,iTransformer 并不是一个新的架构;它并没有重新发明变压器。它只是将其应用于输入的反转维度,这使得模型能够学习多元相关性并捕获时间属性。
现在我们对 iTransformer 模型有了深入的了解,让我们将其应用到一个小型的预测实验中。
对于这个小实验,我们在 Creative Commons 许可下发布的Electricity Transformer 数据集 上应用了 iTransformer 模型。
这是一个流行的基准数据集,用于跟踪中国一个省两个地区的电力变压器的油温。对于这两个区域,我们每小时和每 15 分钟采样一个数据集,总共四个数据集。
虽然 iTransformer 本质上是一个多变量模型,但我们在 96 个时间步长的范围内测试其单变量预测能力。
此实验的代码可在GitHub 上找到。
让我们开始吧!
初始设置
_在这个实验中,我们使用了Neuralforecast_库,因为我相信它提供了深度学习方法最快、最直观的即用型实现。
1 2 3 4 5 6 import pandas as pd import numpy as np import matplotlib.pyplot as plt from datasetsforecast.long_horizon import LongHorizon from neuralforecast.core import NeuralForecast from neuralforecast.models import NHITS, PatchTST, iTransformer, TSMixer
请注意,在撰写本文时,iTransformer 尚未在Neuralforecast_的_公开版本中提供。要立即访问模型,您可以运行:
pip install git+https://github.com/Nixtla/neuralforecast.git
现在,让我们编写一个函数来加载 ETT 数据集及其验证大小、测试大小和频率。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 def load_data (name ): if name == "ettm1" : Y_df, *_ = LongHorizon.load(directory='./' , group='ETTm1' ) Y_df = Y_df[Y_df['unique_id' ] == 'OT' ] Y_df['ds' ] = pd.to_datetime(Y_df['ds' ]) val_size = 11520 test_size = 11520 freq = '15T' elif name == "ettm2" : Y_df, *_ = LongHorizon.load(directory='./' , group='ETTm2' ) Y_df = Y_df[Y_df['unique_id' ] == 'OT' ] Y_df['ds' ] = pd.to_datetime(Y_df['ds' ]) val_size = 11520 test_size = 11520 freq = '15T' elif name == 'etth1' : Y_df, *_ = LongHorizon.load(directory='./' , group='ETTh1' ) Y_df['ds' ] = pd.to_datetime(Y_df['ds' ]) val_size = 2880 test_size = 2880 freq = 'H' elif name == "etth2" : Y_df, *_ = LongHorizon.load(directory='./' , group='ETTh2' ) Y_df['ds' ] = pd.to_datetime(Y_df['ds' ]) val_size = 2880 test_size = 2880 freq = 'H' return Y_df, val_size, test_size, freq
_上面的函数可以方便地以Neuroforecast_期望的格式加载数据,其中我们有一个unique_id用于标记唯一时间序列的列,一个ds用于时间戳的列,以及一个y包含我们的序列值的列。
另请注意,验证和测试规模与科学界在发表论文时使用的一致。
我们现在准备好训练模型了。
训练和预测 要训练 iTransformer 模型,我们只需指定:
请记住,iTransformer 本质上是一个多元模型,这就是为什么我们在拟合模型时需要指定系列数。
由于我们处于单变量场景,n_series=1.
1 2 3 4 5 iTransformer(h=horizon, input_size=3 *horizon, n_series=1 , max_steps=1000 , early_stop_patience_steps=3 )
在上面的代码块中,我们还指定了最大训练步骤数,并将提前停止设置为三次迭代以避免过度拟合。
然后我们对其他模型执行相同的操作,并将它们放入列表中。
1 2 3 4 5 6 7 8 horizon = 96 models = [ iTransformer(h=horizon, input_size=3 *horizon, n_series=1 , max_steps=1000 , early_stop_patience_steps=3 ), TSMixer(h=horizon, input_size=3 *horizon, n_series=1 , max_steps=1000 , early_stop_patience_steps=3 ), NHITS(h=horizon, input_size=3 *horizon, max_steps=1000 , early_stop_patience_steps=3 ), PatchTST(h=horizon, input_size=3 *horizon, max_steps=1000 , early_stop_patience_steps=3 ) ]
伟大的!现在,我们只需初始化该NeuralForecast对象即可访问训练、交叉验证和预测的方法。
1 2 nf = NeuralForecast(models=models, freq=freq) nf_preds = nf.cross_validation(df=Y_df, val_size=val_size, test_size=test_size, n_windows=None )
最后,我们使用该库评估每个模型的性能utilsforecast。
1 2 3 4 5 from utilsforecast.losses import mae, msefrom utilsforecast.evaluation import evaluateettm1_evaluation = evaluate(df=nf_preds, metrics=[mae, mse], models=['iTransformer' , 'TSMixer' , 'NHITS' , 'PatchTST' ]) ettm1_evaluation.to_csv('ettm1_results.csv' , index=False , header=True )
然后对所有数据集重复这些步骤。运行该实验的完整函数如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from utilsforecast.losses import mae, msefrom utilsforecast.evaluation import evaluatedatasets = ['ettm1' , 'ettm2' , 'etth1' , 'etth2' ] for dataset in datasets: Y_df, val_size, test_size, freq = load_data(dataset) horizon = 96 models = [ iTransformer(h=horizon, input_size=3 *horizon, n_series=1 , max_steps=1000 , early_stop_patience_steps=3 ), TSMixer(h=horizon, input_size=3 *horizon, n_series=1 , max_steps=1000 , early_stop_patience_steps=3 ), NHITS(h=horizon, input_size=3 *horizon, max_steps=1000 , early_stop_patience_steps=3 ), PatchTST(h=horizon, input_size=3 *horizon, max_steps=1000 , early_stop_patience_steps=3 ) ] nf = NeuralForecast(models=models, freq=freq) nf_preds = nf.cross_validation(df=Y_df, val_size=val_size, test_size=test_size, n_windows=None ) nf_preds = nf_preds.reset_index() evaluation = evaluate(df=nf_preds, metrics=[mae, mse], models=['iTransformer' , 'TSMixer' , 'NHITS' , 'PatchTST' ]) evaluation.to_csv(f'{dataset} _results.csv' , index=False , header=True )
一旦运行完成,我们就可以从所有数据集上的所有模型中获得预测。然后我们可以继续进行评估。
绩效评估 _由于我们将所有性能指标保存在 CSV 文件中,因此我们可以使用pandas_读取它们并绘制每个数据集的每个模型的性能。
1 2 3 4 5 6 7 8 9 10 11 12 13 files = ['etth1_results.csv' , 'etth2_results.csv' , 'ettm1_results.csv' , 'ettm2_results.csv' ] datasets = ['etth1' , 'etth2' , 'ettm1' , 'ettm2' ] dataframes = [] for file, dataset in zip (files, datasets): df = pd.read_csv(file) df['dataset' ] = dataset dataframes.append(df) full_df = pd.concat(dataframes, ignore_index=True ) full_df = full_df.drop(['unique_id' ], axis=1 )
然后,绘制指标:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import matplotlib.pyplot as pltimport numpy as npdataset_names = full_df['dataset' ].unique() model_names = ['iTransformer' , 'TSMixer' , 'NHITS' , 'PatchTST' ] fig, axs = plt.subplots(2 , 2 , figsize=(15 , 15 )) bar_width = 0.35 axs = axs.flatten() for i, dataset_name in enumerate (dataset_names): df_subset = full_df[(full_df['dataset' ] == dataset_name) & (full_df['metric' ] == 'mae' )] mae_vals = df_subset[model_names].values.flatten() df_subset = full_df[(full_df['dataset' ] == dataset_name) & (full_df['metric' ] == 'mse' )] mse_vals = df_subset[model_names].values.flatten() indices = np.arange(len (model_names)) bars_mae = axs[i].bar(indices - bar_width / 2 , mae_vals, bar_width, color='skyblue' , label='MAE' ) bars_mse = axs[i].bar(indices + bar_width / 2 , mse_vals, bar_width, color='orange' , label='MSE' ) for bars in [bars_mae, bars_mse]: for bar in bars: height = bar.get_height() axs[i].annotate(f'{height:.2 f} ' , xy=(bar.get_x() + bar.get_width() / 2 , height), xytext=(0 , 3 ), textcoords="offset points" , ha='center' , va='bottom' ) axs[i].set_xticks(indices) axs[i].set_xticklabels(model_names, rotation=45 ) axs[i].set_title(dataset_name) axs[i].legend(loc='best' ) plt.tight_layout()
来自 ETT 数据集上所有模型的 MAE 和 MSE,范围为 96 个时间步长。图片由作者提供。
从上图可以看出,iTransformer 在所有数据集上的表现都相当不错,但 TSMixer 整体略好于 iTransformer,PatchTST 是本次实验中整体冠军模型。
当然,请记住,我们没有利用 iTransformer 的多变量功能,并且我们仅在单个预测范围内进行测试。因此,它并不是对 iTransformer 性能的完整评估。
尽管如此,有趣的是看到该模型的表现与 PatchTST 非常接近,这进一步支持了这样的想法:在使用 Transformer 进行时间序列预测时,在标记化之前将时间步分组在一起可以解锁新的性能高度。
结论 iTransformer 采用普通 Transformer 架构,并将其简单地应用于输入序列的反转形状。
这样,整个系列就被标记化了,这模仿了 PatchTST 中提出的修补的极端情况。
这使得模型能够使用其注意力机制来学习多元相关性,而前馈网络则学习序列的时间属性。
尽管在我们有限的实验中,PatchTST 的整体表现最好,但 iTransformer 在许多基准数据集上的长期预测中表现出了最先进的性能。
我坚信每个问题都需要其独特的解决方案,现在您可以将 iTransformer 添加到您的工具箱并将其应用到您的项目中。
谢谢阅读!我希望您喜欢它并学到新东西!