SOFTS: 時間序列預測的最新模型以及Python使用示例
近年來,深度學習一直在時間序列預測中追趕著提升樹模型,其中新的架構已經逐漸為最先進的性能設定了新的標準。
這一切都始于2020年的N-BEATS,然后是2022年的NHITS。2023年,PatchTST和TSMixer被提出,最近的iTransformer進一步提高了深度學習預測模型的性能。
這是2024年4月《SOFTS: Efficient Multivariate Time Series Forecasting with Series-Core Fusion》中提出的新模型,采用集中策略來學習不同序列之間的交互,從而在多變量預測任務中獲得最先進的性能。
在本文中,我們詳細探討了SOFTS的體系結構,并介紹新的STar聚合調度(STAD)模塊,該模塊負責學習時間序列之間的交互。然后,我們測試將該模型應用于單變量和多變量預測場景,并與其他模型作為對比。
SOFTS介紹
SOFTS是 Series-cOre Fused Time Series的縮寫,背后的動機來自于長期多元預測對決策至關重要的認識:
首先我們一直研究Transformer的模型,它們試圖通過使用補丁嵌入和通道獨立等技術(如PatchTST)來降低Transformer的復雜性。但是由于通道獨立性,消除了每個序列之間的相互作用,因此可能會忽略預測信息。
iTransformer 通過嵌入整個序列部分地解決了這個問題,并通過注意機制處理它們。但是基于transformer的模型在計算上是復雜的,并且需要更多的時間來訓練非常大的數據集。
另一方面有一些基于mlp的模型。這些模型通常很快,并產生非常強的結果,但當存在許多序列時,它們的性能往往會下降。
所以出現了SOFTS:研究人員建議使用基于mlp的STAD模塊。由于是基于MLP的,所以訓練速度很快。并且STAD模塊,它允許學習每個序列之間的關系,就像注意力機制一樣,但計算效率更高。
SOFTS架構
在上圖中可以看到每個序列都是單獨嵌入的,就像在iTransformer 中一樣。
然后將嵌入發送到STAD模塊。每個序列之間的交互都是集中學習的,然后再分配到各個系列并融合在一起。
最后再通過線性層產生預測。
這個體系結構中有很多東西需要分析,我們下面更詳細地研究每個組件。
1、歸一化與嵌入
首先使用歸一化來校準輸入序列的分布。使用了可逆實例的歸一化(RevIn)。它將數據以單位方差的平均值為中心。然后每個系列分別進行嵌入,就像在iTransformer 模型。
在上圖中我們可以看到,嵌入整個序列就像應用補丁嵌入,其中補丁長度等于輸入序列的長度。
這樣,嵌入就包含了整個序列在所有時間步長的信息。
然后將嵌入式系列發送到STAD模塊。
2、STar Aggregate-Dispatch (STAD)
STAD模塊是soft模型與其他預測方法的真正區別。使用集中式策略來查找所有時間序列之間的相互作用。
嵌入的序列首先通過MLP和池化層,然后將這個學習到的表示連接起來形成核(上圖中的黃色塊表示)。
核構建好了以后就進入了“重復”和“連接”的步驟,在這個步驟中,核表示被分派給每個系列。
MLP和池化層未捕獲的信息還可以通過殘差連接添加到核表示中。然后在融合(fuse)操作的過程中,核表示及其對應系列的殘差都通過MLP層發送。最后的線性層采用STAD模塊的輸出來生成每個序列的最終預測。
與其他捕獲通道交互的方法(如注意力機制)相比,STAD模塊的主要優點之一是它降低了復雜性。
因為STAD模塊具有線性復雜度,而注意力機制具有二次復雜度,這意味著STAD在技術上可以更有效地處理具有多個序列的大型數據集。
下面我們來實際使用SOFTS進行單變量和多變量場景的測試。
使用SOFTS預測
這里,我們使用 Electricity Transformer dataset 數據集。
這個數據集跟蹤了中國某省兩個地區的變壓器油溫。每小時和每15分鐘采樣一個數據集,總共有四個數據集。
我門使用neuralforecast庫中的SOFTS實現,這是官方認可的庫,并且這樣我們可以直接使用和測試不同預測模型的進行對比。
在撰寫本文時,SOFTS還沒有集成在的neuralforecast版本中,所以我們需要使用源代碼進行安裝。
pip install git+https://github.com/Nixtla/neuralforecast.git
然后就是從導入包開始。使用datasetsforecast以所需格式加載數據集,以便使用neuralforecast訓練模型,并使用utilsforecast評估模型的性能。這就是我們使用neuralforecast的原因,因為他都是一套的
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.losses.pytorch import MAE, MSE
from neuralforecast.models import SOFTS, PatchTST, TSMixer, iTransformer
from utilsforecast.losses import mae, mse
from utilsforecast.evaluation import evaluate
編寫一個函數來幫助加載數據集,以及它們的標準測試大小、驗證大小和頻率。
def load_data(name):
if name == "ettm1":
Y_df, *_ = LongHorizon.load(directory='./', group='ETTm1')
Y_df = Y_df[Y_df['unique_id'] == 'OT'] # univariate dataset
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['ds'] = pd.to_datetime(Y_df['ds'])
val_size = 11520
test_size = 11520
freq = '15T'
return Y_df, val_size, test_size, freq
然后就可以對ETTm1數據集進行單變量預測。
1、單變量預測
加載ETTm1數據集,將預測范圍設置為96個時間步長。
可以測試更多的預測長度,但我們這里只使用96。
Y_df, val_size, test_size, freq = load_data('ettm1')
horizon = 96
然后初始化不同的模型,我們將soft與TSMixer, iTransformer和PatchTST進行比較。
所有模型都使用的默認配置將最大訓練步數設置為1000,如果三次后驗證損失沒有改善,則停止訓練。
models = [
SOFTS(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),
iTransformer(h=horizon, input_size=3*horizon, n_series=1, max_steps=1000, early_stop_patience_steps=3),
PatchTST(h=horizon, input_size=3*horizon, max_steps=1000, early_stop_patience_steps=3)
]
然后初始化NeuralForecast對象訓練模型。并使用交叉驗證來獲得多個預測窗口,更好地評估每個模型的性能。
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()
評估計算了每個模型的平均絕對誤差(MAE)和均方誤差(MSE)。因為之前的數據是縮放的,因此報告的指標也是縮放的。
ettm1_evaluation = evaluate(df=nf_preds, metrics=[mae, mse], models=['SOFTS', 'TSMixer', 'iTransformer', 'PatchTST'])
從上圖可以看出,PatchTST的MAE最低,而softts、TSMixer和PatchTST的MSE是一樣的。在這種特殊情況下,PatchTST仍然是總體上最好的模型。
這并不奇怪,因為PatchTST在這個數據集中是出了名的好,特別是對于單變量任務。下面我們開始測試多變量場景。
2、多變量預測
使用相同的load_data函數,我們現在為這個多變量場景使用ETTm2數據集。
Y_df, val_size, test_size, freq = load_data('ettm2')
horizon = 96
然后簡單地初始化每個模型。我們只使用多變量模型來學習序列之間的相互作用,所以不會使用PatchTST,因為它應用通道獨立性(意味著每個序列被單獨處理)。
然后保留了與單變量場景中相同的超參數。只將n_series更改為7,因為有7個時間序列相互作用。
models = [SOFTS(h=horizon, input_size=3*horizon, n_series=7, max_steps=1000, early_stop_patience_steps=3, scaler_type='identity', valid_loss=MAE()),
TSMixer(h=horizon, input_size=3*horizon, n_series=7, max_steps=1000, early_stop_patience_steps=3, scaler_type='identity', valid_loss=MAE()),
iTransformer(h=horizon, input_size=3*horizon, n_series=7, max_steps=1000, early_stop_patience_steps=3, scaler_type='identity', valid_loss=MAE())]
訓練所有的模型并進行預測。
nf = NeuralForecast(models=models, freq='15min')
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()
最后使用MAE和MSE來評估每個模型的性能。
ettm2_evaluation = evaluate(df=nf_preds, metrics=[mae, mse], models=['SOFTS', 'TSMixer', 'iTransformer'])
上圖中可以看到到當在96的水平上預測時,TSMixer large在ETTm2數據集上的表現優于iTransformer和soft。
雖然這與soft論文的結果相矛盾,這是因為我們沒有進行超參數優化,并且使用了96個時間步長的固定范圍。
這個實驗的結果可能不太令人印象深刻,我們只在固定預測范圍的單個數據集上進行了測試,所以這不是SOFTS性能的穩健基準,同時也說明了SOFTS在使用時可能需要更多的時間來進行超參數的優化。
總結
SOFTS是一個很有前途的基于mlp的多元預測模型,STAD模塊是一種集中式方法,用于學習時間序列之間的相互作用,其計算強度低于注意力機制。這使得模型能夠有效地處理具有許多并發時間序列的大型數據集。
雖然在我們的實驗中,SOFTS的性能可能看起來有點平淡無奇,但請記住,這并不代表其性能的穩健基準,因為我們只在固定視界的單個數據集上進行了測試。
但是SOFTS的思路還是非常好的,比如使用集中式學習時間序列之間的相互作用,并且使用低強度的計算來保證數據計算的效率,這都是值得我們學習的地方。
并且每個問題都需要其獨特的解決方案,所以將SOFTS作為特定場景的一個測試選項是一個明智的選擇。