0
本文作者: 恒亮 | 2017-03-30 14:11 |
雷鋒網(wǎng)按:本文源自美國(guó)機(jī)器學(xué)習(xí)專家 Jason Brownlee 的博客,雷鋒網(wǎng)編譯。
要將機(jī)器學(xué)習(xí)算法應(yīng)用于時(shí)間序列數(shù)據(jù),需要特征工程的幫助。
例如,單變量的時(shí)間序列數(shù)據(jù)集由一系列觀察結(jié)果組成,它們必須被轉(zhuǎn)換成輸入和輸出特征,才能用于監(jiān)督性學(xué)習(xí)算法。
但這里有一個(gè)問(wèn)題:針對(duì)每個(gè)時(shí)間序列問(wèn)題,你可以處理的特征類型和數(shù)量,卻并沒(méi)有明確的限制。當(dāng)然,古典的時(shí)間序列分析工具(如相關(guān)圖correlogram)可以幫助評(píng)估滯后變量(lag variables),但并不能直接幫助開(kāi)發(fā)者對(duì)其他類型的特征進(jìn)行選擇,例如從時(shí)間戳(年、月、日)和移動(dòng)統(tǒng)計(jì)信息(如移動(dòng)平均線moving average)衍生的特征。
因此,我們將在本教程中探討如何利用基于特征重要性和特征選擇的機(jī)器學(xué)習(xí)工具處理時(shí)間序列問(wèn)題。
通過(guò)本教程的學(xué)習(xí),你將了解:
● 如何創(chuàng)建和解釋滯后觀察的相關(guān)圖。
● 如何計(jì)算和解釋時(shí)間序列特征的重要性得分。
● 如何對(duì)時(shí)間序列輸入變量進(jìn)行特征選擇。
本教程共分為如下六個(gè)部分:
1. 載入每月汽車銷量數(shù)據(jù)集:即載入我們將要使用的數(shù)據(jù)集。
2. 平穩(wěn)化:講述如何使數(shù)據(jù)集平穩(wěn)化,以便于后續(xù)的分析和預(yù)測(cè)。
3. 自相關(guān)圖:講述如何創(chuàng)建時(shí)間序列數(shù)據(jù)的相關(guān)圖。
4. 時(shí)間序列到監(jiān)督學(xué)習(xí):將時(shí)間單變量的時(shí)間序列轉(zhuǎn)化為監(jiān)督性學(xué)習(xí)問(wèn)題。
5. 滯后變量的特征重要性:講述如何計(jì)算和查看時(shí)間序列數(shù)據(jù)的特征重要性得分。
6. 滯后變量的特征選擇:講述如何計(jì)算和查看時(shí)間序列數(shù)據(jù)的特征選擇結(jié)果。
在本教程中,我們將基于魁北克在 1960 到 1968 年的月度汽車銷量數(shù)據(jù)進(jìn)行講解。
原始數(shù)據(jù)可以在如下鏈接下載:
https://datamarket.com/data/set/22n4/monthly-car-sales-in-quebec-1960-1968
本例中,我們將下載后的數(shù)據(jù)集保存為 car-sales.csv 文件,同時(shí)刪去了文件中的腳注信息。
基于 Pandas 庫(kù)加載該數(shù)據(jù)集的代碼如下,我們將數(shù)據(jù)保存為一個(gè) Series 對(duì)象:
# line plot of time series
from pandas import Series
from matplotlib import pyplot
# load dataset
series = Series.from_csv('car-sales.csv', header=0)
# display first few rows
print(series.head(5))
# line plot of dataset
series.plot()
pyplot.show()
運(yùn)行以上實(shí)例后的打印情況如下(這里只列出了 5 行):
Month
1960-01-01 6550
1960-02-01 8728
1960-03-01 12026
1960-04-01 14395
1960-05-01 14587
Name: Sales, dtype: int64
完整數(shù)據(jù)的曲線圖如下所示:
從上圖我們可以看到汽車銷量數(shù)據(jù)明顯的季節(jié)性和日益增長(zhǎng)的變化趨勢(shì)。
這種季節(jié)性的變化和增長(zhǎng)趨勢(shì)雖然可以作為序列預(yù)測(cè)的關(guān)鍵特征,但如果需要探索其他的有助于我們做出序列預(yù)測(cè)的系統(tǒng)信號(hào),就必須將它們移除。
通常,我們將除去了季節(jié)性變化和增長(zhǎng)趨勢(shì)的時(shí)間序列稱為平穩(wěn)化序列。
為了消除這種季節(jié)性變化,通常采取季節(jié)差分的辦法,即生成所謂的季節(jié)性適配時(shí)間序列(seasonally adjusted time series)。
本例中季節(jié)性變化的變化周期似乎是一年(12個(gè)月)。下面的代碼展示了如何計(jì)算季節(jié)性適配時(shí)間序列,并將結(jié)果保存到文件 seasonally-adjusted.csv。
# seasonally adjust the time series
from pandas import Series
from matplotlib import pyplot
# load dataset
series = Series.from_csv('car-sales.csv', header=0)
# seasonal difference
differenced = series.diff(12)
# trim off the first year of empty data
differenced = differenced[12:]
# save differenced dataset to file
differenced.to_csv('seasonally_adjusted.csv')
# plot differenced dataset
differenced.plot()
pyplot.show()
代碼中,由于最初的 12 個(gè)月沒(méi)有更早的數(shù)據(jù)用以差分計(jì)算,因此被丟棄。最終得到的季節(jié)差分結(jié)果如下圖所示:
從圖中可以看出,我們通過(guò)差分運(yùn)算成功消除了季節(jié)性變化和增長(zhǎng)趨勢(shì)信息。
通暢情況下,我們根據(jù)與輸出變量的相關(guān)性來(lái)選擇時(shí)間序列的特征。
這被稱為自相關(guān)(autocorrelation),并包括如何繪制自相關(guān)圖,也稱為相關(guān)圖。 自相關(guān)圖展示了每個(gè)滯后觀察結(jié)果的相關(guān)性,以及這些相關(guān)性是否具有統(tǒng)計(jì)學(xué)的顯著性。
例如,下面的代碼繪制了月汽車銷量數(shù)據(jù)集中所有滯后變量的相關(guān)圖。
from pandas import Series
from statsmodels.graphics.tsaplots import plot_acf
from matplotlib import pyplot
series = Series.from_csv('seasonally_adjusted.csv', header=None)
plot_acf(series)
pyplot.show()
運(yùn)行后可以得到一張相關(guān)圖,或自相關(guān)函數(shù)(ACF)圖,如下所示。
圖中 x 軸表示滯后值,y 軸上 -1 和 1 之間則表現(xiàn)了這些滯后值的正負(fù)相關(guān)性。
藍(lán)色區(qū)域中的點(diǎn)表示統(tǒng)計(jì)學(xué)顯著性。滯后值為 0 相關(guān)性為 1 的點(diǎn)表示觀察值與其本身 100% 正相關(guān)。
可以看到,圖中在 1,2,12 和 17 個(gè)月顯示出了顯著的滯后性。
這個(gè)分析為后續(xù)的比較過(guò)程提供了一個(gè)很好的基準(zhǔn)。
通過(guò)將滯后觀察(例如t-1)作為輸入變量,將當(dāng)前觀察(t)作為輸出變量,可以將單變量的月度汽車銷量數(shù)據(jù)集轉(zhuǎn)換為監(jiān)督學(xué)習(xí)問(wèn)題。
為了實(shí)現(xiàn)這一轉(zhuǎn)換,在下面的代碼中我們調(diào)用了 Pandas 庫(kù)中的 shift 函數(shù),通過(guò) shift 函數(shù)我們可以為轉(zhuǎn)換后的觀察值創(chuàng)建新的隊(duì)列。
在以下示例中,我們創(chuàng)建了一個(gè)包含 12 個(gè)月滯后值的新時(shí)間序列,以預(yù)測(cè)當(dāng)前的觀察結(jié)果。
代碼中 12 個(gè)月的遷移表示前 12 行的數(shù)據(jù)不可用,因?yàn)樗鼈儼?NaN 值。
from pandas import Series
from pandas import DataFrame
# load dataset
series = Series.from_csv('seasonally_adjusted.csv', header=None)
# reframe as supervised learning
dataframe = DataFrame()
for i in range(12,0,-1):
dataframe['t-'+str(i)] = series.shift(i)
dataframe['t'] = series.values
print(dataframe.head(13))
dataframe = dataframe[13:]
# save to new file
dataframe.to_csv('lags_12months_features.csv', index=False)
打印輸出如下所示,其中前 12 行的數(shù)據(jù)不可用。
我們將前 12 行的數(shù)據(jù)刪除,然后將結(jié)果保存在 lags_12months_features.csv 文件中。
實(shí)際上,這個(gè)過(guò)程可以在任意的時(shí)間步長(zhǎng)下重復(fù)進(jìn)行,例如 6 或 24 個(gè)月,感興趣的朋友可以自行嘗試。
各種決策樹(shù),例如 bagged 樹(shù)和隨機(jī)森林等,都可以用來(lái)計(jì)算特征值的重要性得分。
這是一種機(jī)器學(xué)習(xí)中的常見(jiàn)用法,以便在開(kāi)發(fā)預(yù)測(cè)模型時(shí)有效評(píng)估輸入特征的相對(duì)有效性。
這里,我們通過(guò)正要性得分,來(lái)幫助評(píng)估時(shí)間序列預(yù)測(cè)輸入特征的相對(duì)重要性。
這一點(diǎn)之所以重要,不僅是因?yàn)槲覀兛梢栽O(shè)計(jì)上述提到的滯后觀察特征,還可以設(shè)計(jì)基于觀測(cè)時(shí)間戳、滾動(dòng)統(tǒng)計(jì)等其他類型的特征。因此,特征重要性是整理和選擇特征時(shí)非常有效的一種方法。
在下面的實(shí)例中,我們加載了上一節(jié)中創(chuàng)建的數(shù)據(jù)集的監(jiān)督性學(xué)習(xí)視圖,然后利用隨機(jī)森林模型(代碼中為RandomForestRegressor),總結(jié)了 12 個(gè)滯后觀察中每一個(gè)的相對(duì)特征重要性得分。
這里使用了大數(shù)量的樹(shù)來(lái)保證得分的穩(wěn)定性。此外,我們還用到了隨機(jī)種子初始化(the random number seed is initialized),用以保證每次運(yùn)行代碼時(shí)都能獲得相同的結(jié)果。
from pandas import read_csv
from sklearn.ensemble import RandomForestRegressor
from matplotlib import pyplot
# load data
dataframe = read_csv('lags_12months_features.csv', header=0)
array = dataframe.values
# split into input and output
X = array[:,0:-1]
y = array[:,-1]
# fit random forest model
model = RandomForestRegressor(n_estimators=500, random_state=1)
model.fit(X, y)
# show importance scores
print(model.feature_importances_)
# plot importance scores
names = dataframe.columns.values[0:-1]
ticks = [i for i in range(len(names))]
pyplot.bar(ticks, model.feature_importances_)
pyplot.xticks(ticks, names)
pyplot.show()
運(yùn)行示例后,首先打印了滯后觀察值的重要性得分,如下所示。
[ 0.21642244 0.06271259 0.05662302 0.05543768 0.07155573 0.08478599
0.07699371 0.05366735 0.1033234 0.04897883 0.1066669 0.06283236]
然后將得分繪制為條形圖,如圖所示。
圖中顯示 t-12 觀測(cè)值的相對(duì)重要性最高,其次就是 t-2 和 t-4。
感興趣的朋友可以仔細(xì)研究這個(gè)結(jié)果與上述自相關(guān)圖的差異。
實(shí)際上,這里還可以用 gradient boosting,extra trees,bagged decision trees 等代替隨機(jī)森林模型,同樣可以計(jì)算特征的重要性得分。
我們還可以通過(guò)特征選擇來(lái)自動(dòng)識(shí)別并選擇出最具預(yù)測(cè)性的輸入特征。
目前,特征選擇最流行方法是遞歸特征選擇(Recursive Feature Selection,RFE)。
RFE 可以創(chuàng)建預(yù)測(cè)模型,對(duì)特征值賦予不同的權(quán)值,并刪掉那些權(quán)重最小的特征,通過(guò)不斷重復(fù)這一流程,最終就能得到預(yù)期數(shù)量的特征。
以下示例中我們演示了如何通過(guò)RFE與隨機(jī)森林模型進(jìn)行特征選擇,注意其中輸入特征的預(yù)期數(shù)量設(shè)置的是 4。
from pandas import read_csv
from sklearn.feature_selection import RFE
from sklearn.ensemble import RandomForestRegressor
from matplotlib import pyplot
# load dataset
dataframe = read_csv('lags_12months_features.csv', header=0)
# separate into input and output variables
array = dataframe.values
X = array[:,0:-1]
y = array[:,-1]
# perform feature selection
rfe = RFE(RandomForestRegressor(n_estimators=500, random_state=1), 4)
fit = rfe.fit(X, y)
# report selected features
print('Selected Features:')
names = dataframe.columns.values[0:-1]
for i in range(len(fit.support_)):
if fit.support_[i]:
print(names[i])
# plot feature rank
names = dataframe.columns.values[0:-1]
ticks = [i for i in range(len(names))]
pyplot.bar(ticks, fit.ranking_)
pyplot.xticks(ticks, names)
pyplot.show()
運(yùn)行以上示例后,可以得到如下 4 個(gè)待選特征。
Selected Features:
t-12
t-6
t-4
t-2
可見(jiàn),這一結(jié)果與上一節(jié)由重要性得分得到的結(jié)果相一致。
同時(shí),程序還會(huì)創(chuàng)建一個(gè)如下所示的條形圖,圖中顯示了每個(gè)待選輸入特征的選擇排序(數(shù)字越小越好)。
同樣,感興趣的朋友還可以設(shè)置不同的預(yù)期特征數(shù)量,或者換用隨機(jī)森林之外的其他模型。
在本教程中,我們通過(guò)實(shí)例代碼講解了如何通過(guò)機(jī)器學(xué)習(xí)的工具對(duì)時(shí)間序列數(shù)據(jù)進(jìn)行特征選擇。
具體來(lái)說(shuō),我們介紹了如下三點(diǎn):
● 如何解釋具有高度相關(guān)性的滯后觀測(cè)的相關(guān)圖。
● 如何計(jì)算和查看時(shí)間序列數(shù)據(jù)中的特征重要性得分。
● 如何使用特征選擇來(lái)確定時(shí)間序列數(shù)據(jù)中最相關(guān)的輸入變量。
來(lái)源:machinelearningmastery,雷鋒網(wǎng)編譯
雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見(jiàn)轉(zhuǎn)載須知。