時間序列的介紹、理論實作應用
前言
時間序列的問題,是在機器學習的知識領域中,應用和需求最廣泛的問題之一。
當我們輸入一個時間序列:
- 如果我們想知道這個序列的數值會如何變化,那麼這是一個回歸問題
- 如果想知道這一串序列代表的是A還是B,那麼則是一個分類問題。
儘管通常與時間序列相關的問題,都是回歸問題,例如股票、機率等等。不過我們還是可以用幾乎相同的方法來處理時間序列的分類問題。
介紹: 時間序列是什麼
你可以把每一段時間序列都當成如上圖(Fig.1)所示的礦車,每一次礦車進入山洞後,都會裝新的資料出來,而礦車的長度是固定的,所以能裝的資料長度也會受到限制。但如果資料短於礦車長度,他還是可以順利的把這一批資料運出來(只是會有幾節車廂是空的,我們會放入空白符號或None)。
上面的舉例,應該可以讓你理解時間序列跟裡面資料的關係。
而當礦車回到卸貨站,也就是我們要開始讀取時間序列資料的時候。我們會依序讀取這一批資料,有時也會特意反過來讀取。總之讀取資料的過程會是有順序的。
時間序列長什麼樣子
如上圖(Fig.2)所示,就是一種可能的時間序列的資料。儘管看起來似乎有週期性,但時間序列內的資料不必然有週期性。如果發現資料有週期性的話可以透過傅立葉轉換之類的方法得到更多特徵。
像上圖(Fig.3)這種架構也是一種特別的時間序列,我們稱之為seq2seq的模型,通常用於NLP之類的翻譯或語音機器人應用。
上圖中的x1, x2, x3, x4可能是4個不同的單字,比如說 「今天好熱」,而這四個字經Encoder(編碼器)所壓縮出來的隱藏向量c1, c2, c3,可以透過Decoder(解碼器)重新變成新的句子,比如說:「去吃冰」。他會產生什麼句子取決於在訓練時我們給這個Encoder-Decoder的模型架構什麼資料。而Decoder如何決定要吐出什麼單字則是透過訓練的時候x1, x2, x3, x4這個序列所對應的Y1, Y2, Y3是什麼而定。這是一種監督式學習。
我們會怎麼進行機器學習
- 快速的做必須做的資料處理
- 找到適當演算法(快速訓練、結構單純),快速得到一個參考分數。
- 選擇適當演算法,並盡可能快速的訓練並驗證。與參考分數比較。
- 找到幾個較好的演算法,做特徵工程或調參。
本文只專注在前三個步驟,因為最後的特徵工程和調參與案例相關。
簡單的時間序列 -股價預測
上面的圖片(Fig.4)是2014年8月到2017年9月之間,Tesla股價的折線圖。我們可以用時間序列的方式來透過這些價格的資料預測未來的資料,不過因為特徵太少(資訊量太少),所以大概準確率不會很高。
首先要先製作許多的時間短序列
透過Sliding window這個技巧我們可以把一筆長長的時序資料變成許多筆短短的時序資料。首先我們先抓第一和第二周的資料。然後我們再抓第二和第三周的資料。
後面的所有實驗都是基於這種方式得到訓練和測試資料
雖然左圖與右圖(Fig.5)看起來接不起來,不過實際上他們有7天的重疊。然後我們不斷重複每間隔一周就取兩周的資料,這種方法就叫做Sliding Windows。其中我們的Stride(步伐)相當於7,而window-size(視窗大小)相當於14。
然後我們可以拿這一籮筐的短時間序列資料去做訓練,訓練的目標相當於拿前13天的收盤價預測第14的收盤價。
你可以先用一個最簡單的模型判斷這些資料是否能有好成績。
Model-1: Zero-Rule model
我們想知道一個最天真的模型能夠得到什麼成績,這個模型叫做Zero-Rule Model,他永遠都認為y的值相當於訓練資料中y的平均值。(y_train.mean())
對訓練資料做預測並評估
用這種方法來預測訓練資料的時候,他的R2值應該等於0。R2其實就是把你的模型結果用來跟Zero-Rule model做比較。如果你覺得模型壞掉了,你可以用你的模型預測原本的訓練資料X,把他的結果跟訓練資料y一起計算R2,如果R2小於0的時候,表示你模型真的壞掉了。
然後我們用這種方法來評估y_test。可以看到R2是負的,這表示我們的模型在預測測試資料時是逆趨勢在預測的。這可以說明其實Tesla的收盤價正在往平均線以上成長。而且成長得滿快的。
Note: 我們把 90%的資料當成訓練資料 X_train, y_train, 剩下的 10%當成測試資料 X_test, y_test。這時候我們只有 95筆訓練資料、11筆測試資料。
Model-2: LSTM Model (長短期記憶模型)
LSTM是RNN的變形,主要是克服不容易訓練的缺點而誕生。我們可以用簡單的LSTM來進行預測。
模型訓練效果好不好?
可以看到,我們訓練時的R2指標是很高的(0.90),所以模型在訓練時訓練的不錯。而mse只有0.03,表示在預測時誤差不大,這代表模型的bias不會太高。
OverFitting?
我們可以看到在y_test上的成果,儘管R2比Zero-Rule好了一點(-0.25 -> -9)但還是一樣是負的,而mse則高達20。這表示在測試的時候我們的模型預測誤差很大。這種狀況表明了我們出現OverFitting。
為了判斷是不是真的OverFitting,上圖是我們把預測結果畫出來的模樣,可以看到在訓練資料上進行預測都還是滿好的,但在測試時效果卻很差,所以可以判斷是因為Overfitting導致我們預測失準了。
OverFitting可能是我們訓練了太多個Epochs、或是資料太少導致模型很容易OverFitting。
我們重新製作短時間序列資料,把Stride改為1,window-size改成7。這會讓我們的資料暴增7倍,看看效果如何。
我們用同樣用Zero-Rule model 和相同架構的LSTM model訓練並評估他們的分數,成果如下:
基本上在測試資料上的R2都比原來更低了,但mse是有縮小的。
Model3: 移動平均(moving average)
我們換另一個簡單的模型來取代原本的Zero-Rule Model。剛才我們是直接計算y值的總體平均。現在我們針對一個小區間(7天)的收盤價做移動平均。結果如下:
看起來顯然比Zero-Rule的效果要好得多,我們把現有的三個模型基於用Stride=1, window-size=7的Sliding-window方法產生的短時序資料能得到的預測結果畫出來看看,如下圖所示:
儘管移動平均看起來比較符合趨勢,但實際上如果計算模型的可信度(R2)和準確度(mse)都會是LSTM更好一些。
那麼目前最好的LSTM看起來還是很糟糕,怎麼辦呢?
我們大方向有三條路:調整目前LSTM模型的參數、換別的模型(包括新架構的LSTM)、重新做資料處理(特徵工程、基於EDA的資料處理)。
調整參數很容易實行,但要調得好很困難,因為DL是一個黑盒子。不過我們可以試著降低模型複雜度(把每一層的神經元減少)。
但以目前的模型而言,調整架構或換另一個模型這兩種方法都可以多做嘗試,例如你可以嘗試XGBoost(建議先做一些特徵工程)、或是用同樣Deep Learning的Conv1D(kernel = 3),事實上以這題而言,Conv1D的效果是最好的(Fig.14-c)。
根據實驗結果推測,Conv1D能表現得好是因為他能找到拐點出現的特徵,而LSTM表現不好是因為他的資料型態不太適合,我們把LSTM的輸入資料要的相關係數分別以矩陣和熱圖的方式呈現(Fig.15, 16)。整個資料有非常均勻的高度相關性,這很合理,因為收盤價一定與昨日高度相關,這會導致我們的LSTM很容易OverFitting。
舉個例子,你只要每次都猜第14天的收盤價 = 第13天的收盤價,你也會有相當高的成績(Fig.17)。
而LSTM太強的學習能力,尤其是跟時間相關的資訊特徵,反而會讓他學到某些沒意義的特徵,所以你可以簡單的透過Dropout或是其他方式增加模型複雜度,讓他不容易訓練。加了一層20%的Dropout後,成績如下所示(Fig.18):
另外補充使用XGBoost(最強的機器學習方法之一)做出來的結果,可以看到其實XGBoost並不擅長這種問題。(非常簡單的測試,沒有調懲罰項等等)
最實際的,還是重新處理資料
(ex: EDA、特徵工程)
目前我們只有使用收盤價,單純使用收盤價來預測收盤價其實資訊量是非常少的。事實上我們還可以找到開盤價、高點、低點等等,都放進去。這會讓模型能夠學習到其他特徵與收盤價之間的關係。
事實上,機器學習的強項也是在於能夠從大量資料中學到特徵,並某種程度克服特徵之間的低相關性,找到更好的Space來分解特徵。而深度學習不但能夠把輸入資料投影到一個非常高維的Space以找出回歸線,也能夠同時找出特徵來同時對資料做處理。在某些問題上,深度學習的效果會非常顯著。
或者,你可以把目前的輸入資料做一些指數、對數轉換,讓特徵更豐富,這會讓模型學習到更複雜的特徵組合。