python statsmodels时间序列分析

写在前面,这是一篇单变量时间序列分析学习笔记,参考了很多大佬的文章,东拼西凑才勉强吧时间序列分析理清。在下数据分析萌新一名,有错误的地方欢迎指正,侵删

一、稳定性检验

当一个序列的均值与标准差不随时间变化,则称该序列是一个平稳序列。 ARMA、AR、MA等模型只能用于预测平稳序列,因此需要对序列进行平稳性检验

1、绘图法

如下图a为平稳序列,图b为非平稳序列
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VmJfJnY1-1637157590275)(F:\typora imgs\image-20211112222403614.png)]

2、ADF检验

参考: https://www.pianshen.com/article/5826219147/

  • 单位根 当一个自回归过程中:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hQ2lJulv-1637157590279)(https://www.pianshen.com/images/743/58b202cc73c71b7e04cd13da4070c00f.gif)]如果滞后项系数b为1,就称为单位根。当单位根存在时,自变量和因变量之间的关系具有欺骗性,因为残差序列的任何误差都不会随着样本量(即时期数)增大而衰减,也就是说模型中的残差的影响是永久的。这种回归又称作伪回归。如果单位根存在,这个过程就是一个随机漫步(random walk)
  • ADF检验的原理
    ADF检验就是判断序列是否存在单位根:如果序列平稳,就不存在单位根;否则,就会存在单位根。所以,ADF检验的 H0 假设就是存在单位根,如果得到的显著性检验统计量小于三个置信度(10%,5%,1%),则对应有(90%,95,99%)的把握来拒绝原假设
  • ADF检验的python实现
from statsmodels.tsa.stattools import adfuller
result = adfuller(your_data)
print(result)

adfuller的参数

参数 含义
x 一维数组
maxlag 最大滞后数目
regression 回归中的包含项(c:只有常数项,默认;ct:常数项和趋势项;ctt:常数项,线性二次项;nc:没有常数项和趋势项)
autolag 自动选择滞后数目(AIC:赤池信息准则,默认;BIC:贝叶斯信息准则;t-stat:基于maxlag,从maxlag开始并删除一个滞后直到最后一个滞后长度基于 t-statistic 显著性小于5%为止;None:使用maxlag指定的滞后)
store True False,默认
regresults True 完整的回归结果将返回。False,默认

adfuller的返回值

返回值 含义
adf Test statistic,T检验,假设检验值
pvalue 假设检验结果
usedlag 使用的滞后阶数
nobs 用于ADF回归和计算临界值用到的观测值数目
icbest 如果autolag不是None的话,返回最大的信息准则值
resstore 将结果合并为一个dummy
  • 结果解读
(-0.45153867687808574, 0.9011315454402649, 1, 198, {'5%': -2.876250632135043, '1%': -3.4638151713286316, '10%': -2.574611347821651}, 1172.4579344852016)

t-statistic 的值 -0.451 ,要求小于10%,p-value的值很大,接受原假设,即存在单位根,序列不具有平稳性

二、差分

当序列不具有平稳性的时候,可以通过差分变换使序列变得平稳。所谓差分就是用下一个数减去上一个数,他们的差值形成了一个新的序列

  • 差分的python实现
df = pd.DataFrame([math.sin(x) + 0.2*x + random.choice([-0.2,-0.1,0,0.1,0.2]) for x in range(1,40)]) #伪数据
diff_1 = df.diff(1) # 1阶差分
diff_2 = diff_1.diff(1) # 2阶差分

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ms0X1fvF-1637157590282)(F:/typora imgs/差分.png)]
可以发现原本不平稳的序列在差分后变得平稳

三、白噪声检验

参考: https://www.cnblogs.com/travelcat/p/11400307.html
白噪声序列的每个数据都是独立且随机的,没有分析的意义,所以接下来需要判断序列是否为白噪声

  • 原理
    白噪声检验可以通过Ljung-Box检验(LB检验)来进行,构造的统计量如下,用于检验N阶滞后范围内序列的自相关性是否显著,或序列是否为白噪声
    Q = n ( n + 2 ) ∑ k = 1 N ρ ^ k 2 n − k Q = n(n+2)\sum \limits_{k=1} ^{N}\frac{\hat{ρ}^2_k}{n-k} Q=n(n+2)k=1Nnkρ^k2
    Q是服从自由度为N的卡方分布,其中ρ²表示滞后k阶的相关系数,n是样本数量

​ __原假设H0:__原本的数据都是独立的,即总体的相关系数为0,能观察到的某些相关仅仅产生于随机抽样的误差。
​ __责备假设H1:__原本的数据不是独立的

  • LB检验python实现
    我们可以通过statsmodels库轻易实现LB检验
from statsmodels.stats.diagnostic import acorr_ljungbox as lb_test

lb_test参数

参数 含义
x 检验的时间序列
lags int,list or None,检验的延迟数
boxpierce 若为True,则同时输出boxpierce统计量的检验结果(Box-Pierce检验为白噪声检验的另一个版本,是LB检验的前身)

lb_test返回值
​ 返回值是一个元组,里面分别是:(LB统计量值array, LB-p值array,若boxpierce=True, 则继续输出BP统计量的值和相应p值)

data_1 = [math.sin(x) + 0.2 * x + random.choice([-0.2,-0.1,0,0.1,0.2]) for x in range(1,40)] #非白噪声
p_vale_1 = lb_test(data_1)["lb_pvalue"] #非白噪声的LB检验P值结果
data_2 = np.random.randint(low = 1, high = 10, size = (40,)) # 白噪声序列
p_vale_2 = lb_test(data_2)["lb_pvalue"] #白噪声的LB检验P值结果
# 绘图:略

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kCVApIKY-1637157590285)(F:\typora imgs\白噪声检验.png)]

  • 结果解读
    __1、__观察图2可以发现滞后超过2后,P值下降到了5%以下,说明该序列不是白噪声
    __2、__而图4的P值始终大于5%,因此该序列为白噪声

四、模型选择与建立

1、常见的时间序列模型

  • AR(Auto Regressive Model)自回归模型
    通过自身前面的的数据与后面的数据的相关性(自相关)建立模型,一个p阶自回归的表达式如下,表示为AR§
    x t = ρ t − 1 x t − 1 + ρ t − 2 x t − 2 + . . . . . . + ρ t − p x t − p + μ x_t = ρ_{t-1}x_{t-1}+ρ_{t-2}x_{t-2}+......+ρ_{t-p}x_{t-p}+μ xt=ρt1xt1+ρt2xt2+......+ρtpxtp+μ
    ​ 其中ρ是某一阶的相关系数,μ是噪声,__p__表示使用了后__p__个时间点的数据来建立回归模型
  • MA(Moving Average Model)移动平均模型
    通过将一段时间序列中白噪声序列进行加权和,可以得到移动平均方程。如下图所示为q阶移动平均过程,表示为MA(q)
    x t = θ t − 1 μ t − 1 + θ t − 2 μ t − 2 + . . . . . . + θ t − p μ t − p + μ t x_t = \theta_{t-1}μ_{t-1}+\theta_{t-2}μ_{t-2}+......+\theta_{t-p}μ_{t-p}+μ_t xt=θt1μt1+θt2μt2+......+θtpμtp+μt
    ​ theta表示移动回归系数。ut表示不同时间点的白噪声
  • ARMA(Auto Regressive and Moving Average Model)自回归移动平均模型
    AR可以解决当前数据与后期数据之间的关系,MA则可以解决随机变动也就是噪声的问题,ARMA综合了两者的特点。表示为__ARMA(p, q)__,p是自回归阶数,q是移动平均阶数

x t = ρ t − 1 x t − 1 + ρ t − 2 x t − 2 + . . . . . . + ρ t − p x t − p + θ t − 1 μ t − 1 + θ t − 2 μ t − 2 + . . . . . . + θ t − p μ t − p x_t =ρ_{t-1}x_{t-1}+ρ_{t-2}x_{t-2}+......+ρ_{t-p}x_{t-p}+\theta_{t-1}μ_{t-1}+\theta_{t-2}μ_{t-2}+......+\theta_{t-p}μ_{t-p} xt=ρt1xt1+ρt2xt2+......+ρtpxtp+θt1μt1+θt2μt2+......+θtpμtp
​ 可以发现ARMA就是AR与MA的组合,当p = 0时ARMA退化为MA,当q = 0时ARMA退化为AR

  • ARIMA(Auto Regressive Integrate Moving Average Model)差分自回归移动平均模型
    前三种模型只适用于平稳序列,ARMIA中间的I表示差分,是在ARMA基础上进行了差分,可以用于非平稳序列。

    表示为ARIMA(p, d, q),其中p是自回归阶数,d是差分阶数,q是移动平均阶数

2、模型选择

① ACF(自相关图)与PACF(偏自相关图)

__参考:__https://blog.csdn.net/Yuting_Sunshine/article/details/95317735

  • __自相关图(ACF):__展示了当前数据与之前数据的数据的相关性变化情况
  • __偏自相关图(PACF):__是剔除了中间k-1个中间数据干扰后的相关程度
  • 使用python绘制ACF与PACF
import statsmodels.api as sm
data = pda.DataFrame([math.sin(x*np.pi/6) + 0.4 * x for x in range(1,36)]) # 数据
fig = fig = plt.figure(figsize = (20,5),facecolor="#ffffff")
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
sm.graphics.tsa.plot_acf(pda.DataFrame(data),title="ACF", ax = ax1) # 自相关图
sm.graphics.tsa.plot_pacf(pda.DataFrame(data),title="PACF", ax = ax2) # 偏自相关图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-957AcmVa-1637157590287)(F:\typora imgs\ACF与PACF.png)]
可以发现该序列的ACF拖尾,PACF截尾,关于截尾与拖尾以及阶数的判断可以参考这篇文章:https://blog.csdn.net/qq_43613793/article/details/109908418
__注:__蓝色阴影区为95%的置信区间

② 模型选择
模型 ACF PACF
AR§ 衰减趋于零(几何形或震荡型) p阶后截尾
MA(q) q阶后截尾 衰减趋于零(几何形或震荡型)
ARMA(p,q) q阶后衰减趋于零(几何形或震荡型) p阶后衰减趋于零(几何形或震荡型)

3、python statsmodels库建模

根据上述规则确定模型以及参数后,就可以开始建模了,如下

import statsmodels.api as sm
# AR模型
ar2 = sm.tsa.AutoReg(data,lags=2) # 2阶自回归模型,data是以时间为索引的pandas Series
result = ar2.fit() # 模型训练
# 预测从2021-12-2到2021-12-10的数据
data_hat = result.predict(start = datetime.date(2021,12,2), end = datetime.date(2021,12,10))

# ARIMA模型
arima214 = sm.tsa.sm.tsa.SARIMAX(data,order=(2,1,4)) # 2阶自回归,1阶差分,4阶移动平均
result = arima214.fit() # 模型训练
data_hat = result.predict(start = datetime.date(2021,12,2), end = datetime.date(2021,12,10)) # 预测
# 预测得到的也是一个pandas Series

根据ARIMA的定义我们知道,ARIMA模型在某些参数为0时可以退化为AR、MA或ARMA。因此模型还可以这样建立

import statsmodels.api as sm
ar1 = sm.tsa.ARIMA(data, order=(1,0,0)) # 一阶AR模型
ma1 = sm.tsa.ARIMA(data, order=(0,0,1)) # 一阶MA模型
arma12 = sm.tsa.ARIMA(data, order=(1,0,2)) # 1阶自回归,2阶移动平均的ARMA模型

同样通过fit()函数来训练模型,最后可以调用summary()函数获取模型的详细信息,例如:

arima214 = sm.tsa.sm.tsa.SARIMAX(data,order=(3,1,0)) # 3阶自回归,1阶差分,0阶移动平均
result = arima214.fit() # 模型训练
print(result.summary()) # 输出三张表,如下
Dep. Variable: y No. Observations: 63
Model: SARIMAX(3, 1, 0) Log Likelihood 156.440
Date: Mon, 15 Nov 2021 AIC -304.880
Time: 21:09:07 BIC -296.371
Sample: 10-01-2021 - 12-02-2021 HQIC -301.539
Covariance Type: opg
coef std err z P>|z| [0.025 0.975]
ar.L1 2.5883 0.052 49.614 0.000 2.486 2.691
ar.L2 -2.4882 0.107 -23.156 0.000 -2.699 -2.278
ar.L3 0.8859 0.074 11.914 0.000 0.740 1.032
sigma2 0.0007 0.000 3.253 0.001 0.000 0.001
Ljung-Box (L1) (Q): 4.42 Jarque-Bera (JB): 34.19
Prob(Q): 0.04 Prob(JB): 0.00
Heteroskedasticity (H): 0.43 Skew: 0.28
Prob(H) (two-sided): 0.06 Kurtosis: 6.60

对于这几张表的解读可以参考这两篇文章:

​ **1、**https://blog.csdn.net/zm147451753/article/details/83107535

​ **2、**https://www.jianshu.com/p/e45558ccf533

4、AIC与BIC

__参考:__https://zhuanlan.zhihu.com/p/142489599

除了通过ACF与PACF来确定模型的参数,更常用的方法是遍历多组参数产生多个参数不同的模型,然后分别计算的这些模型的AIC值(或BIC值),从而选取最好的一个模型

  • **AIC:**赤池信息准则,即Akaike information criterion,是由日本统计学家赤池弘次创立和发展的。建立在熵的概念基础上,可以权衡所估计模型的复杂度和此模型拟合数据的优良性,AIC越小,模型越好
    A I C = 2 k − 2 l n ( L ) AIC = 2k - 2ln(L) AIC=2k2ln(L)

  • **BIC:**贝叶斯信息准则,即Bayesian Information Criterions,BIC的惩罚项比AIC的大,考虑了样本数量,样本数量过多时,可有效防止模型精度过高造成的模型复杂度过高,BIC同样也是越小越好

B I C = k l n ( n ) − 2 l n ( L ) BIC = kln(n) - 2ln(L) BIC=kln(n)2ln(L)
L是在该模型下的最大似然,n是数据数量,k是模型的变量个数

AIC与BIC的可以通statsmodels库来计算

import statsmodels.api as sm
result = sm.tsa.SARIMAX(data,order=(2,1,0)).fit() # 模型建立与训练
AIC = result.aic # 获取AIC
BIC = result.bic # 获取BIC
print(AIC, BIC)
# 输出:-155.2274699440663 -148.48198421791824

五、模型诊断

模型的残差应该是一个平均值为0方差为常数的正态分布的白噪声,如果不是,则需要调整参数重新建模

  • python 代码:
import statsmodels.api as sm
result = sm.tsa.SARIMAX(data,order=(3,1,0)).fit() # data是以时间为索引的pandas Series
result.plot_diagnostics(figsize = (20,10)) #模型诊断

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mCcA6o82-1637157590289)(F:\typora imgs\模型诊断.png)]

  • 结果解读:

    右上方的图绿色的线是标准正态分布N(0,1),黄色的线是残差的分布情况。我们也可以通过左下方的QQ图来判断,越趋近与一条直线分布就越趋近于正态分布
    a.SARIMAX(data,order=(3,1,0)).fit() # data是以时间为索引的pandas Series
    result.plot_diagnostics(figsize = (20,10)) #模型诊断


[外链图片转存中...(img-mCcA6o82-1637157590289)]

- __结果解读:__

  右上方的图绿色的线是标准正态分布N(0,1),黄色的线是残差的分布情况。我们也可以通过左下方的QQ图来判断,越趋近与一条直线分布就越趋近于正态分布

你可能感兴趣的:(python,回归,开发语言)