預備知識
時間序列分析原理
時間序列分析之a(chǎn)uto_arima自動調參
一、定義
ARIMA模型(Autoregressive Integrated Moving Average model),差分整合移動平均自回歸模型,又稱整合移動平均自回歸模型,時間序列預測分析方法之一。
ARIMA(p,d,q)中,
AR是"自回歸",p為自回歸項數(shù);
MA為"滑動平均",q為滑動平均項數(shù),d為使之成為平穩(wěn)序列所做的差分次數(shù)(階數(shù))。
"差分"一詞雖未出現(xiàn)在ARIMA的英文名稱中,卻是關鍵步驟。
1.1 AR模型(自回歸)
描述當前值與歷史值之間的關系,用變量自身的歷史時間數(shù)據(jù)對自身進行預測,數(shù)學模型表達式如下:
其中是當前值,
是常數(shù)項,p是階數(shù),r是自相關系數(shù),
是誤差,同時
要符合正態(tài)分布
該模型反映了在t時刻的目標值值與前t-1~p個目標值之前存在著一個線性關系
自回歸模型的限制:
自回歸模型是用自身的數(shù)據(jù)來進行預測
必須具有平穩(wěn)性
必須具有自相關性,如果自相關系數(shù)()小于0.5,則不宜采用
自回歸只適用于預測與自身前期相關的現(xiàn)象
1.2 MA模型(移動平均)
移動平均模型關注的是自回歸模型中的誤差項的累加,數(shù)學模型表達式如下:
該模型反映了在t時刻的目標值值與前t-1~p個誤差值之前存在著一個線性關系
移動平均法能有效地消除預測中的隨機波動
1.3 ARMA模型(自回歸移動平均)
ARIMA(p,d,q)模型全稱為差分自回歸移動平均模型(Autoregressive Integrated Moving Average Model,簡記ARIMA)
該模型描述的是自回歸與移動平均的結合,具體數(shù)學模型如下:
基本原理:將數(shù)據(jù)通過差分轉化為平穩(wěn)數(shù)據(jù),再將因變量僅對它的滯后值以及隨機誤差項的現(xiàn)值和滯后值進行回歸所建立的模型。
1.4 自相關函數(shù)ACF(autocorrelation function)
有序的隨機變量序列與其自身相比較
自相關函數(shù)反映了同一序列在不同時序的取值之間的相關性
取值范圍為[-1,1]
自相關系數(shù)度量的是同一事件在兩個不同時期之間的相關程度,形象的講就是度量自己過
去的行為對自己現(xiàn)在的影響。在這里可以通過自相關系數(shù)(ACF)圖的最大滯后點來大致判斷q 值。
1.5 偏自相關系數(shù)(PACF)(partial autocorrelation function)
計算某一個要素對另一個要素的影響或相關程度時,把其他要素的影響視為常數(shù),即暫不考慮其他要素的影響,而單獨研究那兩個要素之間的相互關系的密切程度時,稱為偏相關
對于一個平穩(wěn)AR(p)模型,求出滯后k自相關系數(shù)p(k)時實際上得到并不是x(t)與x(t-k)之間單純的相關關系x(t)同時還會受到中間k-1個隨機變量x(t-1)、x(t-2)、……、x(t-k+1)的影響,而這k-1個隨機變量又都和x(t-k)具有相關關系,所以自相關系數(shù)p(k)里實際摻雜了其他變量對x(t)與x(t-k)的影響,剔除了中間k-1個隨機變量x(t-1)、x(t-2)、……、x(t-k+1)的干擾之后x(t-k)對x(t)影響的相關程度。ACF還包含了其他變量的影響而偏自相關系數(shù)
PACF是嚴格這兩個變量之間的相關性
1.6 拖尾與截尾
拖尾:始終有非零取值,不會在k大于某個常數(shù)后就恒等于零(或在0附近隨機波動)
截尾:在大于某個常數(shù)k后快速趨于0為k階截尾

1.7 定階
| 模型 | ACF | PACF |
|---|---|---|
| AR(p) | 衰減趨于0(幾何型或振蕩型) | p階后截尾 |
| MA (q) | q階后截尾 | 衰減趨于0(幾何型或振蕩型) |
| ARMA(p,q) | q階后衰減趨于0(幾何型或振蕩型) | p階后衰減趨于0(幾何型或振蕩型) |
截尾:落在置信區(qū)間內(nèi)(95%的點都符合該規(guī)則)
因為AR(自回歸)建立必須具有平穩(wěn)性,所以在建立ARIMA模型也需要平穩(wěn)性,使數(shù)據(jù)平穩(wěn)性的方法可以講數(shù)據(jù)進行差分處理,如一階差分即t與t-1的差值,二階差分為一階差分基礎上再進行一次差分,使數(shù)據(jù)平穩(wěn)后的差分次數(shù)即為我們要定的參數(shù)d。
若PACFp階段后截尾,則截尾的階數(shù)即為模型所確定的參數(shù)p。
若ACFq階段后截尾,則截尾的階數(shù)即為模型所確定的參數(shù)q。
1.8 建模流程
將序列平穩(wěn)(差分法確定d)
p和q階數(shù)確定:ACF與PACF
ARIMA(p,d,q)

二、Python建模
2.1 導入相關的包
%matplotlib inline
import pandas as pd
import pandas_datareader
import datetime
import matplotlib.pylab as plt
import seaborn as sns
from matplotlib.pylab import style
import statsmodels.api as sm
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.stattools import adfuller
import numpy as np
style.use('ggplot')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
import statsmodels
statsmodels.__version__
#'0.13.5'
import warnings
warnings.filterwarnings("ignore")
2.2 導入數(shù)據(jù)
我們使用一個股票的樣例數(shù)據(jù)進行分析
stock = pd.read_csv('T10yr.csv', index_col=0, parse_dates=[0])
stock
| Date | Open | High | Low | Close | Volume | Adj Close |
|---|---|---|---|---|---|---|
| 2000-01-03 | 6.498 | 6.603 | 6.498 | 6.548 | 0 | 6.548 |
| 2000-01-04 | 6.530 | 6.548 | 6.485 | 6.485 | 0 | 6.485 |
| 2000-01-05 | 6.521 | 6.599 | 6.508 | 6.599 | 0 | 6.599 |
| 2000-01-06 | 6.558 | 6.585 | 6.540 | 6.549 | 0 | 6.549 |
| 2000-01-07 | 6.545 | 6.595 | 6.504 | 6.504 | 0 | 6.504 |
| ... | ... | ... | ... | ... | ... | ... |
| 2016-07-25 | 1.584 | 1.584 | 1.554 | 1.571 | 0 | 1.571 |
| 2016-07-26 | 1.559 | 1.587 | 1.549 | 1.563 | 0 | 1.563 |
| 2016-07-27 | 1.570 | 1.570 | 1.511 | 1.515 | 0 | 1.515 |
| 2016-07-28 | 1.525 | 1.535 | 1.493 | 1.511 | 0 | 1.511 |
| 2016-07-29 | 1.525 | 1.530 | 1.458 | 1.458 | 0 | 1.458 |
4167 rows × 6 columns
#數(shù)據(jù)選取
stock_week = stock['Close'].resample('W-MON').mean()
stock_train = stock_week['2000':'2015']
Date
2000-01-03 6.54800
2000-01-10 6.53900
2000-01-17 6.66300
2000-01-24 6.73720
2000-01-31 6.67280
...
2015-11-30 2.22950
2015-12-07 2.23260
2015-12-14 2.20980
2015-12-21 2.23780
2015-12-28 2.24275
Freq: W-MON, Name: Close, Length: 835, dtype: float64
2.3 數(shù)據(jù)查看
stock_train.plot(figsize=(12,6))
plt.legend(bbox_to_anchor=(1.25, 0.5))
plt.title("Stock Close")
sns.despine()

從數(shù)據(jù)走勢上我們大概可以看出,是有下降的趨勢的,我們用單位根來檢驗一下,為了方便我們寫一個函數(shù)直接輸出相關的數(shù)據(jù)和圖
def test_stationarity(timeseries):
#滑動均值和方差
rolmean = timeseries.rolling(1).mean()
rolstd = timeseries.rolling(1).std()
#繪制滑動統(tǒng)計量
plt.figure(figsize=(24, 8))
orig = plt.plot(timeseries, color='blue',label='data')
plt.legend(loc='best')
plt.title('數(shù)據(jù)展示')
plt.show(block=False)
#adf檢驗
print('Results of Dickey-Fuller Test:')
dftest = adfuller(timeseries, autolag='AIC')
dfoutput = pd.Series(dftest[0:4], index=['Test Statistic','p-value','#Lags Used',
'Number of Observations Used'])
for key,value in dftest[4].items():
dfoutput['Critical Value (%s)'%key] = value
print(dfoutput)
test_stationarity(stock_train)

Results of Dickey-Fuller Test:
Test Statistic -2.196095
p-value 0.207666
Lags Used 1.000000
Number of Observations Used 833.000000
Critical Value (1%) -3.438225
Critical Value (5%) -2.865016
Critical Value (10%) -2.568621
dtype: float64
P值為0.207666> 0.05,所以數(shù)據(jù)存在單位根
2.4 差分
根據(jù)上面說的,當存在單位根,即數(shù)據(jù)不平穩(wěn)時需要進行差分處理。
stock_diff = stock_train.diff()
stock_diff = stock_diff.dropna()
test_stationarity(stock_diff)
直接套用上面定義的函數(shù)進行查看

Results of Dickey-Fuller Test:
Test Statistic -23.506019
p-value 0.000000
Lags Used 0.000000
Number of Observations Used 833.000000
Critical Value (1%) -3.438225
Critical Value (5%) -2.865016
Critical Value (10%) -2.568621
dtype: float64
p-value=0.000000 ,明顯是小于0.05的,所以可以拒絕存在單位根,序列已經(jīng)平穩(wěn)
2.5 ACF和PACF
acf = plot_acf(stock_diff, lags=20)
plt.title("ACF")
acf.show()
pacf = plot_pacf(stock_diff, lags=20)
plt.title("PACF")
pacf.show()


我們根據(jù)ACF和PACF的圖大概可以判定p =2 ,q = 2
2.6 自動訓練定階
根據(jù)之前auto_arima介紹
from pmdarima import auto_arima
stepwise_fit = auto_arima(stock_train,
start_p = 1,
start_q = 1,
max_p = 3,
max_q = 3,
m = 52,
start_P = 0,
seasonal = True,
d = None,
D = 1,
trace = True,
error_action ='ignore', # we don't want to know if an order does not work
suppress_warnings = True, # we don't want convergence warnings
stepwise = True,
n_jobs = -1) # set to stepwise
# To print the summary
stepwise_fit.summary()
Best model: ARIMA(2,0,1)(2,1,0)[52] intercept
Total fit time: 2262.306 seconds
2.7 預測
m = 52
#Model Estimation
# Fit the model
arima2 = sm.tsa.SARIMAX(stock_train, order=(2,0,1), seasonal_order=(2,1,0,m))
model_results = arima2.fit()
#殘差分析 正態(tài)分布 QQ圖線性
model_results.plot_diagnostics(figsize=(15, 12));

pred = model_results.predict(start=0,end=1000)
print (pred)
plt.figure(figsize=(24, 8))
orig = plt.plot(stock_train, color='blue',label='Original')
predict = plt.plot(pred[m+1:], color='red',label='Predict')
plt.legend(loc='best')
plt.title('Original&Predict')
plt.show(block=False)

2.8 殘差分布
ERROR_RATE=(stock_train-pred[m+1:])/stock_train
plt.figure(figsize=(12,4))
plt.scatter(ERROR_RATE.index,ERROR_RATE,color='r')
plt.grid(True)
plt.figure(figsize=(12, 4))
plt.hist(ERROR_RATE, bins=20)
plt.grid(True)
plt.show()

# Load specific evaluation tools
from sklearn.metrics import mean_squared_error
from statsmodels.tools.eval_measures import rmse
# Calculate root mean squared error
print(rmse(stock_train, pred[:m]))
# Calculate mean squared error
print(mean_squared_error(stock_train, pred[:m]))
1.5157632571102173
2.297538251605375