早就知道ARIMA这个算法,但以前只会用来简单做个预测,对于参数选择,什么拖尾截尾一知半解,借着这次重新学一下ARIMA的原理,梳理一下使用ARIMA做时序预测的流程。
原理部分我是看了一篇知乎文章,讲的非常全面,我看了这篇文章感觉才懂,墙裂推荐给大家。感觉有这种博主愿意花费很多时间把一个算法讲的详细全面,真的很好!!!
https://www.zhihu.com/question/265009657/answer/3055557539
自己拿了一个手边的数据梳理了一下arima做预测的一个典型流程吧,这个代码模板无脑用。
总体流程分为:
1. 数据平稳性检测(原数据及差分数据)
2. 绘制安acf,pacf图初步判断数据适合AR模型还是MA模型还是ARIMA
这一步似乎可以省略?因为第三步做了超参优化可以直接帮助选择模型,p=0就是MA或则IMA模型,q=0就是AR或者ARI模型
3. 根据赤池信息准则和贝叶斯信息准则选择合适的(p,d,q)
4. 训练最佳的ARIMA模型并且进行预测
下面是代码:
导包
import matplotlib.pyplot as plt
import pandas as pd
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.tsa.stattools import adfuller
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
1. 查看数据平稳性
def test_stationarity(timeseries):
# 执行Dickey-Fuller测试,检测数据平稳性
#p值小于0.05就可拒绝原假设(数据非平稳),也就是说我们认为数据是平稳的
print('Results of Dickey-Fuller Test:')
dftest = adfuller(timeseries, autolag='AIC')
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)
def diff(df):
# 绘制原数据、一阶差分、二阶差分折线图查看数据平稳性
# 注 data_val是我原数据列名,需要根据自己数据调整
df['first_diff'] = df['data_val'] - df['data_val'].shift(1)
df['second_diff'] = df['first_diff']-df['first_diff'].shift(1)
#绘图查看数据平稳性
plt.figure()
plt.plot(df['data_val'])
plt.title('原数据')
plt.show()
plt.figure()
plt.plot(df['first_diff'])
plt.title('一阶差分结果')
plt.show()
plt.figure()
plt.plot(df['second_diff'])
plt.title('二阶差分结果')
plt.show()
#dickey fuller检测数据平稳性
test_stationarity(df['data_val'])
test_stationarity(df['first_diff'].iloc[1:]) #一阶差分第一个数据点为nan
test_stationarity(df['second_diff'].iloc[2:]) #二阶查分前两个数据点为nan
2. 绘制ACF PACF图
关于ACF和PACF的分析,那篇知乎文章有很详细的分析
def plot_acf_and_pacf(df):
'''
Parameters
----------
df : 时序数据,可以是dataframe,series,list
对任意时间序列,当ACF图像呈现拖尾、且PACF图像呈现截尾状态时,当前时间序列适用AR模型,且
PACF截尾的滞后阶数就是超参数p的理想值;
对任意时间序列,当PACF图像呈现拖尾、且ACF图像呈现截尾状态时,当前时间序列适用MA模型,
ACF截尾的滞后阶数就是超参数q的理想值
对任意时间序列,当ACF图像和PACF图像都不呈现拖尾状态时,无论图像是否截尾,时间序列都
适用于ARIMA模型,且此时ACF和PACF图像无法帮助我们确定p和q的具体值,但能确认p和q一
定都不为0
'''
#计算Xt和Xt-1~Xt-30自相关系数
plot_acf(df,lags=30)
plt.show()
plot_pacf(df,lags=30)
plt.show()
3. 根据赤池信息准则和贝叶斯信息准则,寻找最佳的(p,d,q)来建立模型 。这里我挑选最佳参数是根据赤池信息准则和贝叶斯信息准则的均值,也可以自行查看输出的aic_bic_df来挑选最佳参数。
def param_optimization(df):
# 尝试不同的ARIMA参数组合
models = [] #存储每一次的模型
aic_bic = [] #存储每一次的参数及aic bic结果
aic_bic_min = 10000
best_params = None
p_values = range(0,5)
d_values = range(0, 3) #d也可以通过差分结果得出
q_values = range(0, 5)
df.index.feeq = 'MS' #明确一下数据频率,可写可不写,不写模型会自动计算频率
for p in p_values:
for d in d_values:
for q in q_values:
try:
model = ARIMA(df, order=(p, d, q))
fit_model = model.fit()
aic = fit_model.aic
bic = fit_model.bic
models.append(fit_model)
aic_bic.append((p, d, q, aic, bic))
aic_bic_value = (aic+bic)/2
if aic_bic_value < aic_bic_min:
aic_bic_min = aic_bic_value
best_params=(p,d,q)
print(f'ARIMA({p},{d},{q}): AIC={aic}, BIC={bic}')
except:
continue
# 将AIC和BIC值转换为DataFrame以便查看
aic_bic_df = pd.DataFrame(aic_bic, columns=['p', 'd', 'q', 'AIC', 'BIC'])
print(aic_bic_df)
return best_params,aic_bic_df
4. 拟合模型进行预测
df = pd.read_excel(r'D:\data.xlsx',index_col=0)#读取数据
#根据自己数据可能需要做一些数据处理工作,我这里没写
df.set_index('data_time',inplace=True,drop=True)
#找最佳的p d q
best_params,aic_bic_df = param_optimization(df)
#拟合模型
model = ARIMA(df, order=(best_params[0],best_params[1],best_params[2]))
model_fit = model.fit()
#预测
pre = model_fit.forecast(steps=5)
好啦,就是这样,希望能帮到有需要的伙伴!