時間序列(從如今起稱爲TS)被認爲是數據科學領域中不爲人知的技能之一。python
咱們使用如下步驟:dom
顧名思義,TS是以固定時間間隔收集的數據點的集合。函數
對這些數據進行分析,以肯定長期趨勢,從而預測將來或進行其餘形式的分析。學習
可是什麼使TS不一樣於常規迴歸問題呢?測試
因爲其固有的特性,對其進行分析涉及到各類步驟。下面將詳細討論這些問題。讓咱們從在Python中加載一個TS對象開始。咱們使用航空乘客數據。spa
Pandas有專門的庫來處理TS對象,特別是datatime64[ns]類,它存儲時間信息,咱們能夠快速執行一些操做。讓咱們從啓動所需的庫開始:code
%matplotlib inline from matplotlib.pylab import rcParams data = pd.read_csv('AirPassengers.csv', parse_dates=['Month'], index_col='Month')
讓咱們逐一理解這些論點:對象
如今咱們能夠看到數據以time對象做爲索引,#Passengers做爲列。咱們可使用如下命令交叉檢查索引的數據類型:排序
注意dtype='datetime[ns]'確認它是一個datetime對象。做爲我的偏好,我會將列轉換爲Series對象,以防止每次使用TS時都引用列名稱。索引
ts = data[‘#Passengers’] ts.head(10)
在進一步討論以前,我將討論一些TS數據的索引技術。讓咱們從選擇Series對象中的特定值開始。這能夠經過如下兩種方式實現:
#1.指定索引爲字符串常量: ts['1949-01-01'] #2.導入datetime庫並使用'datetime'函數: from datetime import datetime
二者都將返回值「112」,這也能夠從之前的輸出中確認。假設咱們想要1949年5月以前的全部數據。這能夠經過兩種方式實現:
#1. 指定整個範圍: ts['1949-01-01':'1949-05-01'] #2. 若是其中一個索引位於末尾,請使用「:」: ts[:'1949-05-01']
二者都將產生如下輸出:
這裏有兩點須要注意:
考慮另外一個須要1949年全部值的例子。這能夠經過如下方式實現:
ts['1949']
月份部分被省略了。相似地,若是您選擇某個月的全部日期,則能夠省略日期部分。
如今,讓咱們繼續分析TS。
若是TS的統計特性(如均值、方差)隨時間保持不變,則稱其爲平穩的。但爲何重要呢?大多數TS模型都假設TS是平穩的。直覺上,咱們能夠假設,若是一個TS在一段時間內有一個特定的行爲,那麼它頗有可能在未來也會有一樣的行爲。與非平穩序列相比,平穩序列的相關理論更爲成熟和易於實現。
平穩性是使用很是嚴格的標準來定義的。然而,出於實際目的,咱們能夠假設序列是平穩的,若是它隨時間具備恆定的統計特性,即:
我將跳過這些細節,由於在本文中對其進行了很是明確的定義。讓咱們開始測試平穩性的方法。首先也是最重要的是簡單地繪製數據並進行可視化分析。可使用如下命令繪製數據:
plt.plot(ts)
很明顯,隨着一些季節性變化,數據整體呈上升趨勢。然而,可能並不老是可以作出這樣的視覺直觀推斷(咱們稍後會看到這樣的狀況)。所以,更正式地說,咱們可使用如下方法檢查平穩性:
在這一點上,這些概念聽起來可能不是很直觀。
回到平穩性檢查,咱們將使用滾動統計圖以及Dickey-Fuller檢驗結果不少,因此我定義了一個函數,它以TS做爲輸入併爲咱們生成它們。請注意,我繪製了標準差而不是方差,以保持單位與平均值類似。
def test_stat(timeseries): orig = plt.plot(timeseries, color='blue',label='原始序列') mean = plt.plot(rolmean, color='red', label='滾動平均') std = plt.plot(rolstd, color='black', label = '滾動標準差') plt.title('滾動平均數和標準誤差',fontproperties=myfont) #執行Dickey-Fumer 檢驗: dftest = adfuller(timeseries, maxlag=13, regression='ctt', autolag='BIC')
讓咱們爲輸入序列運行它:
test_stat(ts)
雖然標準差的變化很小,但平均值明顯隨時間增長,這不是一個平穩序列。並且,檢驗統計量遠大於臨界值。請注意,應該比較有符號的值,而不是絕對值。
下一步,咱們將討論能夠用來將這個TS轉換平穩的方法。
雖然許多TS模型都採用平穩性假設,但實際時間序列中幾乎沒有一個是平穩的。統計學家們已經找到了使序列平穩的方法,咱們如今就來討論。實際上,要使一個序列徹底平穩幾乎是不可能的,但咱們要儘可能接近它。
讓咱們瞭解是什麼使TS不穩定。TS的非平穩性有兩個主要緣由:
其基本原理是對序列中的趨勢和季節性進行建模或估計,並從序列中去除這些趨勢和季節性以獲得平穩序列。而後統計預測技術就能夠在這個序列上實現。最後一步是經過應用趨勢和季節性約束將預測值轉換爲原始規模。
注意:我將討論一些方法。在這種狀況下,有些可能工做得很好,而有些可能不行。但咱們的想法是掌握全部的方法,而不是隻關注手頭的問題。
讓咱們從趨勢部分開始。
減小趨勢的第一個技巧之一能夠轉換。例如,在這種狀況下,咱們能夠清楚地看到存在顯着的增加趨勢。所以,咱們能夠應用轉換,以懲罰更高的值,而不是較小的值。這些能夠取對數,平方根,立方根等。在此處取對數轉換簡便簡單:
np.log(ts)
在這種簡單的狀況下,很容易看到數據的將來趨勢。但在有噪音的狀況下,它不是很直觀。所以,咱們可使用一些技術來估計或模擬這一趨勢,而後將其從序列中刪除。有不少方法能夠作到這一點,其中最經常使用的有:
我將在這裏討論平滑,你應該嘗試其餘技術,以及可能解決其餘問題。平滑是指採起滾動估計,即考慮過去的幾個實例。有不少種方法,但我將在這裏討論其中的兩種。
在這種方法中,咱們根據時間序列的頻率取「k」連續值的平均值。這裏咱們能夠取過去一年的平均值,也就是最近12個值。pandas有肯定滾動統計的特定功能。
pd.rolling_mean(ts_log,12)
紅線表示滾動平均值。咱們從原來的數列中減去這個。注意,由於咱們取最後12個值的平均值,因此滾動平均值沒有定義前11個值。這能夠觀察到:
ts_log - moving_avg
注意前11個是Nan。讓咱們刪除這些NaN值並檢查圖以檢驗平穩性。
moving_avg_diff.dropna(inplace=True)
這看起來是一個更好的系列。滾動值彷佛略有變化,但沒有具體趨勢。並且,檢驗統計量小於5%的臨界值,因此咱們能夠用95%的置信度說這是一個平穩序列。
然而,這種方法的一個缺點是,時間段必須嚴格定義,在這種狀況下,咱們能夠取年平均數,但在預測股票價格等複雜狀況下,很可貴出一個數字。因此咱們取一個「加權移動平均值」,其中最近的值被賦予更高的權重。分配權重的方法有不少種,一種流行的方法是指數加權移動平均法,即用衰減因子將權重分配給全部先前的值。請在此處查找詳細信息。這能夠實現爲:
ewma(ts_log, half=12)
請注意,這裏的參數「半衰期」用於定義指數衰減的量。這只是一個假設,很大程度上取決於業務領域。其餘參數,如跨度和質心,也能夠用來定義衰變,這將在上面共享的連接中討論。如今,讓咱們從序列中刪除此項並檢查平穩性:
ts_log - expwighted_avg
這個TS在平均值和標準誤差上的變化甚至更小。此外,檢驗統計量小於1%的臨界值,這比前一種狀況要好。注意,在這種狀況下,不會出現缺失值,由於從開始算起的全部值都是給定的權重。因此即便沒有之前的值,它也能工做。
之前討論過的簡單的趨勢減小技術並不適用於全部狀況,特別是那些具備高季節性的狀況。讓咱們討論兩種消除趨勢和季節性的方法:
處理趨勢性和季節性最經常使用的方法之一是差分。在這項技術中,咱們取某一時刻的觀測值與前一時刻的觀測值之差。這在改善平穩性方面效果很好。一階差分可按以下方式進行:
ts_log - ts_log.shift()
這彷佛大大減小了這一趨勢。讓咱們使用繪圖進行驗證:
咱們能夠看到平均值和標準差隨時間的變化很小。同時,Dickey-Fuller檢驗統計量小於10%的臨界值,所以TS是平穩的,置信度爲90%。咱們也能夠取二階或三階差,在某些應用中可能會獲得更好的結果。
在這種方法中,趨勢和季節性都被分別建模,序列的其他部分被返回。我將跳過統計數據得出結果:
decompose(ts_log) decomposition.trend decomposition.seasonal decomposition.resid
在這裏咱們能夠看到趨勢,季節性是從數據中分離出來的,咱們能夠對殘差進行建模。讓咱們檢查殘差的平穩性:
ts_log_decompose = residual
Dickey-Fuller檢驗統計量顯著低於1%的臨界值。因此這個t很是接近平穩。另外,您應該注意到,在本例中,將殘差轉換爲將來數據的原始值不是很直觀。
咱們看到了不一樣的技術,全部這些技術都至關好地使TS平穩。由於這是一種很是流行的技術,因此讓咱們在差分後在TS上創建模型。此外,在這種狀況下,將噪聲和季節性添加回預測殘差中相對容易。執行趨勢和季節性估計技術後,可能有兩種狀況:
讓我簡單介紹一下ARIMA。我不會深刻討論技術細節,但若是您但願更有效地應用它們,您應該詳細瞭解這些概念。ARIMA表明自迴歸綜合移動平均線。平穩時間序列的ARIMA預測只不過是一個線性(相似於線性迴歸)方程。預測因子取決於ARIMA模型的參數(p,d,q):
這裏的一個重要問題是如何肯定「p」和「q」的值。咱們先來討論一下。
差分後TS的ACF和PACF圖能夠繪製爲:
#繪圖ACF: plt.subplot(121) plt.plot(lag_acf) plt.axhline(y=0,linestyle='--',color='gray') #繪圖PACF: plt.subplot(122) plt.plot(lag_pacf) plt.axhline(y=0,linestyle='--',color='gray') plt.tight_layout()
在這個圖中,0兩邊的兩條虛線是置信區間。這些可用於肯定「p」和「q」值,以下所示:
如今,讓咱們創建3種不一樣的ARIMA模型,既考慮個體效應,也考慮組合效應。我也會輸出RSS。請注意,這裏的RSS是殘差值,而不是實際序列。
咱們須要先加載ARIMA模型:
可使用ARIMA的order參數指定p、d、q值,該參數採用元組(p、d、q)。讓咱們模擬3個案例:
model.fit(disp=-1) plt.plot(ts_log_diff)
results_MA = model.fit(disp=-1) plt.plot(ts_log_diff)
plt.plot(ts_log_diff) plt.plot(results_ARIMA.fittedvalues, color='red')
在這裏,咱們能夠看到AR和MA模型有幾乎相同的RSS,可是結合起來會更好。如今,咱們剩下最後一步,即將這些值恢復到原始比例。
因爲組合模型給出了最佳結果,讓咱們將其縮放回原始值,看看它的預測表現如何。第一步是將預測結果存儲爲一個單獨的序列並觀察它。
請注意,這些開始於'1949-02-01',而不是第一個月。爲何?這是由於咱們取了一個滯後1,第一個元素以前沒有任何東西能夠減去。將差分轉換爲對數刻度的方法是將這些差分連續地添加到基數上。一個簡單的方法是首先肯定索引處的累積和,而後將其添加到基數中。累積總和以下所示:
您可使用前面的輸出快速地作一些計算,以檢查這些是否正確。接下來咱們要把它們加到底數上。爲此,讓咱們建立一個以全部值做爲基數的序列,並將其差分相加。這能夠這樣作:
這裏的第一個元素是基數自己,而後從那裏累計加值。最後一步是取指數並與原數列進行比較。
plt.plot(predictions_ARIMA)
這些都是Python中的內容。咱們來學習一下如何在R中實現時間序列預測。
#安裝包並調用庫 install.packages("tseries") #讀取Airpaseengers數據 tsdata<-AirPassengers #識別數據類別 class(tsdata) #觀察時間序列數據 tsdata #數據摘要 dfSummary(tsdata)
輸出
class(tsdata) "ts" > #觀察時間序列數據 > tsdata Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 1949 112 118 132 129 121 135 148 148 136 119 104 118 1950 115 126 141 135 125 149 170 170 158 133 114 140 1951 145 150 178 163 172 178 199 199 184 162 146 166 1952 171 180 193 181 183 218 230 242 209 191 172 194 1953 196 196 236 235 229 243 264 272 237 211 180 201 1954 204 188 235 227 234 264 302 293 259 229 203 229 1955 242 233 267 269 270 315 364 347 312 274 237 278 1956 284 277 317 313 318 374 413 405 355 306 271 306 1957 315 301 356 348 355 422 465 467 404 347 305 336 1958 340 318 362 348 363 435 491 505 404 359 310 337 1959 360 342 406 396 420 472 548 559 463 407 362 405 1960 417 391 419 461 472 535 622 606 508 461 390 432 > # tsdata Dimensions: 144 x 1 Duplicates: 26 ---------------------------------------------------------------------------------------------------- No Variable Stats / Values Freqs (% of Valid) Graph Valid Missing ---- ---------- -------------------------- ----------------------- --------------------- -------- -- 1 tsdata Mean (sd) : 280.3 (120) 118 distinct values . : . 144 0 [ts] min < med < max: Start: 1949-01 : : . . : (100%) (0%) 104 < 265.5 < 622 End : 1960-12 : : : : : IQR (CV) : 180.5 (0.4) : : : : : : : : : : : : : : : . . ----------------------------------------------------------------------------------------------------
#檢查數據並繪製原始數據 plot(tsdata, ylab="乘客(1000人)", type="o")
cycle(tsdata) Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 1949 1 2 3 4 5 6 7 8 9 10 11 12 1950 1 2 3 4 5 6 7 8 9 10 11 12 1951 1 2 3 4 5 6 7 8 9 10 11 12 1952 1 2 3 4 5 6 7 8 9 10 11 12 1953 1 2 3 4 5 6 7 8 9 10 11 12 1954 1 2 3 4 5 6 7 8 9 10 11 12 1955 1 2 3 4 5 6 7 8 9 10 11 12 1956 1 2 3 4 5 6 7 8 9 10 11 12 1957 1 2 3 4 5 6 7 8 9 10 11 12 1958 1 2 3 4 5 6 7 8 9 10 11 12 1959 1 2 3 4 5 6 7 8 9 10 11 12 1960 1 2 3 4 5 6 7 8 9 10 11 12
#將數據分解爲趨勢、季節性和隨機偏差份量 plot(tsdata_decom)
#測試數據的平穩性 #單位根檢驗 adf(tsdata) #自相關檢驗 plot(acf(tsdata,plot=FALSE))+ labs(title="航空旅客數據相關圖") plot(acf(tsdata_decom$random,plot=FALSE))
輸出
Augmented Dickey-Fuller Test data: tsdata Dickey-Fuller = -7.3186, Lag order = 5, p-value = 0.01 alternative hypothesis: stationary
the p-value is 0.01 which ip值爲0.01,小於0.05,所以,咱們拒絕了零假設,所以時間序列是平穩的。s <0.05, therefore, we reject the null hypothesis and hence time series is stationary.
最大滯後爲1個月或12個月,代表與12個月週期正相關。
自動繪製7:138的隨機時間序列觀測值,不包括NA值
#擬合模型 #線性模型 plot(tsdata) + smooth(method="lm") #ARIMA 模型 arimats
Series: tsdata ARIMA(2,1,1)(0,1,0)[12] Coefficients: ar1 ar2 ma1 0.5960 0.2143 -0.9819 s.e. 0.0888 0.0880 0.0292 sigma^2 estimated as 132.3: log likelihood=-504.92 AIC=1017.85 AICc=1018.17 BIC=1029.35
#Arima模型的預測 fore(arimats, level = c(95))
最後咱們有一個原始數據的預測。
最受歡迎的看法
1.在python中使用lstm和pytorch進行時間序列預測
2.python中利用長短時間記憶模型lstm進行時間序列預測分析