結構化多元時序模型在攜程業務量上的預測應用
一、背景
多元時間序列(MTS)預測一直是業務中的一個重要問題,科學地預測下單量或用戶數能夠協助財務制定預算、協助客服安排人員、幫助業務方更好地評估某個活動上線的效果。在預定類業務,例如電商平臺、OTA行業等,一段時間內的下單人數或是訂單量背后其實蘊藏著一定的時間規律或者某種特定的時空結構,也就是其本身近似于一個有著較復雜結構的時間序列。如何對未來一定時間內的下單用戶或是業務量進行預測,其核心問題就是如何有效地對這類復雜的時空結構建模,最大程度地模擬出數據背后的結構特征,進而得到對于未來有效的預測。
本文主要將介紹SCNN模型及其代碼的具體實現,以及如何將其應用在預測業務量上的實際操作過程,旨在面對一些擁有復雜時空結構的多元變量數據時能更準確地進行預測。下文將首先對模型原理進行簡要闡釋,隨后展示代碼邏輯,最后介紹在具體業務場景上的實踐應用。
二、現有方法及潛在問題
目前針對時序數據的預測一般是通過同比或者環比的方式加上業務方自己對業務增長的理解進行,或是使用ARIMA等較簡單的時序模型進行預測,并沒有使用非常貼合數據結構規律的模型。因此較難對一些復雜的時序數據有較精準科學的刻畫。
之前介紹過的BSTS結構模型也是一種針對結構化時序數據的模型,能夠拆解出數據背后的結構因子。但是因為融入了貝葉斯的思想,考慮的都是參數的分布形式,最終給出的預測結果也都是包含置信區間的“區間估計”,不能滿足業務方想要一個“具體預測值”的需求。且BSTS模型普遍情況下適合單維變量的預測情況,不能很好地捕捉到不同變量之間的相關性。而實際上,大多數的變量都會受到外界各種其他變量的影響,因此使用多元時序的預測模型是一個更好地選擇。
同時,為了滿足業務方想要一個更具體的預測結果,我們需要一類“點估計”的預測模型。結合上述兩點要求,SCNN模型是一個不錯的選擇。下文中我們將詳細介紹這一模型的思想原理以及其具體使用的場景和方法。
三、模型介紹
結構化時間序列數據在日常生活中并不少見,尤其像攜程這樣的OTA行業,平臺的下單情況其實就具有一定時間規律,例如周末往往是一周內的下單高峰期;節假日是一年內的下單高峰期等等。
SCNN模型(Structured Components-based Neural Network)全稱為“基于結構化組件的神經網絡模型”,正如其名,它的主要特點體現在:(1)將數據分解為多個結構;(2)適用于多元序列數據;(3)應用了神經網絡的建模思想。
在時間序列預測中,基于分解的建模思路也并不少見,常見地,將序列分為周期項;季節項等等。SCNN模型也類似這樣的思路:將時序數據分為4個模塊:長周期項(long-term);短周期項(short-term);季節性項(seasonal-component)以及序列間相關性項(co-evolving component),隨后對各個結構模塊進行解耦再分別建模,分別預測;最終將結果通過卷積方式融合在一起,進而輸出對未來數據的預測。多元時間序列可以表示為一簇{Yn,t}n∈N,t∈T,其中{Yn,t}表示在t時間的第n個變量的數值。那基于現有數據,對未來序列的預測即可表示為如下概率公式:
簡答來說,SCNN模型的主要思想就是將一個多元時序數據分解成4個模塊,每個模塊可以從不同的角度提供數據信息,以此讓模型能夠更好地“學習”到原序列內在的結構規律,并更好地作出對未來的預測。
圖3-1展示了某一個時序數據通過SCNN拆解后得到的4個模塊,最上方的藍線表示原有的數據,下方的四種曲線分別表示一種結構。可以看出一個表面有著某種規律的數據背后其實可以細分拆解出多個不同的結構模塊。
3.1 多元序列生成過程
基于上述的分解思想,原始的序列數據被有序地拆分為了4個模塊,分別是長周期項、季節項、短周期項以及序列間相關性項。具體過程可以表示為以下的公式:
其中,表示原始的序列數據;
表示經過一層層分解之后的數據。相應的
表示針對于long-term;short-term;seasonal-term;co-evolving-term狀態下的均值和標準差;最后的Rn,t 表示原數據經過4層分解后的剩余項。
更具象地,可以用“交通密度數據“來模擬這一過程,不同的模塊可以反映出影響交通數據的不同方面:長周期項能夠體現一個城市的交通總體趨勢,例如人口的增長導致的擁堵或整個城市經濟發展導致的交通變化,是一個較長時間范圍內的影響;季節性項體現在某固定周期內的交通變化,例如每天上下班的高峰時段會帶來交通的擁堵或是周末帶來的擁堵;短周期項則能夠捕捉由一些突發事件導致的短暫瞬時變化,例如突發的交通事故或是突然的惡劣天氣等導致短時間內的交通變化;序列間相關性項則反應不同交通道路之間的相互影響程度,例如突然的交通事故可能會加大鄰近道路的擁堵情況;最終的剩余項(殘差項)則會保留一些隨機效應或是系統誤差等等。
需要注意的是,不同項之間會存在互相流動的情況,例如突發的交通事故如果一直持續,可能會發展成“短周期項”,如果持續的時間更長,則可能會轉移成長周期項,這種流動性就要求模型能夠更加靈活,從而準確地把握每一個結構的流動情況。
3.2 結構分解
本節將介紹如何對4個模塊進行分解建模以及預測:
1)長周期項:如前文所示,長周期反映的是序列數據在較長時間范圍內的變化。因此選擇構建一個較大的滑動窗口,取每個窗口內的均值與標準差作為長周期項的兩個參數。
其中表示長周期項的均值與標準差;
表示將原數據進行長周期化后的數據(提取出長周期項)。
2)季節性項:與長周期項的滑動窗口類似,在基于 “序列的周期長度是一致的”假設前提下,對季節性項也采取一個窗口統計的方法。
其中表示季節性項的均值與標準差;
表示將
再進行季節性化后的數據(提取出季節性項)。
3)短周期項:和長周期項相同,這里取一個較短的滑動窗口來進行計算;較短的窗口能夠防止一些短期內的信息平滑掉,從而能夠體現出數據在短時間內的變化,提供更全面的信息。
其中表示短周期項的均值與標準差;
表示將
進行短周期化后的數據(提取短周期項)。
4)序列間相關性項:相較于單元序列,多元序列需要考慮到不同變量之間的相關性,如上述的交通案例中某一道路的突發情況會對鄰近道路造成影響,這一過程就體現了序列間相關性。作者認為不同序列間會共享某一個相關性值(例如道路A鄰近的兩條道路B和C,如果都發生了交通事故,他們對于道路A的影響程度可能是同一個相關性結構),因此我們需要識別出哪些序列間會共享同一個相關性結構,換句話說我們需要知道每一對序列之間的相關性結構。
我們可以采取通過一些先驗知識計算兩兩序列之間的相關性權重矩陣;也可以通過讓模型自己學習,SCNN模型選擇了后者,采用注意力計算的方法,給每一對序列之間設置一個注意力分數并通過softmax方式進行標準化以確保注意力分數總和為1;最終每一對序列之間的分數可以表示如下:
其中分別表示第n個變量與第
個變量在標準化后和標準化前的注意力分數;
表示將注意力分數分配到每兩個變量后的的均值與標準差;Rn,t 表示
被抽取序列間相關性之后。最終無法被分解的剩余項。
下圖展示了一個多元時間序列經過4道分解的過程:先抽取長周期項;再抽取季節性項;再抽取短周期項最后抽取序列間的相關性項。在進行4道分解之后會得到4個模塊各自的模型,隨后會分別進行預測,最終將4個模塊預測的結果經過一維卷積融合得到最終輸出的預測序列。
圖3-2展示SCNN模型對于4個模塊分解的過程。過程中會分別計算出每個模塊的均值與標準差值作為模型參數,將4個模塊分別抽取之后分別進行建模、預測;最后將各模塊的預測結果進行融合得到最終的序列預測結果。
3.3 結構預測
上述內容介紹了如何將序列的4個模塊分別抽取并建模的過程,下面將介紹如何對這4個模塊分別進行預測。
長周期和季節性項因為統一采用了滑動窗口的形式并且其周期較長、較平滑,如果預測較近的未來,這兩項的趨勢不會有太大的波動,因此可以直接用參數估計的方式進行預測,即直接用當前窗口的均值作為下一個窗口的估計,公示如下:
短周期項、相關性項以及殘差項因為會在短時間內有較大的變動因此無法使用長周期的方法進行推測。作者認為可以對這三種模塊各自建立一個自回歸的模型,能夠基于過去的信息來預測未來的情況。為了簡便作者統一用下面的表達式來表示這三項結構的自回歸模型:
其中是模型中的權重矩陣,bi表示預測偏差。
,表示囊括了短周期、序列間相關性以及殘差項這三個結構,其中我們主要需要訓練
以及bi。
圖3-3表示對于不同模塊的預測方法。長周期直接使用上一個窗口的均值當做下一個窗口的預測值;季節性與長周期方法類似,使用上一個季節的均值當做下一個季節窗口的預測。短周期與序列間相關性項是利用自回歸模型進行推測。
3.4 結構融合
通過上述方式可以分別得到四種模塊在要求范圍內的預測結果,之后作者提出用神經網絡的方式對預測的結果進行融合。具體來說,引入一個神經模塊,分為兩個分支:一個專門用于特征學習(通過神經網絡自動學習輸入數據中的特征結構),另一個用于參數學習(通過訓練過程調整網絡中的權重和偏差等參數,提升網絡的擬合程度),最后這兩個分支的輸出將通過卷積方式整合成最終的預測結果。
3.5 損失函數&殘差項處理
傳統對于預測模型的評估指標即為MAE或者MSE,通過預測值與真實值之間的差距來評估模型預測的好壞,但是這樣的評估方法有一個內在的假設:所有變量的方差量綱相同。但由于時序數據在不同時間點下的波動程度并不相同,如果基于這樣的假設進行預測,那最終融合后的數據可能并不是最佳的預測結果。于是作者考慮將MLE納入損失函數定義中,將損失函數重新定義為:
其中第一項用來控制預測結果的波動不要太大;第二項則同時控制預測結果與真實結果的差距與預測結果的波動性均不要太大。
但作者認為僅僅依靠改變上述目標函數仍存在一定風險,他認為經過4層拆解之后的剩余項Rn,t中仍可能包含沒有分解干凈的結構特征,最后導致模型給殘差部分分配一個較高的權重,而這些權重本應被分配到相應的結構項上。如果殘差項擁有了不恰當的高權重,那一旦時序數據后續受到高頻的隨機噪聲的干擾,那模型的有效性就會大幅下降。
為了解決這個問題,作者額外再引入了一個正則化項來控制殘差項中的結構權重,以此促使模型更多地聚焦在分解出的4個結構項上,同時保證模型如果在僅使用4個分解項結構而沒有殘差項的情況下也能做出相對合理的預測結果。具體來說,在訓練模型的過程中,SCNN在分解模塊之后,會有兩個分支。一個分支保留了殘差項,和4個模塊一起用來訓練模型;另一個分支則將殘差項全部置零,只傳遞結構成分來進行后續模型訓練。最后分別用這兩種方法得到預測結果并進行加權求和,構建最終的目標函數:
其中就是通過置零殘差項得到的模型預測結果;
是保留殘差項的模型預測結果。最終我們會使用這個目標函數來訓練模型。
圖3-4展示了目標函數不同的構建方式。第一張圖表示傳統的MSE損失函數;第二張圖是考慮了時序結構特點的損失函數納入了MLE;第三張圖表示在第二張圖的目標函數構建的基礎上,參照公式(21)將殘差項置零后得到的預測結果與普通預測結果加權后得到最終的目標函數。
四、模型應用與代碼實現
以上我們介紹了SCNN模型的基本思想以及理論步驟,下面我們將介紹作者在git上開源的代碼邏輯,以及我們如何在實際業務過程中使用該模型對業務量進行預測。具體代碼實現可以參考文獻[2]。
圖4-1展示了訓練模型的具體執行過程,從輸入數據訓練、選取最佳模型、使用模型進行預測到最后對模型進行定期更新迭代。
4.1 代碼實現
下面通過部分代碼來展示實現過程,這里主要介紹4個模塊的抽取與預測部分:
# 進行季節性歸一化處理,input:數據集+周期長度;output:季節性結構的均值與方差以及標準化后結果
def SeasonalNorm(x, period_length):
mean = F.pad(mean.reshape(b * c, n, -1), mode='circular', pad=(t % period_length, 0)).reshape(b, c, n, -1)
var = F.pad(var.reshape(b * c, n, -1), mode='circular', pad=(t % period_length, 0)).reshape(b, c, n, -1)
out = (x - mean) / (var + epsilon) ** 0.5
return out, mean, var ** 0.5
# 序列間相關性項
class AdaSpatialNorm(nn.Module):
def forward(self, x):
mean_f = torch.matmul(adj_mat, x_f)
var_f = torch.matmul(adj_mat, x_f ** 2) - mean_f ** 2 + 0.00001
mean = mean_f.view(b, t, n, c).permute(0, 3, 2, 1)
var = var_f.view(b, t, n, c).permute(0, 3, 2, 1)
out = (x - mean) / (var + epsilon) ** 0.5
return out, mean, var ** 0.5
# 進行長短周期的歸一化處理,input:數據集與滑動窗口的長度;output:經過長/短周期歸一化后的值以及各自結構的均值方差
def TermNorm(x, term_length):
mean = F.pad(mean.reshape(b * c, n, -1), mode='replicate', pad=(term_length-1, 0)).reshape(b, c, n, -1)
var = F.pad(var.reshape(b * c, n, -1), mode='replicate', pad=(term_length-1, 0)).reshape(b, c, n, -1)
out = (x - mean) / (var + epsilon) ** 0.5
return out, mean, var ** 0.5
#對四個模塊進行卷積融合,input:原數據集,output:預測后的數值
class SCNN(nn.Module):
def forward(self, input):
pred_distr_args = self.proj_distr_args(out) # 不mask殘差項得到的預測結果
pred_distr_args = (pred_distr_args[0], pred_distr_args[1], F.threshold(pred_distr_args[2], 0.2, 0.2))
pred_distr = self.distr_output.distribution(pred_distr_args)
pred_distr_args_aux = self.proj_distr_args(out_aux) # mask殘差項后得到的預測結果
pred_distr_args_aux = (pred_distr_args_aux[0], pred_distr_args_aux[1], F.threshold(pred_distr_args_aux[2], 0.2, 0.2))
pred_distr_aux = self.distr_output.distribution(pred_distr_args_aux)
pred_mean = pred_distr_args[1].reshape(b, n, self.num_pred, 1).permute(0, 2, 1, 3)
if self.training:
return pred_distr, pred_distr_aux
else:
return pred_mean
上述代碼展示了部分SCNN模型的建模及預測過程,包括長短周期項、季節性項以及序列間項的建模過程,最后的SCNN類是將這幾個模塊分別建模并做預測,融合在一起后得到最終預測的結果。
4.2 最佳模型選取
通過構建訓練集、驗證集與測試集(*不是無序打亂,會滿足時間連貫性,例如訓練集是1~80天的數據,驗證集是81~120天的數據,測試集是121~150天的數據*),以RMSE與MAE等指標為標準選取效果最好的模型并保存。
4.3 模型參數
模型包含大量參數,可以歸納為4個部分(如下圖所示),不同版塊的參數將通過不同方式獲取。
圖4-2展示了不同類型的模型參數,可以分為與SCNN結構相關的參數值;與神經網絡相關的模型參數值;模型訓練的指標值以及訓練預測時的步長設置等。
數據集自身結構參數:長/短周期及季節項等參數可以直接通過對歷史數據的分析得到。
神經網絡相關參數:可以通過提前設置或是對比不同參數下的模型效果來得到最優的那個。原文中作者嘗試了多個參數包括網絡層數;hidden channel;kernal size等等來對比不同組合下模型的效果(如圖4-3所示)。這種通過不同參數組合對比模型結果的方式能直觀反映出參數的優劣但也會消耗較大的資源,實際應用中可以視資源條件而定。
圖4-3展示了在不同的網絡超參設置下模型表現的結果對比,可以看出并不是網絡層數越多或核數越多就一定會得到更好的訓練效果。
模型訓練相關參數:這部分參數主要涉及訓練模型時對訓練集、驗證集、測試集的劃分,更推薦各個子集的長度是周期項的倍數,例如如果以每小時作為步長,周期項為一天,則周期值為24,那訓練集、驗證集與測試集最好都能夠是24的倍數,這樣模型訓練的時候能夠更好的學到周期項的影響。當然具體情況視數據集本身結構而定。其余的迭代次數與模型指標也視具體情況和資源條件而定。
訓練&預測步長參數:事先需要定好使用多長時間內的數據對未來多久范圍內的數據進行預測。SCNN模型更擅長對于短時間內的未來進行預測,能夠很好地捕捉到短時間內的數據波動情況。
4.4 模型對比
作者使用了BikeNYC、PeMSD7及Electricity三個數據集進行測試,將SCNN的預測效果與其他一些時序預測模型進行對比。從結果看,SCNN模型在對未來短時間的預測上,效果優于其他模型。此處展示了在BikeNYC數據集上部分模型與SCNN模型的預測效果,作者進行了3次橫向實驗,此處取3次指標值的平均值進行展示:
五、業務場景實踐
我們希望對業務量進行合理地預測,來協助財務、產品等多方調整評估自身業務。通過對歷史數據的分析發現,每日業務量的數值可以看作一個時間序列,它會受到一個地區長期人口增長或是旅游業發展帶來的長期影響;每個周末的出行小高峰會體現出季節性的特點;每天上下班的小高峰類似是一個短周期項;且業務量與當下的站內活躍人數、下單人數等等其他變量之間會存在相關性,符合SCNN模型的適用數據對象。
于是我們嘗試使用SCNN模型來進行結構拆解及預測,以此給出更科學的預測結果。另一方面,我們發現平峰時期的業務量結構與節假日高峰時期的業務量結構并不完全相同,因此我們選擇分開訓練適用平峰期業務與高峰期業務的模型。
5.1 數據選取&模型訓練
數據預備:從數據圖像上我們可以看出,在一天之內業務量呈現某種固定的波動趨勢,因此我們取1小時為1步長,以一天(24H)為季節性周期。同時也可以發現每周的業務量也呈現相似的波動規律,例如周中是一周中的“淡季”,周四~周日是一周中的“旺季”,于是我們取一周(168H)為一個長周期。綜上,確定了模型中所有的結構參數。
圖5-1展示了每小時業務量的波動趨勢,體現出一定的周期性和規律性。
數據選取:考慮到疫情對出行業務的影響,我們選取了2019年與2023年全年的所有數據進行模型訓練,變量包括業務量、下單人數、訪問人數等多列變量;
模型訓練:將上述數據代入SCNN模型中,選取若干不同的hidden channel, kernel size訓練模型,以RMSE為指標得到最佳的SCNN模型及其參數。
方法改進:針對節假日,我們發現不同節假日的業務量趨勢結構各不相同,且都與平峰期不同,例如端午期間就不是以一周為長周期的趨勢。因此針對節假日我們單獨訓練了模型,考慮到節假日有提前開售以及人們不同的返程習慣,這里使用的是每個節假日前30天起到節假日結束后7天的數據,同樣通過調試不同的模型參數來確定最佳的節假日SCNN模型。而針對平峰期,我們即使用2019年與2023年全年的數據進行訓練,得到最佳模型。
模型應用:根據上述方法分別得到了適用于平峰期與節假日高峰期的兩個模型。隨后我們將模型應用在2024年的數據上進行準確性的驗證。
5.2 代碼實現&結果解讀
考慮到春節的特殊性,我們選擇從2024年3月1日起進行模型的驗證:用每168H的數據來預測下一個24H的業務量(例如用3/1~3/7的數據預測3/8的數據),并采取rolling prediction的方式對3~6月的每日業務量數據進行預測(用3/1~3/7的數據預測3/8的數據,隨后用3/2~3/8的數據預測3/9的數據)。過程中并未用到任何實際真實的數據,完全是通過模型預測完成了對3個月內每天業務量的預測任務。整個預測期間會涉及清明、五一與端午三個節假日,我們會在平峰期時使用平峰期SCNN模型;在節假日適用高峰期SCNN模型。下方展示了部分訓練及預測使用的代碼模塊:
# 設置規定指標閾值與迭代次數,訓練模型得到最佳模型
for epoch in range(nb_epoch):
model.train()
running_loss = []
for j, x_batch in enumerate(gen_batch(dataset.get_data('train'), batch_size, dynamic_batch=False, shuffle=True)):
xh = torch.tensor(xh, dtype=torch.float32).to(device)
y = torch.tensor(y, dtype=torch.float32).to(device)
pred_distr, pred_distr_aux = model(xh)
model.zero_grad()
loss = - pred_distr.log_prob(y.permute(0, 2, 1, 3).reshape(-1, n_pred)).mean() - 0 * pred_distr_aux.log_prob(y.permute(0, 2, 1, 3).reshape(-1, n_pred)).mean()
loss.backward()
nn.utils.clip_grad_norm_(model.parameters(), 10)
optimizer.step()
running_loss.append(loss.data.cpu().numpy())
if epoch % 10 == 0:
model.eval()
min_va_val, min_val, min_ta_val = model_inference(device, model, dataset, test_batch_size, n_his, n_pred, min_va_val, min_val, n)
for i in range(n_pred):
print(f'MAPE {va[i*3]:7.3%}, {te[i*3]:7.3%}, {ta[i*3]:7.3%};'
f'MAE {va[i*3+1]:4.3f}, {te[i*3+1]:4.3f}, {ta[i*3+1]:4.3f};'
f'RMSE {va[i*3+2]:6.3f}, {te[i*3+2]:6.3f}, {ta[i*3+2]:6.3f}.')
if va_mean_rmse < min_rmse:
torch.save(model.state_dict(), best_model_path)
min_rmse = va_mean_rmse
stop = 0
else:
stop += 1
if stop == 10:
break
model.load_my_state_dict(torch.load(best_model_path))
print('Best Results:')
#調用之前的最佳模型進行預測
model.load_my_state_dict(torch.load('MODEL/best_model.h5'))
model.eval()
#使用該模型對未來給定步長進行預測
norm_data = scaler.fit_transform(hist_data)
zz = torch.tensor(norm_data, dtype=torch.float32).to(device)
pred = model(zz)
preds.append(pred.data.cpu().numpy())
圖5-2展示了某一天SCNN模型的預測結果與真實數據的對比情況,橫坐標是當天的小時數。當天預測的總業務量的相對誤差為1.43%。
圖5-3展示了3-6月模型對于每天業務量的預測結果和真實結果的對比情況。整體預測值與實際值相對誤差為1.34%。
從上圖可以看出,平峰期模型的預測結果與實際情況相差不大,表現相對穩定。但是在五一、端午等節假日期間,模型預測與實際業務量的趨勢大體相同但是在一些峰值表現上存在差距。
推測存在三方面原因:
1)模型目前是根據歷史19年與23年的數據進行訓練的,是基于這兩年數據的表現結構進行的預測,24年存在一些額外的營銷活動、以及24年與23年用戶的出行需求也有所不同(23年因疫情放開導致用戶“報復性”出游帶來的出行需求增大,24年則可能趨于平穩)。
2)目前針對高峰期的模型,采用的訓練數據只有19年與23年的12個節假日(因特殊性未使用春節數據),不充足的數據量會導致模型學到的結構規律不夠穩定。
3)目前針對各個節假日使用的是同一個高峰期的SCNN模型,但其實各個節假日因放假時長不同,結構規律也不同,并不能完全用一個模型來進行預測,因此會導致預測結果的偏差。
5.3 落地應用&未來改進
將模型在2024年3-6月上的預測結果同步業務并獲得接受之后,目前已將模型使用的訓練數據更新到2024年6月,同時將此方法應用在對未來兩個季度的每日業務量預測上,持續更新并以看板的形式呈現。后續考慮可以在以下四點上進行優化:
1)將每天預測的結果與真實結果之間的GAP作為模型目標函數的一部分,讓模型更好地進行自我更新調整,得到更準確的預測結果。
2)將方法平臺化、工具化,能夠支持業務方自行選擇想要預測的時間周期及變量,模型將根據該變量的歷史表現判定是否適用SCNN模型,如果適用則進行訓練并得到最佳模型,最終基于此模型輸出預測結果。
3)目前模型對于節假日的預測表現并不十分穩定,主要原因也是訓練的數據集過少且每年的節假日的營銷手段不完全一致,并不能很好地固化每個節假日的結構特點。后續只有不斷積累數據,同時也擴充一些“場外因素”,例如通過外部的用戶搜索量、社媒上的出行討論度、營銷活動力度等等來及時反映出當前節假日的出行熱度,從而更好地幫助模型預測此次節假日的業務量情況。
4)目前針對不同的節假日采用的是同一個節假日的SCNN模型,但其實各個節假日的結構特征不完全一致,最理想的狀態是每個節假日有自己專屬的SCNN模型來學習并預測,但現在的數據量暫不能達到訓練的要求,只能等數據量的擴充或是在同一個節假日模型中加入參數區分不同的節假日來提升模型對不同節假日結構特點的適配性。
六、方法拓展
本文介紹的SCNN模型通過拆解長短周期項、季節性項以及序列間相關性項,對時序數據輸出“點估計型”的預測結果。這可以和之前介紹過的CausalImpact相結合,在CausalImpact中也是先對時序數據進行擬合預測得到反事實值,然后得到預測值與真實值之間的差距來評估策略的提升效應。在CausalImpact中默認使用的時序模型是BSTS,但也可以自定義時序模型,例如我們可以自己訓練SCNN模型,然后將此模型當做時序模型放到CausalImpact中計算策略的效應值。
from causalimpact.misc import standardize
normed_data, _ = standardize(data.astype(np.float32)) #標準化數據
obs_data = normed_data.iloc[:70, 0]
# 使用其他時序模型來進行擬合得到反事實值
linear_level = tfp.sts.LocalLinearTrend(observed_time_series=obs_data)
linear_reg = tfp.sts.LinearRegression(design_matrix=normed_data.iloc[:, 1:].values.reshape(-1, normed_data.shape[1] -1))
model = model.load_my_state_dict(torch.load('MODEL/best_SCNN_model.h5'))
# 將自義定時序模型代入CausalImpact包中
ci = CausalImpact(data, pre_period, post_period, model=model)
七、總結
本文介紹了一種多元時間序列數據的預測模型,通過將數據拆解為長周期、季節性、短周期及序列間相關性四種結構,對數據進行解耦、分塊預測、通過神經網絡對預測結果進行融合來得到最終的輸出結果;通過重構損失函數、置零殘差項等方式提升了模型的魯棒性與準確性,能夠最大程度上學習到序列背后的結構特點并做出盡可能準確的預測結果。
本文進一步介紹了該方法的實現方式以及如何將該方法應用在實際的業務量預測上,結合具體的業務場景介紹了SCNN模型的具體使用步驟以及注意事項,同時就實踐結果分析了該方法目前在應用上的優點與不足,以及后續的優化方向。
未來隨著數據量的擴充以及模型的完善,有望針對不同類型的時序數據進行特定的結構學習與預測,另一方面,也可以通過使用SCNN模型進行反事實預測,將該方法拓展到CausalImpact等一些因果推斷的評估場景中,更好地發揮其捕捉數據結構進行合理預測的優勢。