案例剖析:利用LSTM深層神經網路進行時間序列預測

格伯納發表於2018-09-10

本文將重點介紹如何使用LSTM神經網路架構,使用Keras和Tensorflow提供時間序列預測,特別是在股票市場資料集上,以提供股票價格的動量指標。

這個框架的程式碼可以在下面的GitHub repo中找到(它假設python版本3.5.x和requirements.txt檔案中的需求版本。偏離這些版本可能會導致錯誤):https://github.com/jaungiers/LSTM-Neural-Network-for-Time-Series-Prediction

什麼是LSTM神經元?

長期困擾傳統神經網路架構的基本問題之一是,如何能夠解釋依賴於資訊和上下文的輸入序列。該資訊可以是句子中的前一個單詞,以方便通過上下文來預測下一個單詞可能是什麼,或者它也可以是序列的時序資訊。

簡而言之,傳統的神經網路每次都會採用獨立的資料向量,並且沒有記憶體概念來幫助他們處理需要記憶體的任務。

早期嘗試解決這個問題的方法是對網路中的神經元使用簡單的反饋型別方法,其中輸出被反饋到輸入中,以提供最後看到的輸入的上下文。這些被稱為遞迴神經網路(RNN)。雖然這些RNN在一定程度上起作用,但它們有一個相當大的缺點,因此它們的一些重要用途都會導致產生消失梯度的問題。我們不會進一步擴充套件討論它,而是說由於這個問題導致RNN不適合大多數現實問題,因此,我們需要找到別的解決辦法。

這就是長期短期記憶(LSTM)神經網路起作用的地方。與RNN神經元一樣,LSTM神經元在其管道中可以保持記憶,以允許解決順序和時間問題,而不會出現影響其效能的消失梯度問題。

許多關於它的研究論文和文章都可以在網上找到,它們在數學細節上討論了LSTM細胞的工作原理。然而,在本文中,我們不會討論LSTM的複雜工作原理,因為我們更關心它們的使用。

對於上下文,下面是LSTM神經元的典型內部工作圖。它由若干層和逐點操作組成,這些操作充當資料輸入、輸出的門,為LSTM單元狀態提供資訊。這種單元狀態是通過網路和輸入保持長期記憶和上下文。

案例剖析:利用LSTM深層神經網路進行時間序列預測


一個簡單的正弦波示例

為了演示LSTM神經網路在預測時間序列中的使用,讓我們從最基本的事情開始,我們可以想到這是一個時間序列:可靠的正弦波。讓我們建立我們需要的資料,以便為LSTM網路訓練此函式的許多“振盪模型”。

程式碼資料資料夾中提供的資料包含我們建立的sinewave.csv檔案,該檔案包含5001個正弦波時間段,幅度和頻率為1(角頻率為6.28),時間差值為0.01。繪製時的結果如下所示:

案例剖析:利用LSTM深層神經網路進行時間序列預測

資料集為正弦波

現在我們有了資料,我們實際上想要實現什麼?簡單的說,我們只是希望LSTM從我們將提供的資料的設定視窗大小中學習正弦波,並且希望我們可以要求LSTM預測該系列中的第N步驟,並且它將繼續輸出正弦波。

我們將首先把CSV檔案中的資料轉換載入到pandas資料幀,然後將其用於輸出,它將為LSTM提供資料的numpy陣列。 Keras LSTM層的工作方式是採用3維(N,W,F)的numpy陣列,其中N是訓練序列的數量,W是序列長度,F是每個序列的特徵數。我們選擇使用50的序列長度(讀取視窗大小)來允許網路,因此可以在每個序列中看到正弦波的形狀,有希望自己建立基於序列的序列模式。

序列本身是滑動視窗,因此每次移動1,導致與先前視窗不斷重疊。當繪製時,序列長度為50的典型訓練視窗如下所示:

案例剖析:利用LSTM深層神經網路進行時間序列預測

Sinewave資料集訓練視窗

為了載入這些資料,我們在程式碼中建立了一個DataLoader類,為資料載入層提供抽象。您會注意到,在初始化DataLoader物件時,會傳入檔名, 並確定用於訓練與測試的資料百分比的拆分變數,且允許選擇一列或多列資料的列變數用於單維或多維分析。

案例剖析:利用LSTM深層神經網路進行時間序列預測


在我們有一個允許我們載入資料的資料物件之後,需要構建深度神經網路模型。同樣,對於抽象,我們的程式碼框架使用的是模型類和config.json檔案,在給定儲存在配置檔案中的所需體系結構和超引數的情況下,輕鬆構建模型的例項。構建我們網路的主要功能是build_model()函式,它接收經過解析的配置檔案。

案例剖析:利用LSTM深層神經網路進行時間序列預測


此功能程式碼如下所示,可以輕鬆擴充套件,以便將來在更復雜的體系架構上使用。

載入資料並建立模型後,我們現在可以繼續使用我們的訓練資料訓練模型。為此,我們建立了一個單獨的執行模組,它將利用我們的模型和模組抽象將它們組合起來進行訓練、輸出和視覺化。

下面是訓練我們模型的一般執行執行緒程式碼:

案例剖析:利用LSTM深層神經網路進行時間序列預測


對於輸出,我們將執行兩種型別的預測:第一種將以逐點方式進行預測,即我們每次僅預測單個點,將此點繪製為預測,然後沿著下一個視窗進行預測使用完整的測試資料並再次預測下一個點。

我們要做的第二個預測是預測一個完整的序列,我們只用訓練資料的第一部分初始化一次訓練視窗。然後模型預測下一個點,我們就移動視窗,就像逐點方法一樣。不同之處在於我們使用我們在先前預測中預測的資料來進行下一步預測。在第二步中,這意味著只有一個資料點(最後一個點)來自先前的預測。在第三個預測中,最後兩個資料點將來自先前的預測,依此類推。經過50次預測後,我們的模型將隨後根據自己的先前預測進行預測。這使我們可以使用該模型預測未來的許多時間步驟,但由於它是在預測的基礎上進行預測,這反過來可以反過來又可以預測,將增加預測的錯誤率,我們會預測的更遠。

下面我們可以看到逐點預測和完整序列預測的程式碼和相應的輸出。

案例剖析:利用LSTM深層神經網路進行時間序列預測


案例剖析:利用LSTM深層神經網路進行時間序列預測

逐點正弦波預測

案例剖析:利用LSTM深層神經網路進行時間序列預測

正弦波全序列預測

作為參考,可以在下面的配置檔案中看到用於正弦波示例的網路架構和超引數。

案例剖析:利用LSTM深層神經網路進行時間序列預測


在真實資料的疊加下我們可以看到,只需1個時期和相當小的訓練資料集,LSTM深度神經網路就可以很好地預測正弦函式。

您可以看到,隨著我們對未來越來越多的預測,誤差幅度會隨著先前預測中的誤差在用於未來預測時被越來越多地放大並且增加。因此,我們看到在完整序列示例中,預測越遠,我們預測預測的頻率和幅度與真實資料相比就越不準確。然而,由於sin函式是一個非常簡單的零噪聲振盪函式,它仍然可以在沒有過度擬合的情況下很好地預測它。這很重要,因為我們可以通過增加時期和取出dropout 層來輕鬆地過度擬合模型。這個訓練資料幾乎完全準確,與測試資料具有相同的模式,但對於其他現實世界的例子,將模型過度擬合到訓練資料上會導致測試精度直線下降,因為模型不會一概而論。

在下一步中,我們將嘗試在此類真實資料上使用該模型來檢視效果。

不那麼簡單的股票市場

我們在精確的逐點基礎上預測了幾百個正弦波的步長。因此,我們現在可以在股市時間序列中做同樣的事情並立即獲利,對嗎?不幸的是,在現實世界中,這並不是那麼簡單。

與正弦波不同,股票市場時間序列不是可以對映的任何特定靜態函式。描述股票市場時間序列運動的最佳屬性是隨機遊走。作為隨機過程,真正的隨機遊走沒有可預測的模式,因此嘗試對其進行建模將毫無意義。幸運的是,許多方面都在持續爭論說股票市場不是一個純粹的隨機過程,這使我們可以理解時間序列可能有某種隱藏模式。正是這些隱藏的模式,LSTM深度網路成為預測的主要候選者。

此示例將使用的資料是資料資料夾中的sp500.csv檔案。此檔案包含2000年1月至2018年9月的標準普爾500股票指數的開盤價、最高價、最低價、收盤價以及每日交易量。

在第一個例子中,我們將僅使用收盤價建立單維模型。調整config.json檔案以反映新資料,我們將保持大部分引數相同。然而,需要做出的一個改變是,與只有-1到+1之間的數值範圍的正弦波不同,收盤價是股票市場不斷變化的絕對價格。這意味著如果我們試圖在不對其進行標準化的情況下訓練模型,它就永遠不會收斂。

為了解決這個問題,我們將採用每個n大小的訓練/測試資料視窗,並對每個視窗進行標準化以反映從該視窗開始的百分比變化(因此點i = 0處的資料將始終為0)。我們將使用以下等式進行歸一化,然後在預測過程結束時進行去標準化,以獲得現實世界數量的預測:

n =價格變化的標準化列表[視窗]

p =調整後的每日回報價格的原始清單[視窗]

正常化: 

案例剖析:利用LSTM深層神經網路進行時間序列預測



反規範化:

案例剖析:利用LSTM深層神經網路進行時間序列預測


我們已將normalise_windows()函式新增到DataLoader類以執行此轉換,並且配置檔案中包含布林規範化標誌,表示這些視窗的規範化。

案例剖析:利用LSTM深層神經網路進行時間序列預測


隨著視窗的標準化,我們現在可以執行模型,就像我們針對正弦波資料執行模型一樣。但是,我們在執行這些資料時做了一個重要的改變,而不是使用我們框架的model.train()方法,只是使用我們建立的model.train_generator()方法。我們這樣做是因為我們發現在嘗試訓練大型資料集時很容易耗盡記憶體,因為model.train()函式將完整資料集載入到記憶體中,然後將規範化應用於記憶體中的每個視窗,容易導致記憶體溢位。因此,我們使用了Keras的fit_generator()函式,允許使用python生成器動態訓練資料集來繪製資料,這意味著記憶體利用率將大大降低。下面的程式碼詳細說明了用於執行三種型別預測的新執行執行緒(逐點,完整序列和多序列)。

案例剖析:利用LSTM深層神經網路進行時間序列預測


案例剖析:利用LSTM深層神經網路進行時間序列預測


如上所述,在單個逐點預測上執行資料可以非常接近匹配返回的內容。但這有點欺騙性。經過仔細檢查,會發現預測線由奇異的預測點組成,這些預測點在它們後面具有整個先前的真實歷史視窗。因此,網路不需要了解時間序列本身,除了下一個點很可能不會離最後一點太遠。因此,即使它得到錯誤點的預測,下一個預測也將考慮真實的歷史並忽略不正確的預測,然後再次允許產生錯誤。

雖然這對於下一個價格點的精確預測而言最初聽起來並不樂觀,但它確實有一些重要的用途。雖然它不知道確切的下一個價格是多少,但它確實能夠準確地表示下一個價格的範圍。

此資訊可用於諸如波動率預測等應用(能夠預測市場中高或低波動的時段對特定交易策略非常有利),或遠離交易這也可用作良好指標用於異常檢測。可以通過預測下一個點,然後將其與真實資料進行比較來實現異常檢測,並且如果真實資料值與預測點顯著不同,則可以針對該資料點標出異常標記。

案例剖析:利用LSTM深層神經網路進行時間序列預測

標準普爾500指數逐點預測

繼續進行完整的序列預測,似乎這被證明是對這種型別的時間序列最不有用的預測(至少使用這些超引數訓練這個模型)。我們可以看到預測開始時的輕微碰撞,其中模型遵循某種型別的動量,但是很快我們可以看到模型確定最佳模式是收斂到時間序列的某個均衡。在這個階段,這可能看起來並沒有提供太多價值,但是均值迴歸交易者可能會在那裡宣稱,該模型只是找到價格序列在波動率被消除時將恢復的平均值。

案例剖析:利用LSTM深層神經網路進行時間序列預測

標準普爾500指數全序列預測

最後,我們對該模型進行了第三種預測,我將其稱為多序列預測。這是完整序列預測的混合,因為它仍然使用測試資料初始化測試視窗,預測下一個點,然後使用下一個點建立一個新視窗。但是,一旦它到達輸入視窗完全由過去預測組成的點,它就會停止,向前移動一個完整的視窗長度,用真實的測試資料重置視窗,然後再次啟動該過程。實質上,這為測試資料提供了多個趨勢線預測,以便能夠分析模型獲得未來動量趨勢的程度。

案例剖析:利用LSTM深層神經網路進行時間序列預測

標準普爾500指數多序列預測

我們可以從多序列預測中看出,網路似乎正確地預測了絕大多數時間序列的趨勢(和趨勢幅度)。雖然不完美,但它確實表明了LSTM深度神經網路在順序和時間序列問題中的有用性。通過仔細的超引數調整,肯定可以實現更高的準確性。

結論

雖然本文的目的是在實踐中給出LSTM深度神經網路的一個工作例項,但它只是觸及了它們在順序和時間問題中的潛力和應用的表面。

在撰寫本文時,LSTM已成功應用於眾多現實問題中,從此處所述的經典時間序列問題到文字自動糾正、異常檢測和欺詐檢測,以及開發自動駕駛汽車技術的核心。

目前使用上述LSTM存在一些侷限性,特別是在使用金融時間序列時,該系列本身具有很難建模的非平穩特性(儘管在使用貝葉斯深度神經網路方法方面取得了進展)解決時間序列的非平穩性問題。同樣對於一些應用,還發現基於注意力的神經網路機制的新進展已經超過LSTM(並且LSTM與這些基於注意力的機制相結合也優於其自身)。

然而,截至目前,LSTM在更經典的統計時間序列方法上提供了顯著的進步,能夠非線性地建模關係,並且能夠以非線性方式處理具有多個維度的資料。

我們開發的框架的完整原始碼可以在以下GitHub頁面上的MIT許可證下找到:https: //github.com/jaungiers/LSTM-Neural-Network-for-Time-Series-Prediction

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31509949/viewspace-2213894/,如需轉載,請註明出處,否則將追究法律責任。

相關文章