时间序列分析建模步骤及Python实现

平稳时间序列的意义

根据数理统计学常识,要分析的随机变量获得的样本信息越多,分析的结果就会越可靠,但由于时间序列分析的特殊数据结构,对随机序列{...,X1,X2...,Xt,...}而言,它在任意时刻 t 的序列值 Xt 都是一个随机变量,而且由于时间的不可重复性,该变量在任意一个时刻都只能获得唯一的样本观察值,通常是没有办法分析的。在平稳序列场合里,序列的均值等于常数,意味着原本含有可列多个随机变量的均值序列变成了一个常数序列,原本每个随机变量的均值只能依靠唯一的一个样本观察值去估计,现在每一个样本观察值都变成了常数均值的样本观察值,这极大的减少了随机变量的个数,并增加了待估参数的样本容量。

平稳性校验

  • 一种是根据时序图和自相关图显示的特征做出判断的图检验方法(自相关图是一个平面二维坐标悬垂线图,一个坐标轴便是延迟时期数,另一个坐标轴表示自相关系数,通常以悬垂线表示自相关系数的大小。自相关图进行平稳性判断的标准:随着延迟期数 k 的增加,平稳序列的自相关系数会很快的衰减向零;反之,非平稳序列的自相关系数衰减向零的速度通常比较慢)
import numpy as np
import pandas as pd
from datetime import datetime
import matplotlib.pylab as plt
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

#读取原始时间序列数据
df=pd.read_csv('wq.csv',encoding='utf-8', index_col='datatime') #从csv文件中读取时间序列数据,index_col列定义为索引对象
df.index=pd.to_datetime(df.index)
ts=df['dataColumn'] #指定时间序列中对应的数据列
ts.head()
ts.head().index

ts=ts.dropna() #去除掉时间序列中的空值,否则无法绘制出正常的acf图

#输出原始序列
f = plt.figure(facecolor='white')
ts.plot(color='blue', label='Original')
plt.title('TimeSeries Original Data')
plt.show()

#输出ACF(自相关图)、PACF(偏自相关图)
f = plt.figure(facecolor='white')
ax1 = f.add_subplot(211)
plot_acf(ts, lags=31, ax=ax1)
ax2 = f.add_subplot(212)
plot_pacf(ts, lags=31, ax=ax2)
plt.show()

  

  • 另一种是构造检验统计量进行假设检验的方法(目前最常用的平稳性统计校验方法是单位根检验,DF检验和ADF检验)DF检验只适合1阶自回归过程的平稳性检验,ADF检验是对DF检验做了一个修正,得到增广DF检验(augrmented Dickey-Fuller)。一般认为检验结果p值<0.05时,认为检验序列为平稳时间序列
from statsmodels.tsa.stattools import adfuller

#adf校验
ts=ts[~ts.isin(['null'])] #去除时间序列中值为空的行
ts=ts.dropna() #去除掉所有NaN值
dftest = adfuller(ts)  #ADF校验
# 对上述函数求得的值进行语义描述
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) #输出df校验结果

数据预处理

通过平稳性校验,序列可以分为平稳序列和非平稳序列,对于非平稳序列,通常要进行进一步的校验、变换或处理后,才能确定合适的拟合模型;变化处理方式包含对数变化、差分变换、拆分处理等。

对数变换主要是为了减小变化较大的时序数据的振动幅度,使其线性规律更加明显
#对数变换
ts_log = np.log(ts)

#对数变换后的序列输出
f = plt.figure(facecolor='white')
ts_log.plot(color='blue', label='log Data')
plt.title('TimeSeries log Data')
plt.show()
 
平滑法:根据平滑技术的不同,平滑法分为移动平均法和指数平均法,移动平均即利用一定时间间隔内的平均值作为某一期的估计值,而指数平均则是用变权的方法来计算均值,认为离着预测点越近的点,作用越大。
  • 简单中心移动平均能有效消除季节效应,有效提取低阶趋势,能实现拟合方差最小
  • 简单移动平均比值能有效提取季节效应 
# 对size个数据进行移动平均
rol_mean = timeSeries.rolling(window=size).mean()
# 对size个数据进行加权移动平均
rol_weighted_mean = pd.ewma(timeSeries, span=size)
rol_mean.dropna(inplace=True)
rol_weighted_mean.dropna(inplace=True)

    

差分运算,(预测方法中并没有解决高于2阶的差分)经过差分运算后的序列,呈现典型的随机波动特征。差分方法的优点是对确定性信息的提取比较充分,缺点是很难对模型进行直观解释(当序列具有非常显著的确定性趋势或者季节效应时,为了通过确定性因素分解方法提取序列中各种确定性效应的解释,构造了残差自回归模型)
  • 序列蕴涵显著的线性趋势,1阶差分就可以实现趋势平稳
  • 序列蕴涵曲线趋势,通常低阶(2阶或者3阶)差分就可以提取出曲线趋势的影响
  • 蕴涵固定个周期的序列,进行步长为固定周期长度的差分运算,可以较好的提取周期信息
#差分计算
ts_diff1=ts.diff(1)
ts_diff2=ts.diff(2)

#输出时间序列
f = plt.figure(facecolor='white')
ts.plot(color='green', label='原始数据')
ts_diff1.plot(color='blue', label='1阶差分')
ts_diff2.plot(color='red', label='2阶差分')
plt.show()

拆分:使用确定性因素分解方法。所有的序列波动都可以归纳为受长期趋势、循环趋势、季节性变化、随机波动4大类因素的综合影响,也就是说任何一个时间序列都可以用这4个因素的某个函数进行拟合,最常用的函数是加法函数和乘法函数

from statsmodels.tsa.seasonal import seasonal_decompose
decomposition = seasonal_decompose(ts, model="additive",period=6)

trend = decomposition.trend #趋势序列
seasonal = decomposition.seasonal  #季节序列
residual = decomposition.resid  #随机序列

 

白噪声检验 

对于平稳序列,只有那些序列值之间具有密切的相关关系,历史数据对未来发展有一定影响的序列,才值得建模。(如果序列彼此之间没有任何相关性,那就意味着该序列是一个没有记忆的序列,过去的序列对未来的发展没有任何影响,是一种没有任何分析价值的而序列,称之为纯随机序列,白噪声序列就是一种纯随机序列)

Barlett证明,如果一个时间序列是纯随机的,得到一个观察期数为n的观察序列,那么该序列的延迟非零期的样本自相关系数将近似服从均值为0,方差为序列观察期数倒数的正态分布。
我们假设序列为纯随机的,即延迟期数小于或等于m期的序列值之间相互独立(不相关)。使用Q统计量和LB统计量来校验白噪声序列,计算出Q统计量的p值之后,如果p值大于0.05,就说明我们无法拒绝原假设(该序列是白噪声序列),这个时间序列的确就是白噪声序列。
  • Q统计量:Q统计量近似服从自由度为m的卡方分布,当Q统计量大于卡方分位点或者统计量的P值小于α时,则可以以1-α的置信水平拒绝原假设,认为该序列为非白噪声序列,否则,不能拒绝原假设,认为该序列为纯随机序列。在大样本场合,检验效果很好,但在小样本场合不太精确
  • LB统计量:是对Q统计量的修正,同样近似服从自由度为m的卡方分布,在各种检验场合,普遍采用的Q统计量通常指的都是LB统计量
from statsmodels.stats.diagnostic import acorr_ljungbox
p_value = acorr_ljungbox(ts,lags=[6,12]) #lags可自定义,一般取第6和第12延迟期数,这是因为平稳序列通常具有短期相关性,如果序列值之间存在显著的相关关系,通常只存在于延迟期间比较短的序列值之间。
print(p_value)

  

acorr_ljungbox(ts, lags=None, boxpierce=False)函数检验无自相关函数输入输出说明
输入值:
lags为延迟期数,如果为整数,则是包含在内的延迟期数,如果是一个列表或数组,那么所有时滞都包含在列表中最大的时滞中
boxpierce为True时表示除开返回LB统计量还会返回Box和Pierce的Q统计量
返回值:
lbvalue:测试的统计量
pvalue:基于卡方分布的p统计量
bpvalue:((optionsal), float or array) – test statistic for Box-Pierce test
bppvalue:((optional), float or array) – p-value based for Box-Pierce test on chi-square distribution
 

模型选择

常见模型包括AR(自回归模型)、MA(移动平均模型)、ARMA(自回归移动平均模型)、ARIMA(求和自回归移动平均模型)。模型选择的一项重要工作是确定p,q 的阶数。

一种通过对平稳时间序列的自相关系数(ACF)和偏自相关系数(PACF)的计算,绘制自相关图和偏自相关图,通过拖尾、截尾性质,确定合适的模型以及各自阶数。

  

 另一种通过借助AIC、BIC统计量自动确定

 

##借助AIC、BIC统计量自动确定
from statsmodels.tsa.arima_model import ARMA
def proper_model(data_ts, maxLag): 
    init_bic = float("inf")
    init_p = 0
    init_q = 0
    init_properModel = None
    for p in np.arange(maxLag):
        for q in np.arange(maxLag):
            model = ARMA(data_ts, order=(p, q))
            try:
                results_ARMA = model.fit(disp=-1, method='css')
            except:
                continue
            bic = results_ARMA.bic
            if bic < init_bic:
                init_p = p
                init_q = q
                init_properModel = results_ARMA
                init_bic = bic
    return init_bic, init_p, init_q, init_properModel

 调用自定义函数

#调用自定义方法
proper_model(trainSeting,40)

ARIMA模型的实质就是差分运算与ARMA模型的组合。这一关系意义重大。这说明任何非平稳序列如果能通过适当阶数的差分实现差分后平稳,就可以对差分后序列进行ARMA模型拟合了

from statsmodels.tsa.arima_model import ARIMA

model=ARIMA(data,order=(p,d,q)).fit()

 

参数估计

  • 矩估计
  • 极大似然估计(必须已知总体的分布函数,在时间序列分析中,序列总体的分布通常是未知的,为便于分析和计算,通常假设序列服从多元正态分布)
  • 最小二乘估计(在实际中,最常用的是条件最小二乘估计方法)

模型检验

模型检验包括模型的显著性校验和参数的显著性校验
  • 模型的检验即为残差序列中的白噪声检验,如果残差序列是白噪声序列,则拟合残差项中将不蕴涵任何相关信息,即模型提取的信息足够充分,模型的显著性高;反之,说明模型拟合不够有效,需要选择其他模型,重新拟合
  • 参数的显著性校验就是要检验每一个未知参数是否显著非零。检验的目的是使模型最精简

模型优化

综合考虑模型的拟合精度和未知参数个数的综合最优配置。若一个拟合模型通过了校验,说明在一定的置信水平下,该模型能有效拟合观察值序列的波动,但这种有效模型不一定是唯一的。在所有通过校验的模型中使用AIC或者SBC函数达到最小的函数为相对最优模型。
 
 
参考资料:中国人民大学出版社《应用时间序列分析》第四版    王燕编著 

posted @ 2021-12-22 11:53  鸣梦  阅读(2564)  评论(1编辑  收藏  举报