写在前面,这是一篇单变量时间序列分析学习笔记,参考了很多大佬的文章,东拼西凑才勉强吧时间序列分析理清。在下数据分析萌新一名,有错误的地方欢迎指正,侵删
当一个序列的均值与标准差不随时间变化,则称该序列是一个平稳序列。 ARMA、AR、MA等模型只能用于预测平稳序列,因此需要对序列进行平稳性检验
如下图a为平稳序列,图b为非平稳序列
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VmJfJnY1-1637157590275)(F:\typora imgs\image-20211112222403614.png)]
参考: https://www.pianshen.com/article/5826219147/
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的值很大,接受原假设,即存在单位根,序列不具有平稳性
当序列不具有平稳性的时候,可以通过差分变换使序列变得平稳。所谓差分就是用下一个数减去上一个数,他们的差值形成了一个新的序列
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
白噪声序列的每个数据都是独立且随机的,没有分析的意义,所以接下来需要判断序列是否为白噪声
__原假设H0:__原本的数据都是独立的,即总体的相关系数为0,能观察到的某些相关仅仅产生于随机抽样的误差。
__责备假设H1:__原本的数据不是独立的
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)]
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=ρt−1xt−1+ρt−2xt−2+......+ρt−pxt−p+θt−1μt−1+θt−2μt−2+......+θt−pμt−p
可以发现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是移动平均阶数
__参考:__https://blog.csdn.net/Yuting_Sunshine/article/details/95317735
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阶后衰减趋于零(几何形或震荡型) |
根据上述规则确定模型以及参数后,就可以开始建模了,如下
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
__参考:__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=2k−2ln(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方差为常数的正态分布的白噪声,如果不是,则需要调整参数重新建模
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图来判断,越趋近与一条直线分布就越趋近于正态分布