背景介绍
时间序列:一组对于某一变量连续时段上的观测值。
模式识别主要涉及到两个方向:一个是复杂统计,另一个是机器学习。复杂统计是将数据拟合到已知的古典模型中,比如ARMA。而机器学习会用深度学习-神经网络,进行暴力拟合。本文主要讲述复杂统计中的AR、MA、ARMA、ARIMA四种经典模型。深度学习可以参考:https://zhuanlan.zhihu.com/p/23366705。
时间序列分为三类
1.平稳序列:均值和方差是常数,通常建立线性模型来拟合未来的发展状况,如AR、MA、ARMA模型等。
2.可以转化为平稳序列的非平稳序列:一般经过K次差分后平稳,再按照平稳序列进行拟合,如ARIMA模型。
3.无法转化为平稳序列的非平稳序列:所谓的白噪声序列,没有任何规律可循。可以停止分析。
判断是否平稳的方法:
a. 根据时序图和自相关图的特征做出主观判断,该方法操作简单、应用广泛,但带有主观性。
时序图检验:平稳序列的时序图显示序列值始终在一个常数附近随机波动,且波动的范围有界。
自相关图检验:平稳序列具有短期相关性,所以间隔越远的过去值对现时值的影响会越来越小。
平稳序列的自相关系数会比较快的衰减趋向于零,可以转化为平稳序列的非平稳序列则比较慢。
b. 构造检验统计量,目前最常用的方法是单位根检验。存在单位根就是非平稳时间序列。
建模步骤
(1)得到平稳序列数据:上述1类不用处理,上述2类要进行差分处理。
(2)计算ACF/PACF:计算得出序列的自相关系数和偏相关系数图形。
(3)模型识别:根据ACF、PACF图形选择合适的模型。
(4)模型检验:估计模型中未知参数的值并进行检验。
(5)模型优化:如调整参数值达到理想状态。
(6)模型应用:进行短期预测。
ACF/PACF是什么
ACF: 自相关函数(系数) Autocorrelation
PACF:偏相关函数(系数) Partial Correlation
ACF在计算X(t)和X(t-h)的相关性的时候,仅会考虑(t-h)数据点对X(t)的影响。
PACF在计算X(t)和X(t-h)的相关性的时候,会挖空(t-h,t)上所有数据点对X(t)的影响。
这个过程用的多元线性拟合、最小二乘求极值的思想,各个数据点作为特征,其特征向量就是系数值。
ACF/PACF图形识别:拖尾 or 截尾
平稳序列的ACF/PACF图形不是拖尾就是截尾:
拖尾就是有衰减趋势,慢慢趋于0或者极小值。
截尾就是在某阶之后,突然变为0或者极小值 。
常见的三角对称图形,既非拖尾也非截尾,属于单调序列的典型表现形式,表示原始数据是不平稳序列。
还有一种常见说法:拖尾是不在某阶后均为0;截尾是在某阶后均为0。有点一分为二的绝对,不太认同。
根据ACF/PACF图形选择模型
平稳序列:
如果ACF拖尾,PACF截尾,则用 AR 算法
如果ACF截尾,PACF拖尾,则用 MA 算法
如果ACF拖尾、PACF拖尾,则用 ARMA 算法。
可以转化为平稳序列的非平稳序列:
常用 ARIMA算法。它是ARMA算法的扩展版,用法类似 。
模型介绍
AR(p)、MA(q)、ARMA(p,q)、ARIMA(p,d,q):p为自回归项数,q为移动平均项数,d为差分阶数。
1.AR(p)模型:描述当前值与历史值间的关系。参数p为自回归项数,可认为是截尾阶数。
2.MA(q)模型:描述自回归部分的误差累计。参数q为移动平均项数,可认为是截尾阶数。
3.ARMA(p,q)模型:前两个模型的结合体。q=0时即AR(p)模型;p=0时即MA(q)模型。
4.ARIMA(p,d,q)模型:ARMA(p,q)的基础上增加差分步骤,参数d为差分次数。
英文名称:Autoregressive Integrated Moving Average。“差分”单词虽未体现,却是关键步骤。
差分是为了将非平稳序列转化为平稳序列。若一次差分后的序列即达到平稳序列,那么参数d=1。依此类推。
由上可以得出:
并不需要按照ACF/PACF图形选择模型。可以直接应用ARMA/ARIMA算法,只要确定参数p/q的值即可。
一般阶数不超过length/10,所以将p/q分别从0递加试到length/10,模型误差最小时即确定参数p/q的值。
简单示例
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.pylab import style
import statsmodels.tsa.api as smt
import seaborn as sns
style.use('ggplot')
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 参数初始化
discfile = '123.xlsx'
forecastnum = 5
# 读取数据,指定日期列为指标,Pandas自动将“日期”列识别为Datetime格式
data = pd.read_excel(discfile, index_col=u'日期')
# 时序图
data.plot()
plt.show()
# 自相关图
from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.graphics.tsaplots import plot_pacf
#plot_acf(data).show()
#plot_pacf(data).show()
# 平稳性检测
from statsmodels.tsa.stattools import adfuller as ADF
#print('ADF', ADF(data[u'销量']))
# 返回值依次为adf、pvalue、usedlag、nobs、critical values、icbest、regresults、resstore
# 差分后的结果
D_data = data.diff().dropna()
D_data.columns = [u'销量差分']
D_data.plot() # 时序图
plt.show()
plot_acf(D_data).show() # 自相关图
plot_pacf(D_data).show() # 偏自相关图
print(u'差分序列的ADF检验结果为:', ADF(D_data[u'销量差分'])) # 平稳性检测
from statsmodels.stats.diagnostic import acorr_ljungbox # 白噪声检验
print(u'差分序列的白噪声检验结果为:', acorr_ljungbox(D_data, lags=1)) # 返回统计量和p值
from statsmodels.tsa.arima_model import ARIMA
data[u'销量'] = data[u'销量'].astype(float)
# 定阶
pmax = int(len(D_data) / 10) # 一般阶数不超过length/10
qmax = int(len(D_data) / 10) # 一般阶数不超过length/10
bic_matrix = [] # bic矩阵
for p in range(pmax + 1):
tmp = []
for q in range(qmax + 1):
try: # 存在部分报错,所以用try来跳过报错。
tmp.append(ARIMA(data, (p, 1, q)).fit().bic)
except:
tmp.append(None)
bic_matrix.append(tmp)
bic_matrix = pd.DataFrame(bic_matrix) # 从中可以找出最小值
p, q = bic_matrix.stack().idxmin() # 先用stack展平,然后用idxmin找出最小值位置。
#print(u'BIC最小的p值和q值为:%s、%s' % (p, q))
model = ARIMA(data, (p, 1, q)).fit() # 建立ARIMA(0, 1, 1)模型
model.summary(2) # 给出一份模型报告
print model.forecast(5) # 作为期5天的预测,返回预测结果、标准误差、置信区间。