5個時間序列預(yù)測的深度學(xué)習(xí)模型對比總結(jié):從模擬統(tǒng)計(jì)模型到可以預(yù)訓(xùn)練的無監(jiān)督模型(附代碼)
來源:DeepHub IMBA
時間序列預(yù)測在最近兩年內(nèi)發(fā)生了巨大的變化,尤其是在kaiming的MAE出現(xiàn)以后,現(xiàn)在時間序列的模型也可以用類似MAE的方法進(jìn)行無監(jiān)督的預(yù)訓(xùn)練。
Makridakis M-Competitions系列(分別稱為M4和M5)分別在2018年和2020年舉辦(M6也在今年舉辦了)。對于那些不了解的人來說,m系列得比賽可以被認(rèn)為是時間序列生態(tài)系統(tǒng)的一種現(xiàn)有狀態(tài)的總結(jié),為當(dāng)前得預(yù)測的理論和實(shí)踐提供了經(jīng)驗(yàn)和客觀的證據(jù)。
2018年M4的結(jié)果表明,純粹的“ ML”方法在很大程度上勝過傳統(tǒng)的統(tǒng)計(jì)方法,這在當(dāng)時是出乎意料的。在兩年后的M5[1]中,最的高分是僅具有“ ML”方法。并且所有前50名基本上都是基于ML的(大部分是樹型模型)。這場比賽看到了LightGBM(用于時間序列預(yù)測)以及Amazon's Deepar [2]和N-Beats [3]的首次亮相。N-Beats模型于2020年發(fā)布,并且優(yōu)于M4比賽的獲勝者3%!
最近的 Ventilator Pressure Prediction比賽展示了使用深度學(xué)習(xí)方法來應(yīng)對實(shí)時時間序列挑戰(zhàn)的重要性。比賽的目的是預(yù)測機(jī)械肺內(nèi)壓力的時間順序。每個訓(xùn)練實(shí)例都是自己的時間序列,因此任務(wù)是一個多個時間序列的問題。獲勝團(tuán)隊(duì)提交了多層深度架構(gòu),其中包括LSTM網(wǎng)絡(luò)和Transformer 塊。
在過去的幾年中,許多著名的架構(gòu)已經(jīng)發(fā)布,如MQRNN和DSSM。所有這些模型都利用深度學(xué)習(xí)為時間序列預(yù)測領(lǐng)域貢獻(xiàn)了許多新東西。除了贏得Kaggle比賽,還給我們帶來了更多的進(jìn)步比如:
多功能性:將模型用于不同任務(wù)的能力。
MLOP:在生產(chǎn)中使用模型的能力。
解釋性和解釋性:黑盒模型并不那么受歡迎。
本文討論了5種專門研究時間序列預(yù)測的深度學(xué)習(xí)體系結(jié)構(gòu),論文是:
- N-BEATS (ElementAI)
- DeepAR (Amazon)
- Spacetimeformer [4]
- Temporal Fusion Transformer or TFT (Google) [5]
- TSFormer(時間序列中的MAE)[7]
N-BEATS
這種模式直接來自于(不幸的)短命的ElementAI公司,該公司是由Yoshua Bengio聯(lián)合創(chuàng)立的。頂層架構(gòu)及其主要組件如圖1所示:
N-BEATS是一個純粹的深度學(xué)習(xí)架構(gòu),它基于集成前饋網(wǎng)絡(luò)的深度堆棧,這些網(wǎng)絡(luò)也通過正向和反向的相互連接進(jìn)行堆疊。
每一個塊只對由前一個的backcast產(chǎn)生的殘差進(jìn)行建模,然后基于該誤差更新預(yù)測。該過程模擬了擬合ARIMA模型時的Box-Jenkins方法。
以下是該模型的主要優(yōu)勢:
表達(dá)性強(qiáng)且易于使用:該模型易于理解,具有模塊化結(jié)構(gòu),它被設(shè)計(jì)為需要最小的時間序列特征工程并且不需要對輸入進(jìn)行縮放。
該模型具有對多個時間序列進(jìn)行概括的能力。換句話說,分布略有不同的不同時間序列可以用作輸入。在N-BEATS中是通過元學(xué)習(xí)實(shí)現(xiàn)的。元學(xué)習(xí)過程包括兩個過程:內(nèi)部學(xué)習(xí)過程和外部學(xué)習(xí)過程。內(nèi)部學(xué)習(xí)過程發(fā)生在塊內(nèi)部,并幫助模型捕獲局部時間特征。外部學(xué)習(xí)過程發(fā)生在堆疊層,幫助模型學(xué)習(xí)所有時間序列的全局特征。
雙重殘差疊加:殘差連接和疊加的想法是非常巧妙的,它幾乎被用于每一種類型的深度神經(jīng)網(wǎng)絡(luò)。在N-BEATS的實(shí)現(xiàn)中應(yīng)用了相同的原理,但有一些額外的修改:每個塊有兩個殘差分支,一個運(yùn)行在回看窗口(稱為backcast),另一個運(yùn)行在預(yù)測窗口(稱為forecast)。
每一個連續(xù)的塊只對由前一個塊重建的backcast產(chǎn)生的殘差進(jìn)行建模,然后基于該誤差更新預(yù)測。這有助于模型更好地逼近有用的后推信號,同時最終的堆棧預(yù)測預(yù)測被建模為所有部分預(yù)測的分層和。就是這個過程模擬了ARIMA模型的Box-Jenkins方法。
可解釋性:模型有兩種變體,通用的和可解釋性的。在通用變體中,網(wǎng)絡(luò)任意學(xué)習(xí)每個塊的全連接層的最終權(quán)值。在可解釋的變體中,每個塊的最后一層被刪除。然后將后推backcast和預(yù)測forecast分支乘以模擬趨勢(單調(diào)函數(shù))和季節(jié)性(周期性循環(huán)函數(shù))的特定矩陣。
注意:原始的N-BEATS實(shí)現(xiàn)只適用于單變量時間序列。
結(jié)合深度學(xué)習(xí)和自回歸特性的新穎時間序列模型。圖2顯示了DeepAR的頂層架構(gòu):
以下是該模型的主要優(yōu)勢:
DeepAR在多個時間序列上工作得非常好:通過使用多個分布略有不同的時間序列來構(gòu)建全局模型。也適用于許多現(xiàn)實(shí)場景。例如電力公司可能希望為每個客戶推出電力預(yù)測服務(wù),每個客戶都有不同的消費(fèi)模式(這意味著不同的分布)。
除了歷史數(shù)據(jù),DeepAR還允許使用已知的未來時間序列(自回歸模型的一個特點(diǎn))和額外的靜態(tài)屬性。在前面提到的電力需求預(yù)測場景中,一個額外的時間變量可以是月份(作為一個整數(shù),值在1-12之間)。假設(shè)每個客戶都與一個測量功耗的傳感器相關(guān)聯(lián),那么額外的靜態(tài)變量將是sensor_id或customer_id之類的東西。
如果莫熟悉使用MLPs和rnn等神經(jīng)網(wǎng)絡(luò)架構(gòu)進(jìn)行時間序列預(yù)測,那么一個關(guān)鍵的預(yù)處理步驟是使用標(biāo)準(zhǔn)化或標(biāo)準(zhǔn)化技術(shù)對時間序列進(jìn)行縮放。這在DeepAR中是不需要手動操作的,因?yàn)榈讓拥哪P蛯γ總€時間序列i的自回歸輸入z進(jìn)行縮放,縮放因子為v_i,即該時間序列的平均值。具體而言,論文基準(zhǔn)中使用的比例因子方程如下:
但是在實(shí)踐中,如果目標(biāo)時間序列的大小差異很大,那么在預(yù)處理過程中應(yīng)用自己的縮放還是很有必要的。例如,在能源需求預(yù)測場景中,數(shù)據(jù)集可以包含中壓電力客戶(例如小工廠,按兆瓦單位消耗電力)和低壓客戶(例如家庭,按千瓦單位消耗電力)。
DeepAR進(jìn)行概率預(yù)測,而不是直接輸出未來值。這是以蒙特卡洛樣本的形式完成的。
這些預(yù)測被用來計(jì)算分位數(shù)預(yù)測,通過使用分位數(shù)損失函數(shù)。對于那些不熟悉這種損失類型的人,分位數(shù)損失不僅用來計(jì)算一個估計(jì),而且用來計(jì)算圍繞該值的預(yù)測區(qū)間。
在單變量時間序列中時間依賴性是最重要的。但是在多個時間序列場景中,事情就沒那么簡單了。例如假設(shè)我們有一個天氣預(yù)報任務(wù),想要預(yù)測五個城市的溫度。讓我們假設(shè)這些城市屬于一個國家。鑒于目前所看到的,我們可以使用DeepAR并將每個城市作為外部靜態(tài)協(xié)變量進(jìn)行建模。
換句話說,該模型將同時考慮時間和空間關(guān)系。這便是Spacetimeformer的核心理念:
使用一個模型來利用這些城市/地點(diǎn)之間的空間關(guān)系,從而學(xué)習(xí)額外的有用依賴,因?yàn)槟P蛯⑼瑫r考慮時間和空間關(guān)系。
深入研究時空序列
顧名思義,這種模型在內(nèi)部使用了基于transformers的結(jié)構(gòu)。在使用基于transformers的模型進(jìn)行時間序列預(yù)測時,一種流行的產(chǎn)生時間感知嵌入的技術(shù)是通過Time2Vec[6]嵌入層傳遞輸入(對于NLP任務(wù)是使用位置編碼向量來代替Time2Vec)。雖然這種技術(shù)對于單變量時間序列非常有效,但對于多變量時間輸入?yún)s沒有任何意義??赡苁窃谡Z言建模中,句子中的每個單詞都用嵌入表示,單詞本質(zhì)上是一個是詞匯表的一部分,而時間序列則沒那么簡單。
在多元時間序列中,在給定的時間步長t,輸入的形式為x_1,t, x2,t, x_m,t其中x_i,t是特征i的數(shù)值,m是特征/序列的總數(shù)。如果我們將輸入通過一個Time2Vec層,將產(chǎn)生一個時間嵌入向量。這種嵌入真正代表什么?答案是它將把整個輸入集合表示為單個實(shí)體(令牌)。因此模型將只學(xué)習(xí)時間步之間的時間動態(tài),但將錯過特征/變量之間的空間關(guān)系。
Spacetimeformer解決了這個問題,它將輸入扁平化為一個大向量,稱為時空序列。如果輸入包含N個變量,組織成T個時間步,則生成的時空序列將具有(NxT)標(biāo)記。下圖3更好地顯示了這一點(diǎn):
論文指出:“(1)包含時間信息的多元輸入格式。****輸入缺少(“?”)值,在進(jìn)行預(yù)測時設(shè)置為零。(2)時間序列通過一個Time2Vec層,生成一個代表周期性輸入模式的頻率嵌入。(3)二進(jìn)制嵌入表示該值是作為上下文給出的還是需要預(yù)測的。(4)將每個時間序列的整數(shù)索引映射到一個具有查找表嵌入的“空間”表示。(5)利用前饋層投影每個時間序列的Time2Vec嵌入和變量值。(6)將值和時間,變量和給定的嵌入求和會導(dǎo)致使MSA在時間和可變空間之間以更長的序列作為輸入。
換句話說,最后的序列編碼了一個包含了時間、空間和上下文信息統(tǒng)一的嵌入。但是這種方法的一個缺點(diǎn)是,序列可能會變得很長導(dǎo)致資源的二次增長。這是因?yàn)楦鶕?jù)注意機(jī)制,每個令牌都要對另一個進(jìn)行檢查。作者使用了一種更有效的體系結(jié)構(gòu),稱為Performer注意機(jī)制,適用于更大的序列。
Temporal Fusion Transformer(TFT)是由Google發(fā)布的基于Transformer的時間序列預(yù)測模型。TFT比以前的模型更加通用。
TFT的頂層架構(gòu)如圖4所示。以下是該模型的主要優(yōu)勢:
與前面提到的模型一樣,TFT支持在多個異構(gòu)時間序列上構(gòu)建模型。
TFT支持三種類型的特征:i)具有已知的未來輸入的時變數(shù)據(jù)ii)僅到目前為止已知的時變數(shù)據(jù)iii)分類/靜態(tài)變量,也被稱為時不變特征。因此TFT比以前的型號更通用。在前面提到的電力需求預(yù)測場景中,我們希望使用濕度水平作為一個時變特征,這是到目前為止才知道的。這在TFT中是可行的,但在DeepAR中不行。
圖5顯示了如何使用所有這些特性的示例:
TFT非常強(qiáng)調(diào)可解釋性。具體地說,通過利用Variable Selection組件(如上圖4所示),模型可以成功地度量每個特性的影響。因此可以說模型學(xué)習(xí)了特性的重要性。
另一方面,TFT提出了一種新的可解釋的多頭注意機(jī)制:該層的注意權(quán)重可以揭示在回顧期間哪些時間步是最重要的。這些權(quán)重的可視化可以揭示整個數(shù)據(jù)集中最顯著的季節(jié)模式。
預(yù)測區(qū)間:與DeepAR類似,TFT通過使用分位數(shù)回歸輸出預(yù)測區(qū)間和預(yù)測值。
綜上所述,深度學(xué)習(xí)無疑徹底改變了時間序列預(yù)測的格局。上述所有模型除了無與倫比的性能之外,還有一個共同點(diǎn):它們充分利用多重、多元的時間數(shù)據(jù),同時它們使用外生信息,將預(yù)測性能提高到前所未有的水平。但是在自然語言處理(NLP)任務(wù)中多數(shù)都利用了預(yù)訓(xùn)練的模型。NLP任務(wù)的feed大多是人類創(chuàng)造的數(shù)據(jù),充滿了豐富而優(yōu)秀的信息,幾乎可以看作是一個數(shù)據(jù)單元。在時間序列預(yù)測中,我們可以感覺到缺乏這種預(yù)先訓(xùn)練的模型。為什么我們不能像在NLP中那樣在時間序列中利用這個優(yōu)勢呢?
這就引出了我們要介紹的最后一個模型TSFormer,該模型考慮了兩個視角,我們講從輸入到輸出將其為四個部分,并且提供Python的實(shí)現(xiàn)代碼(官方也提供了),這個模型是剛剛發(fā)布不久的,所以我們才在這里著重介紹它。
它是一種基于Transformer(TSFormer)的無監(jiān)督的時間序列預(yù)訓(xùn)練模型,使用了MAE中的訓(xùn)練策略并且能夠捕獲數(shù)據(jù)中非常長的依賴關(guān)系。
NLP和時間序列:
在某種程度上,NLP信息和Time Series數(shù)據(jù)是相同的。它們都是順序數(shù)據(jù)和局部敏感的,這意味著與它的下一個/以前的數(shù)據(jù)點(diǎn)有關(guān)。但是還是有一些區(qū)別,在提出我們的預(yù)訓(xùn)練模型時,我們應(yīng)該考慮兩個差異,就像我們在NLP任務(wù)中所做的那樣:
時間序列數(shù)據(jù)的密度比自然語言數(shù)據(jù)低得多
我們需要比NLP數(shù)據(jù)更長的時間序列數(shù)據(jù)
TSFormer簡介
TSFormer與MAE的主要體系結(jié)構(gòu)基本類似,數(shù)據(jù)通過一個編碼器,然后經(jīng)過一個****,最終的目標(biāo)是為了重建缺失(人工掩蔽)的數(shù)據(jù)。
我們將他總結(jié)為以下4點(diǎn)
1、掩蔽
作為數(shù)據(jù)進(jìn)入編碼器的前一步。輸入序列(S?)已分布到P片中,其長度為L。因此,用于預(yù)測下一個時間步長的滑動窗口的langth是P XL。
遮蔽比率為75%(看著很高,估計(jì)是用了MAE一樣的參數(shù));我們要完成的是一項(xiàng)自監(jiān)督任務(wù),所以數(shù)據(jù)越少編碼器的計(jì)算速度就越快。
這樣做(掩蔽輸入序列段)的主要原因是:
段(patch)比單獨(dú)點(diǎn)好。
它使使用下游模型變得簡單(STGNN將單元段作為輸入)
可以分解編碼器的輸入大小。
class Patch(nn.Module): def __init__(self, patch_size, input_channel, output_channel, spectral=True): super().__init__() self.output_channel = output_channel self.P = patch_size self.input_channel = input_channel self.output_channel = output_channel self.spectral = spectral if spectral: self.emb_layer = nn.Linear(int(patch_size/2+1)*2, output_channel) else: self.input_embedding = nn.Conv2d(input_channel, output_channel, kernel_size=(self.P, 1), stride=(self.P, 1))
def forward(self, input): B, N, C, L = input.shape if self.spectral: spec_feat_ = torch.fft.rfft(input.unfold(-1, self.P, self.P), dim=-1) real = spec_feat_.real imag = spec_feat_.imag spec_feat = torch.cat([real, imag], dim=-1).squeeze(2) output = self.emb_layer(spec_feat).transpose(-1, -2) else: input = input.unsqueeze(-1) # B, N, C, L, 1 input = input.reshape(B*N, C, L, 1) # B*N, C, L, 1 output = self.input_embedding(input) # B*N, d, L/P, 1 output = output.squeeze(-1).view(B, N, self.output_channel, -1) assert output.shape[-1] == L / self.P return output
以下是生成遮蔽的函數(shù)
class MaskGenerator(nn.Module): def __init__(self, mask_size, mask_ratio, distribution='uniform', lm=-1): super().__init__() self.mask_size = mask_size self.mask_ratio = mask_ratio self.sort = True self.average_patch = lm self.distribution = distribution if self.distribution == "geom": assert lm != -1 assert distribution in ['geom', 'uniform']
def uniform_rand(self): mask = list(range(int(self.mask_size))) random.shuffle(mask) mask_len = int(self.mask_size * self.mask_ratio) self.masked_tokens = mask[:mask_len] self.unmasked_tokens = mask[mask_len:] if self.sort: self.masked_tokens = sorted(self.masked_tokens) self.unmasked_tokens = sorted(self.unmasked_tokens) return self.unmasked_tokens, self.masked_tokens
def geometric_rand(self): mask = geom_noise_mask_single(self.mask_size, lm=self.average_patch, masking_ratio=self.mask_ratio) # 1: masked, 0:unmasked self.masked_tokens = np.where(mask)[0].tolist() self.unmasked_tokens = np.where(~mask)[0].tolist() # assert len(self.masked_tokens) > len(self.unmasked_tokens) return self.unmasked_tokens, self.masked_tokens
def forward(self): if self.distribution == 'geom': self.unmasked_tokens, self.masked_tokens = self.geometric_rand() elif self.distribution == 'uniform': self.unmasked_tokens, self.masked_tokens = self.uniform_rand() else: raise Exception("ERROR") return self.unmasked_tokens, self.masked_tokens
2、編碼
包括了輸入嵌入,位置編碼和Transformer 塊的。編碼器只能在未遮蔽的patchs上執(zhí)行(這個也是MAE的方法)。
輸入嵌入
使用線性的投影來獲得輸入的嵌入,可將未遮蔽的空間轉(zhuǎn)換為潛在空間。它的公式可以在下面看到:
W和B是可學(xué)習(xí)的參數(shù),U是維度中的模型輸入向量。
位置編碼
簡單的位置編碼層用于附加新的順序信息。添加了“可學(xué)習(xí)”一詞,這有助于表現(xiàn)出比正弦更好的性能。因此可學(xué)習(xí)的位置嵌入顯示了時間序列的良好結(jié)果。
class LearnableTemporalPositionalEncoding(nn.Module): def __init__(self, d_model, dropout=0.1, max_len: int = 1000): super().__init__() self.dropout = nn.Dropout(p=dropout) self.pe = nn.Parameter(torch.empty(max_len, d_model), requires_grad=True) nn.init.uniform_(self.pe, -0.02, 0.02)
def forward(self, X, index): if index is None: pe = self.pe[:X.size(1), :].unsqueeze(0) else: pe = self.pe[index].unsqueeze(0) X = X + pe X = self.dropout(X) return X
class PositionalEncoding(nn.Module): def __init__(self, hidden_dim, dropout=0.1): super().__init__() self.tem_pe = LearnableTemporalPositionalEncoding(hidden_dim, dropout)
def forward(self, input, index=None, abs_idx=None): B, N, L_P, d = input.shape # temporal embedding input = self.tem_pe(input.view(B*N, L_P, d), index=index) input = input.view(B, N, L_P, d) # absolute positional embedding return input
Transformer 塊
論文使用了4層Transformer ,比計(jì)算機(jī)視覺和自然語言處理任務(wù)中常見的數(shù)量低。這里所使用的Transformer 是最基本的也是在原始論文中提到的結(jié)構(gòu),如下圖4所示:
class TransformerLayers(nn.Module): def __init__(self, hidden_dim, nlayers, num_heads=4, dropout=0.1): super().__init__() self.d_model = hidden_dim encoder_layers = TransformerEncoderLayer(hidden_dim, num_heads, hidden_dim*4, dropout) self.transformer_encoder = TransformerEncoder(encoder_layers, nlayers)
def forward(self, src): B, N, L, D = src.shape src = src * math.sqrt(self.d_model) src = src.view(B*N, L, D) src = src.transpose(0, 1) output = self.transformer_encoder(src, mask=None) output = output.transpose(0, 1).view(B, N, L, D) return output
3、解碼
該****包括一系列Transformer塊。它適用于所有的patch(相比之下MAE是沒有位置嵌入,因?yàn)樗膒atch已經(jīng)有位置信息),并且層數(shù)只有一層,然后使用了簡單的MLP,這使得輸出長度等于每個patch的長度。
4、重建目標(biāo)
對每一個數(shù)據(jù)點(diǎn)(i)進(jìn)行遮蔽patch的計(jì)算,并選擇mae (Mean-Absolute-Error)作為主序列和重建序列的損失函數(shù)。
這就是整體的架構(gòu)了
下面是代碼實(shí)現(xiàn):
def trunc_normal_(tensor, mean=0., std=1.): __call_trunc_normal_(tensor, mean=mean, std=std, a=-std, b=std)
def unshuffle(shuffled_tokens): dic = {} for k, v, in enumerate(shuffled_tokens): dic[v] = k unshuffle_index = [] for i in range(len(shuffled_tokens)): unshuffle_index.append(dic[i]) return unshuffle_index
class TSFormer(nn.Module): def __init__(self, patch_size, in_channel, out_channel, dropout, mask_size, mask_ratio, L=6, distribution='uniform', lm=-1, selected_feature=0, mode='Pretrain', spectral=True): super().__init__() self.patch_size = patch_size self.seleted_feature = selected_feature self.mode = mode self.spectral = spectral self.patch = Patch(patch_size, in_channel, out_channel, spectral=spectral) self.pe = PositionalEncoding(out_channel, dropout=dropout) self.mask = MaskGenerator(mask_size, mask_ratio, distribution=distribution, lm=lm) self.encoder = TransformerLayers(out_channel, L) self.decoder = TransformerLayers(out_channel, 1) self.encoder_2_decoder = nn.Linear(out_channel, out_channel) self.mask_token = nn.Parameter(torch.zeros(1, 1, 1, out_channel)) trunc_normal_(self.mask_token, std=.02) if self.spectral: self.output_layer = nn.Linear(out_channel, int(patch_size/2+1)*2) else: self.output_layer = nn.Linear(out_channel, patch_size)
def _forward_pretrain(self, input): B, N, C, L = input.shape # get patches and exec input embedding patches = self.patch(input) patches = patches.transpose(-1, -2) # positional embedding patches = self.pe(patches)
# mask tokens unmasked_token_index, masked_token_index = self.mask()
encoder_input = patches[:, :, unmasked_token_index, :]
# encoder H = self.encoder(encoder_input) # encoder to decoder H = self.encoder_2_decoder(H) # decoder # H_unmasked = self.pe(H, index=unmasked_token_index) H_unmasked = H H_masked = self.pe(self.mask_token.expand(B, N, len(masked_token_index), H.shape[-1]), index=masked_token_index) H_full = torch.cat([H_unmasked, H_masked], dim=-2) # # B, N, L/P, d H = self.decoder(H_full)
# output layer if self.spectral: # output = H spec_feat_H_ = self.output_layer(H) real = spec_feat_H_[..., :int(self.patch_size/2+1)] imag = spec_feat_H_[..., int(self.patch_size/2+1):] spec_feat_H = torch.complex(real, imag) out_full = torch.fft.irfft(spec_feat_H) else: out_full = self.output_layer(H)
# prepare loss B, N, _, _ = out_full.shape out_masked_tokens = out_full[:, :, len(unmasked_token_index):, :] out_masked_tokens = out_masked_tokens.view(B, N, -1).transpose(1, 2)
label_full = input.permute(0, 3, 1, 2).unfold(1, self.patch_size, self.patch_size)[:, :, :, self.seleted_feature, :].transpose(1, 2) # B, N, L/P, P label_masked_tokens = label_full[:, :, masked_token_index, :].contiguous() label_masked_tokens = label_masked_tokens.view(B, N, -1).transpose(1, 2)
# prepare plot ## note that the output_full and label_full are not aligned. The out_full in shuffled ### therefore, unshuffle for plot unshuffled_index = unshuffle(unmasked_token_index + masked_token_index) out_full_unshuffled = out_full[:, :, unshuffled_index, :] plot_args = {} plot_args['out_full_unshuffled'] = out_full_unshuffled plot_args['label_full'] = label_full plot_args['unmasked_token_index'] = unmasked_token_index plot_args['masked_token_index'] = masked_token_index
return out_masked_tokens, label_masked_tokens, plot_args
def _forward_backend(self, input): B, N, C, L = input.shape # get patches and exec input embedding patches = self.patch(input) patches = patches.transpose(-1, -2) # positional embedding patches = self.pe(patches)
encoder_input = patches # no mask when running the backend.
# encoder H = self.encoder(encoder_input) return H
def forward(self, input_data):
if self.mode == 'Pretrain': return self._forward_pretrain(input_data) else: return self._forward_backend(input_data)
看完這個論文,我發(fā)現(xiàn)這基本上可以說是復(fù)制了MAE,或者說是時間序列的MAE,在預(yù)測階段也是與MAE類似,使用編碼器的輸出作為特征,為下游任務(wù)提供特征數(shù)據(jù)作為輸入,有興趣的可以讀讀原始論文并且看看論文給的代碼。
[1] Makridakis et al., The M5 Accuracy competition: Results, findings and conclusions, (2020)[2] D. Salinas et al., DeepAR: Probabilistic forecasting with autoregressive recurrent networks, International Journal of Forecasting (2019).[3] Boris N. et al., N-BEATS: Neural Basis Expansion Analysis For Interpretable Time Series Forecasting, ICLR (2020)[4] Jake Grigsby et al., Long-Range Transformers for Dynamic Spatiotemporal Forecasting,[5] Bryan Lim et al., Temporal Fusion Transformers for Interpretable Multi-horizon Time Series Forecasting, International Journal of Forecasting September 2020[6] Seyed Mehran Kazemi et al.,Time2Vec: Learning a Vector Representation of Time, July 2019[7] Pre-training Enhanced Spatial-temporal Graph Neural Network for Multivariate Time Series Forecasting[8] Masked Autoencoders Are Scalable Vision Learners
*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點(diǎn),如有侵權(quán)請聯(lián)系工作人員刪除。
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)