機器學習可以被用於時間序列預測。
在機器學習能使用之前,時間序列預測需要被重新轉化成有監督學習。將一個序列組合成成對的輸入輸出序列。
在這篇教程中,你會發現如何通過使用機器學習算法將單變量和多變量的時間預測序列轉化成有監督學習。
在看完這篇教程之后,你會知道:
1、如何寫一個將時間序列的數據集轉化成有監督學習的數據集的函數。
2、如何將機器學習用於一個單變量的時間序列。
3、如何將機器學習用於一個多變量的時間序列。
開始吧~
- 時間序列vs有監督學習
開始之前,我們先來看看時間序列和有監督學習的數據。
一個時間預測序列是一串通過時間索引排序的數字序列,這可以被認為是一列排好序的數值。
比如:
0 1 2 3 4 5
一個有監督學習將輸入(X)和輸出(Y)進行組合,以便於算法可以學習如何預測從輸入預測輸出。
比如:
X, Y 1, 2 2, 3 3, 4 4, 5 5, 6
- Pandas的shift()函數
一個幫助將時間序列轉化成有監督學習任務的關鍵函數是Pandas shift() 函數。
給定一個DataFrame,shift()函數可以被用來創造一列數據的副本,然后將數據向前推進或者向后回退。
這個行為要求在監督學習的形式內創造一列滯后的觀察值作為時間序列的預測值。
讓我們看一下例子吧~
我們定義一個模擬的含有十個數據的時間序列,在DateFrame這樣創造:
from pandas import DataFrame df = DataFrame() df['t'] = [x for x in range(10)] print(df)
運行這個小例子,會打印時間序列數據以及它們的列索引
t 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9
我們可以通過在頂上插入一個新行使得這一列的時間序列數據滯后原來一個時間步長。因為新的行沒有數據,我們可以使用NaN來表示沒有數據。
shift()函數可以自動幫我們做這個事:
from pandas import DataFrame df = DataFrame() df['t'] = [x for x in range(10)] df['t-1'] = df['t].shift(1) print(df)
運行這個小例子會得到兩行數據,第一列是原來的,第二列是轉化后的。
可以看出來將序列向前推進一個時間步可以給我們一個原始的有監督學習數據集,盡管X和Y是錯誤的順序。忽略列中的行標記。第一行被拋棄因為有NaN數值。第二行表示輸入為0.0時,輸出為1。
t t-1 0 0 NaN 1 1 0.0 2 2 1.0 3 3 2.0 4 4 3.0 5 5 4.0 6 6 5.0 7 7 6.0 8 8 7.0 9 9 8.0
可以看到,如果我們重復上述過程給shift()函數2,3...等參數,就可以創造一個可以被用來預測輸出Y的長的輸入序列X。
shift()函數也可以接收負整數為參數,負整數會將數據提前並且在序列最后加NaN。
from pandas import DataFrame df = DataFrame() df['t'] = [x for x in range(10)] df['t+1'] = df['t'].shift(-1) print(df)
運行這個小例子,會得到:
t t+1 0 0 1.0 1 1 2.0 2 2 3.0 3 3 4.0 4 4 5.0 5 5 6.0 6 6 7.0 7 7 8.0 8 8 9.0 9 9 NaN
在時間序列預測中,(t)表示當前時間,未來將要被預測的時間是(t+1, t+2,...,t+n),過去被已經被觀察的時間是(t-1, t-2,..., t-n)。
我們已經看到對時間序列如何進行正向或者逆向的轉化組成輸入和輸出形式的DateFrame,並將此作為有監督學習的數據集。這種方法不僅可以組成X->y的預測,還可以組成輸入和輸出都是序列的X->Y的預測。
- The series_to_supervised() Function
在這部分,我們會定義一個新的python函數叫做 series_to_supervised() ,它可以完成將單變量或者多變量的時間序列數據轉化成有監督學習的數據。
這個函數有四個參數:
- data:2D的numpy數組或者列表存儲序列。
- n_in:將時間序列滯后n_in個時間步,取值范圍為[1...len(data)],默認值為1。
- n_out:輸出y的個數,取值范圍為[1...len(data)-1]。默認值為1。
- dropnan:布爾值,表示是否丟棄NaN值。默認值為True,表示丟棄。
- return:panda DataFrame
from pandas import DataFrame from pandas import concat def series_to_supervised(data, n_in=1, n_out=1, dropnan=True): """ Frame a time series as a supervised learning dataset. Arguments: data: Sequence of observations as a list or NumPy array. n_in: Number of lag observations as input (X). n_out: Number of observations as output (y). dropnan: Boolean whether or not to drop rows with NaN values. Returns: Pandas DataFrame of series framed for supervised learning. """ n_vars = 1 if type(data) is list else data.shape[1] df = DataFrame(data) cols, names = list(), list() # input sequence (t-n, ... t-1) for i in range(n_in, 0, -1): cols.append(df.shift(i)) names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)] # forecast sequence (t, t+1, ... t+n) for i in range(0, n_out): cols.append(df.shift(-i)) if i == 0: names += [('var%d(t)' % (j+1)) for j in range(n_vars)] else: names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)] # put it all together agg = concat(cols, axis=1) agg.columns = names # drop rows with NaN values if dropnan: agg.dropna(inplace=True) return agg
參考博客:https://machinelearningmastery.com/convert-time-series-supervised-learning-problem-python/