用Python语言进行多元时间序列ARIMAX模型分析
1.ARIMAX模型定义
ARIMAX模型是指带回归项的ARIMA模型,又称扩展的ARIMA模型。回归项的引入有利于提高模型的预测效果。引入的回归项一般是与预测对象(即被解释变量)相关程度较高的变量。比如分析居民的消费支出序列时,消费会受到收入的影响,如果将收入也纳入到研究范围,就能够得到更精确的消费预测。
2.ARIMAX的建模步骤
读取数据(观察值序列)-->通过观察响应变量的时序图来判断是否需要进行差分来提取序列相关信息-->进行差分使得差分后的序列无趋势无周期-->切分训练数据与测试数据
-->平稳性检验(一般会进行单位根检验和自相关图与偏自相关图检验)-->纯随机性检验-->协整检验(EG两步法)-->建立ARIMAX模型-->模型检验和优化-->未来预测-->做图像可视化观察
注:本案例未进行纯随机性检验和协整检验,有需要可自行添加
3.本案例数据查看
案例数据中,第一列为时间序列数据,第二列为响应数据,第三列以及后每列数据为输入数据
4.当缕清数据性质后进行操作,具体Python代码步骤如下(有省略步骤请按具体建模步骤自行添加)
4.1倒库
import pandas as pd import matplotlib.pyplot as plt import numpy as np from statsmodels.tsa.stattools import adfuller as ADF from statsmodels.graphics.tsaplots import plot_acf from statsmodels.graphics.tsaplots import plot_pacf import pyflux as pf #pyflux库是一个专门用来建立时间序列模型的python库,需要numpy 1.23.0版本 from sklearn.metrics import mean_absolute_error,mean_squared_error #绝对值误差 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False
4.2读取数据
df=pd.read_excel("时间序列的多元回归分析.xlsx") data=df.copy() data.set_index('year',inplace=True) #展示部分所用数据 print(data.head())
4.3进行一阶差分
data=data.diff(1).iloc[1:,] print(data.head())
4.4观察每一个标量指标经过差分后的时序图
plt.figure(figsize=(20,20)) plt.subplot(3,3,1) data.EXP.plot(c='r') plt.grid() plt.xlabel("年份") plt.ylabel("EXP") plt.subplot(3,3,2) data.CUR.plot(c='r') plt.grid() plt.xlabel("年份") plt.ylabel("CUR") plt.subplot(3,3,3) data.CRR.plot(c='r') plt.grid() plt.xlabel("年份") plt.ylabel("CRR") plt.subplot(3,3,4) data.D.plot(c='r') plt.grid() plt.xlabel("年份") plt.ylabel("D") plt.subplot(3,3,5) data.Trade.plot(c='r') plt.grid() plt.xlabel("年份") plt.ylabel("Trade") plt.subplot(3,3,6) data.Invest.plot(c='r') plt.grid() plt.xlabel("年份") plt.ylabel("Invest") plt.subplot(3,3,7) data.Rate.plot(c='r') plt.grid() plt.xlabel("年份") plt.ylabel("Rate") plt.subplot(3,3,8) data.Gov.plot(c='r') plt.grid() plt.xlabel("年份") plt.ylabel("Gov") plt.subplot(3,3,9) data.Pro.plot(c='r') plt.grid() plt.xlabel("年份") plt.ylabel("Pro") plt.show()
4.5切分数据
#切分数据 85%训练 15%测试 trainnum = np.int64(data.shape[0] * 0.85) traindata = data.iloc[0:trainnum, :] testdata = data.iloc[trainnum:data.shape[0], :] print(traindata.shape) print(testdata.shape)
4.6单位根检验
#单位根检验:检验序列平稳性 def Adf_test(data): Adftest = ADF(data, autolag='BIC') Adfoutput = pd.Series(Adftest[0:4], index=['Test Statistic', 'p-value', 'Lags Used', 'Number of Observations Used']) print(">>>{}的单位根检验结果:".format(data.name)) print(Adfoutput) Adf_test(traindata.EXP) # p-value 0.994235 不平稳 Adf_test(traindata.CUR) # p-value 0.384367 不平稳 Adf_test(traindata.CRR) # p-value 0.992719 不平稳 Adf_test(traindata.D) # p-value 1.000000 不平稳 Adf_test(traindata.Trade) # p-value 0.126649 不平稳 Adf_test(traindata.Invest) # p-value 0.236028 不平稳 Adf_test(traindata.Rate) # p-value 1.151937e-26 平稳 Adf_test(traindata.Gov) # p-value 0.999009 不平稳 Adf_test(traindata.Pro) # p-value 0.907343 不平稳
4.7对每个差分后的数组进行自相关图与偏自相关图绘制
#对每个数组进行自相关图与偏自相关图绘制 #ACF(自相关图)、PACF(偏自相关图) def Acf_Pacf(data): f = plt.figure(facecolor='white',figsize=(6,2)) ax1 = f.add_subplot(121) plot_acf(data, lags=data.shape[0]//2-1, ax=ax1) ax2 = f.add_subplot(122) plot_pacf(data, lags=data.shape[0]//2-1, ax=ax2) plt.show() Acf_Pacf(traindata.EXP) Acf_Pacf(traindata.CUR) Acf_Pacf(traindata.CRR) Acf_Pacf(traindata.D) Acf_Pacf(traindata.Trade) Acf_Pacf(traindata.Invest) Acf_Pacf(traindata.Rate) Acf_Pacf(traindata.Gov) Acf_Pacf(traindata.Pro)
4.8建立ARIMAX模型
#建立ARIMAX模型(利用差分后的数据进行建模,实际上仍然相当于arimax(p,d,q)) model=pf.ARIMAX(data=traindata,formula="EXP~CUR+CRR+D+Trade+Invest+Rate+Gov+Pro",ar=1,integ=0,ma=1) result=model.fit("MLE") print(result.summary())
4.9模型结果拟合
#模型结果拟合 model.plot_fit(figsize=(5,3))
4.10未来预测数据
#未来预测数据 future=model.predict(h=testdata.shape[0], #未来期数 oos_data=testdata, #测试集数据 intervals=True) #预测置信区间 print(future) # print(future.to_excel("未来数据及置信区间.xlsx")) #未来预测图像(要注意是否进行了差分) model.plot_predict(h=testdata.shape[0], #未来期数 oos_data=testdata, #测试集数据 past_values=traindata.shape[0], figsize=(6,4))
4.11可视化原始数据和预测数据进行对比
#可视化原始数据和预测数据进行对比 traindata.EXP.plot(figsize=(14,7),label="训练集数据") testdata.EXP.plot(figsize=(14,7),label="测试集数据") future.EXP.plot(style="g--o",label="未来预测数据") #可视化出置信区间 plt.fill_between(future.index,future["5% Prediction Interval"], future["95% Prediction Interval"],color='blue',alpha=0.15, label="95%置信区间") plt.grid() plt.xlabel("Time") plt.ylabel("EXP") plt.title("ARIMAX(1,0,1)模型") # plt.legend(loc=0) plt.show()
4.12模型优化,通过遍历寻找合适的 p,q
#通过遍历寻找合适的 p,q p = np.arange(6) q = np.arange(6) pp,qq = np.meshgrid(p,q) resultdf = pd.DataFrame(data = {"arp":pp.flatten(),"mrq":qq.flatten()}) resultdf["bic"] = np.double(pp.flatten()) resultdf["mae"] = np.double(qq.flatten()) ## 迭代循环建立多个模型 for ii in resultdf.index: model_i = pf.ARIMAX(data=traindata,formula="EXP~CUR+CRR+D+Trade+Invest+Rate+Gov+Pro",ar=resultdf.arp[ii],ma=resultdf.mrq[ii],integ=0) try: modeli_fit = model_i.fit("MLE") bic = modeli_fit.bic EXP_pre = model.predict(h=testdata.shape[0],oos_data=testdata) mae = mean_absolute_error(testdata.EXP,EXP_pre.EXP) except: bic = np.nan resultdf.bic[ii] = bic resultdf.mae[ii] = mae #绝对值误差 print("模型迭代结束") print(resultdf.sort_values(by="bic").head()) #此时找到了最优的arma参数,换掉之前的模型参数即可
到此,多元时间序列建模基本结束!