編者按:本文將介紹如何基于Keras和Tensorflow,用LSTM進行時間序列預測。文章數據來自股票市場數據集,目標是提供股票價格的動量指標。
GitHub:github.com/jaungiers/LSTM-Neural-Network-for-Time-Series-Prediction
什么是LSTM?
自提出后,傳統神經網絡架構一直沒法解決一些基礎問題,比如解釋依賴于信息和上下文的輸入序列。這些信息可以是句子中的某些單詞,我們能用它們預測下一個單詞是什么;也可以是序列的時間信息,我們能基于時間元素分析句子的上下文。
簡而言之,傳統神經網絡每次只會采用獨立的數據向量,它沒有一個類似“記憶”的概念,用來處理和“記憶”有關各種任務。
為了解決這個問題,早期提出的一種方法是在網絡中添加循環,得到輸出值后,它的輸入信息會通過循環被“繼承”到輸出中,這是它最后看到的輸入上下文。這些網絡被稱為遞歸神經網絡(RNN)。雖然RNN在一定程度上解決了上述問題,但它們還是存在相當大的缺陷,比如在處理長期依賴性問題時容易出現梯度消失。
這里我們不深入探討RNN的缺陷,我們只需知道,既然RNN這么容易梯度消失,那么它就不適合大多數現實問題。在這個基礎上,Hochreiter&Schmidhuber于1997年提出了長期短期記憶網絡(LSTM),這是一種特殊的RNN,它能使神經元在其管道中保持上下文記憶,同時又解決了梯度消失問題。具體工作原理可讀《一文詳解LSTM網絡》。
上圖是LSTM的一個典型內部示意圖,它由若干節點和若干操作組成。其中,操作充當輸入門、輸出門和遺忘門,為節點狀態提供信息。而節點狀態負責在網絡中記錄長期記憶和上下文。
一個簡單的正弦曲線示例
為了演示LSTM在預測時間序列中的作用,我們先從最基礎的開始:一個時間序列——標準正弦曲線。
代碼數據文件夾中提供的數據包含我們創建的sinewave.csv文件,該文件包含5001個正弦曲線時間段,幅度和頻率為1(角頻率為6.28),時間差為0.01。它的圖像如下所示:
正弦曲線數據集
有了數據,接下來就是實現目標。在這個任務中,我們希望LSTM能根據提供的數據學習正弦曲線,并預測此后的N步,持續輸出曲線。
為了做到這一點,我們需要先對CSV文件中的數據進行轉換,把處理后的數據加載到pandas的數據框架中。之后,它會輸出numpy數組,饋送進LSTM。Keras的LSTM一般輸入(N, W, F)三維numpy數組,其中N表示訓練數據中的序列數,W表示序列長度,F表示每個序列的特征數。
在這個例子中,我們使用的序列長度是50(讀取窗口大小),這意味著網絡能在每個序列中都觀察到完整的正弦曲線形狀,便于學習。
序列本身是滑動窗口,因此如果我們每次只移動1,所得圖像其實和先前的圖像是完全一樣的。下面是我們在示例中截取的窗口圖像:
為了加載這些數據,我們在代碼中創建了一個DataLoader類。你可能會注意到,在初始化DataLoader對象時,會傳入文件名、傳入確定用于訓練與測試的數據百分比的拆分變量,以及允許選擇一列或多列數據的列變量用于單維或多維分析。
當我們有一個允許加載數據的數據對象之后,就是時候準備構建深層神經網絡模型了。我們的代碼框架利用模型類型和config.json文件,再加上存儲在配置文件中的架構和超參數,可以輕松構建出模型。其中執行構建命令的主要函數是build_model(),它負責接收解析的配置文件。
這個函數的代碼如下所示,它可以輕松擴展,以便用于更復雜的架構。
加載數據并建立模型后,現在我們可以用訓練數據訓練模型。如下代碼所示,我們創建了一個單獨的運行模塊,它會利用我們的模型和DataLoader一起訓練,輸出預測結果和可視化。
對于輸出,我們會進行兩種類型的預測:一是逐點預測,即先讓模型預測單個點的值,在圖中繪出位置,然后移動滑動窗口,用完整的測試數據預測下個點的值。二是預測一個完整序列,即只用訓練數據的第一部分初始化一次訓練窗口,然后就像逐點預測一樣,不斷移動滑動窗口并預測下一個點。
和第一種做法不同的是,第二種做法是在用預測所得的數據進行預測,即在第二次預測時,模型所用數據中有一個數據點(最后一個點)來自之前的預測;第三次預測時,數據中就有兩個點來自之前的預測……以此類推,到第50次預測時,測試集里的數據已經完全是預測的數據。這意味著模型可預測的時間序列被大大延長。
逐點預測結果
完整序列預測結果
作為參考,你可以在下面的配置文件中看到用于正弦曲線示例的網絡架構和超參數。
我們可以從上面兩幅圖中發現,如果用第二種方法進行預測,隨著測試集中被不斷加入新的預測數據點,模型的性能會漸漸下降,預測結果和真實結果的誤差越來越大。但正弦函數是一個非常簡單的零噪聲震蕩函數,總體來看,我們的模型在沒有過擬合的同時還是能很好的模型曲線大致情況的。
接下來,就讓我們在股票數據上試試LSTM。
沒那么簡單的股票市場
很多股民都做過這樣一個夢:如果我能準確預測大盤走向,那一夜暴富豈不是手到擒來?但一覺醒來,現實是殘酷的,預測這件事并不像數字模擬那么簡單。
和正弦曲線不同,股票市場的時間序列并不是某個特定靜態函數的映射,它最明顯的屬性是隨機性。真正的隨機是不可預測的,也沒有預測的價值,但是,很多人相信股票市場不是一個純粹的隨機市場,它的時間序列可能存在某種隱藏模式。而根據上文的介紹,LSTM無疑是捕捉這種長期依賴關系的一個好方法。
下文使用的數據是Github數據文件夾中的sp500.csv文件。此文件包含2000年1月至2018年9月的標準普爾500股票指數的開盤價、最高價、最低價、收盤價以及每日交易量。
在第一個例子中,正弦曲線的取值范圍是-1到1,這和股票市場不同,收盤價是個不斷變化的絕對價格,這意味著如果我們不做歸一化處理就直接訓練模型,它永遠不會收斂。
為了解決這個問題,我們設訓練/測試的滑動窗口大小為n,對每個窗口進行歸一化,以反映從該窗口開始的百分比變化。
n = 價格變化的歸一化列表[滑動窗口]
p = 調整后每日利潤的原始列表[滑動窗口]
歸一化:ni= pi/p0- 1
反歸一化:pi= p0( ni+ 1)
處理完數據后,我們就可以和之前一樣運行模型。但是,我們做了一個重要的修改:不使用model.train() ,而是用model.traingenerator()。這樣做是為了在處理大型數據集時節約內存,前者會把完整數據集全部加載到內存中,然后一個窗口一個窗口歸一化,容易內存溢出。此外,我們還調用了Keras的fitgenerator()函數,用python生成器動態訓練數據集來繪制數據,進一步降低內存負擔。
在之前的例子中,逐點預測的結果比完整序列預測更精確,但這有點欺騙性。在這種情況下,除了預測點和最后一次預測的數據點之間的距離,神經網絡其實不需要了解時間序列本身,因為即便它這次預測錯誤了,在進行下一次預測時,它也只會考慮真實結果,完全無視自己的錯誤,然后繼續產生錯誤預測。
雖然這聽起來不太妙,但其實這種方法還是有用的,它至少能反映下一個點的范圍,可用于波動率預測等應用。
逐點預測結果
接著是完整序列預測,在正弦曲線那個例子中,這種方法的偏差雖然越來越大,但它還是保留了整體波動形狀。如下圖所示,在復雜的股票價格預測中,它連這個優勢都沒了,除了剛開始橙線略有波動,它預測的整體趨勢是一條水平線。
完整序列預測結果
最后,我們對該模型進行了第三種預測,我將其稱為多序列預測。這是完整序列預測的混合產物,因為它仍然使用測試數據初始化測試窗口,預測下一個點,然后用下一個點創建一個新窗口。但是,一旦輸入窗口完全由過去預測點組成,它就會停止,向前移動一個完整的窗口長度,用真實的測試數據重置窗口,然后再次啟動該過程。
實質上,這為測試數據提供了多個趨勢線預測,以便我們評估模型對未知數據的預測性能。
多序列預測結果
如上圖所示,神經網絡似乎正確地預測了絕大多數時間序列的趨勢(和趨勢幅度),雖然不完美,但它確實表明LSTM在時間序列問題中確實有用武之地。
結論
雖然本文給出了LSTM應用的一個示例,但它只觸及時間序列預測問題的表面。現如今,LSTM已成功應用于眾多現實問題,從文本自動糾正、異常檢測、欺詐檢測到自動駕駛汽車技術開發。
它還存在一些局限性,特別是在金融時間序列任務上,通常這類任務很難建模。此外,一些基于注意力機制的神經網絡也開始在其他任務上表現出超越LSTM的性能。
但截至目前,LSTM相比傳統神經網絡還是進步明顯,它能夠非線性地建模關系并以非線性方式處理具有多個維度的數據,這是幾十年前的人們夢寐以求的。
-
神經網絡
+關注
關注
42文章
4765瀏覽量
100565 -
keras
+關注
關注
2文章
20瀏覽量
6080 -
rnn
+關注
關注
0文章
88瀏覽量
6875
原文標題:基于LSTM深層神經網絡的時間序列預測
文章出處:【微信號:jqr_AI,微信公眾號:論智】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論