时间序列分析之ARIMA预测

预备知识
时间序列分析原理
时间序列分析之auto_arima自动调参

一、定义

ARIMA模型(Autoregressive Integrated Moving Average model),差分整合移动平均自回归模型,又称整合移动平均自回归模型,时间序列预测分析方法之一。
ARIMA(p,d,q) = \begin{cases} AR(p), & \text{p阶自回归} \\ MA(q), & \text{q阶滑动平均} \\ d,& \text{平稳时的差分阶数} \\ \end{cases}

ARIMA(p,d,q)中,
AR是"自回归",p为自回归项数;
MA为"滑动平均",q为滑动平均项数,d为使之成为平稳序列所做的差分次数(阶数)。

"差分"一词虽未出现在ARIMA的英文名称中,却是关键步骤。

1.1 AR模型(自回归)

描述当前值与历史值之间的关系,用变量自身的历史时间数据对自身进行预测,数学模型表达式如下:
y_t = \mu + \sum\limits_{i=1}^{p}r_t y_{t-1} + \epsilon_t

其中是y_t当前值,\mu是常数项,p是阶数,r是自相关系数,ϵ_t是误差,同时ϵ_t要符合正态分布
该模型反映了在t时刻的目标值值与前t-1~p个目标值之前存在着一个线性关系

自回归模型的限制:
自回归模型是用自身的数据来进行预测
必须具有平稳性
必须具有自相关性,如果自相关系数(φ_i)小于0.5,则不宜采用
自回归只适用于预测与自身前期相关的现象

1.2 MA模型(移动平均)

移动平均模型关注的是自回归模型中的误差项的累加,数学模型表达式如下:
y_t = \mu + \epsilon_t + \sum\limits_{i=1}^{q}\theta_i \epsilon_{t-i}

该模型反映了在t时刻的目标值值与前t-1~p个误差值之前存在着一个线性关系

移动平均法能有效地消除预测中的随机波动

1.3 ARMA模型(自回归移动平均)

ARIMA(p,d,q)模型全称为差分自回归移动平均模型(Autoregressive Integrated Moving Average Model,简记ARIMA)

该模型描述的是自回归与移动平均的结合,具体数学模型如下:
y_t = \mu + \sum\limits_{i=1}^{p}r_t y_{t-1} + \epsilon_t + \sum\limits_{i=1}^{q}\theta_i \epsilon_{t-i}

基本原理:将数据通过差分转化为平稳数据,再将因变量仅对它的滞后值以及随机误差项的现值和滞后值进行回归所建立的模型。

1.4 自相关函数ACF(autocorrelation function)

有序的随机变量序列与其自身相比较

自相关函数反映了同一序列在不同时序的取值之间的相关性

ACF(k) = \sum\limits_{t=k+1}^n \frac{(Z_t-\overline Z)(Z_{t-k}-\overline Z)}{\sum\limits_{t=1}^n(Z_t-\overline Z)^2}
取值范围为[-1,1]

自相关系数度量的是同一事件在两个不同时期之间的相关程度,形象的讲就是度量自己过
去的行为对自己现在的影响。在这里可以通过自相关系数(ACF)图的最大滞后点来大致判断q 值。

1.5 偏自相关系数(PACF)(partial autocorrelation function)

PACF(k) = \frac{E(Z_t - E Z_t)(Z_{t-k} - E Z_{t-k})}{\sqrt {E(Z_t - E Z_t)^2\sqrt{E(Z_{t-k} - E Z_{t-k})^2}}} = \frac{cov[(Z_t - \overline Z_t)(Z_{t-k} - \overline Z_{t-k})]}{\sqrt {var(Z_t - \overline Z_t)\sqrt{E(Z_{t-k} - \overline Z_{t-k})}}}

计算某一个要素对另一个要素的影响或相关程度时,把其他要素的影响视为常数,即暂不考虑其他要素的影响,而单独研究那两个要素之间的相互关系的密切程度时,称为偏相关

对于一个平稳AR(p)模型,求出滞后k自相关系数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)具有相关关系,所以自相关系数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还包含了其他变量的影响而偏自相关系数
PACF是严格这两个变量之间的相关性

1.6 拖尾与截尾

拖尾:始终有非零取值,不会在k大于某个常数后就恒等于零(或在0附近随机波动)
截尾:在大于某个常数k后快速趋于0为k阶截尾

拖尾与截尾

1.7 定阶

模型 ACF PACF
AR(p) 衰减趋于0(几何型或振荡型) p阶后截尾
MA (q) q阶后截尾 衰减趋于0(几何型或振荡型)
ARMA(p,q) q阶后衰减趋于0(几何型或振荡型) p阶后衰减趋于0(几何型或振荡型)

截尾:落在置信区间内(95%的点都符合该规则)

因为AR(自回归)建立必须具有平稳性,所以在建立ARIMA模型也需要平稳性,使数据平稳性的方法可以讲数据进行差分处理,如一阶差分即t与t-1的差值,二阶差分为一阶差分基础上再进行一次差分,使数据平稳后的差分次数即为我们要定的参数d。

若PACFp阶段后截尾,则截尾的阶数即为模型所确定的参数p。
若ACFq阶段后截尾,则截尾的阶数即为模型所确定的参数q。

1.8 建模流程

将序列平稳(差分法确定d)

p和q阶数确定: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 导入数据

我们使用一个股票的样例数据进行分析

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

#数据选取
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 数据查看

stock_train.plot(figsize=(12,6))
plt.legend(bbox_to_anchor=(1.25, 0.5))
plt.title("Stock Close")
sns.despine()
在这里插入图片描述

从数据走势上我们大概可以看出,是有下降的趋势的,我们用单位根来检验一下,为了方便我们写一个函数直接输出相关的数据和图

def test_stationarity(timeseries):
    
    #滑动均值和方差
    rolmean = timeseries.rolling(1).mean()
    rolstd = timeseries.rolling(1).std()

    #绘制滑动统计量
    plt.figure(figsize=(24, 8))   
    orig = plt.plot(timeseries, color='blue',label='data')
    
    plt.legend(loc='best')
    plt.title('数据展示')
    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,所以数据存在单位根

2.4 差分

根据上面说的,当存在单位根,即数据不平稳时需要进行差分处理。

stock_diff = stock_train.diff()
stock_diff = stock_diff.dropna()
test_stationarity(stock_diff)

直接套用上面定义的函数进行查看


在这里插入图片描述

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的,所以可以拒绝存在单位根,序列已经平稳

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()
在这里插入图片描述

在这里插入图片描述

我们根据ACF和PACF的图大概可以判定p =2 ,q = 2

2.6 自动训练定阶

根据之前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()

#残差分析 正态分布 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350