ARIMA模型预测餐厅销量
1 2 3 | import numpy as np import pandas as pd import matplotlib.pyplot as plt |
1 2 | from IPython.core.interactiveshell import InteractiveShell InteractiveShell.ast_node_interactivity = "all" |
1 2 | from matplotlib.pylab import style # 自定义图表风格 style.use( 'ggplot' ) |
1 2 3 | # 解决中文的显示问题 plt.rcParams[ "font.sans-serif" ] = [ "SimHei" ] plt.rcParams[ "axes.unicode_minus" ] = False |
1 2 3 4 5 6 | from statsmodels.graphics.tsaplots import plot_acf,plot_pacf # 自相关图、偏自相关图 from statsmodels.tsa.stattools import adfuller as ADF # 平稳性检验 from statsmodels.stats.diagnostic import acorr_ljungbox # 白噪声检验 import statsmodels.api as sm # D-W检验,一阶自相关检验 from statsmodels.graphics.api import qqplot # 画QQ图,检验一组数据是否服从正态分布 from statsmodels.tsa.arima_model import ARIMA |
1、导入数据
1 2 | sale = pd.read_excel( './arima_data.xls' , index_col = '日期' ) sale.head() |
1 2 3 4 | sale.info() print ( '-----' ) sale.销量 = sale.销量.astype( 'float' ) sale.info() |
2、原始序列检验
· 时序图
1 2 3 4 5 | plt.figure(figsize = ( 10 , 5 )) sale.plot() plt.show() #解读:具有单调递增趋势,则是非平稳序列。 |
· 自相关图
1 2 3 | plot_acf(sale, lags = 35 ).show() #解读:自相关系数长期大于零,没有趋向于零,说明序列间具有很强的长期相关性。 |
· 平稳性检验
1 2 3 4 5 | #方法:单位根检验 print ( '原始序列的ADF检验结果为:' ,ADF(sale.销量)) #解读:P值大于显著性水平α(0.05),接受原假设(非平稳序列),说明原始序列是非平稳序列。 |
第一个是adf检验的结果。 第二个是统计量的P值。 第三个是计算过程中用到的延迟阶数。 第四个是用于ADF回归和计算的观测值的个数。 第五个是配合第一个一起看的,是在99%,95%,90%置信区间下的临界的ADF检验的值。
原文链接:adfuller函数返回值的参数说明与记录
3、一阶差分序列检验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | d1_sale = sale.diff(periods = 1 , axis = 0 ).dropna() #时序图 plt.figure(figsize = ( 10 , 5 )) d1_sale.plot() plt.show() #解读:在均值附件比较平稳波动 #自相关图 plot_acf(d1_sale, lags = 34 ).show() #解读:有短期相关性,但趋向于零。 #平稳性检验 print ( '原始序列的ADF检验结果为:' ,ADF(d1_sale.销量)) #解读:P值小于显著性水平α(0.05),拒绝原假设(非平稳序列),说明一阶差分序列是平稳序列。 |
· 白噪声检验
1 2 3 | print ( '一阶差分序列的白噪声检验结果为:' ,acorr_ljungbox(d1_sale, lags = 1 )) #返回统计量、P值 #解读:p值小于0.05,拒绝原假设(纯随机序列),说明一阶差分序列是非白噪声序列。 |
4、定阶
· 参数调优:人工判别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | d1_sale = sale.diff(periods = 1 , axis = 0 ).dropna() #自相关图 plot_acf(d1_sale, lags = 34 ).show() #解读:有短期相关性,但趋向于零。 #偏自相关图 plot_pacf(d1_sale, lags = 10 ).show() #偏自相关图 plot_pacf(d1_sale, lags = 17 ).show() #解读:自相关图,1阶截尾;偏自相关图,拖尾。则ARIMA(p,d,q)=ARIMA(0,1,1) |
· 参数调优:BIC
1 2 3 4 | pmax = int ( len (d1_sale) / 10 ) #一般阶数不超过length/10 qmax = int ( len (d1_sale) / 10 ) #一般阶数不超过length/10 pmax qmax |
1 2 3 4 5 6 7 8 9 | bic_matrix = [] for p in range (pmax + 1 ): tmp = [] for q in range (qmax + 1 ): try : tmp.append(ARIMA( tuple (sale), (p, 1 , q)).fit().bic) except : tmp.append( None ) bic_matrix.append(tmp) |
1 2 | bic_matrix = pd.DataFrame(bic_matrix) bic_matrix |
1 2 | p,q = bic_matrix.stack().idxmin() #最小值的索引 print ( '用BIC方法得到最优的p值是%d,q值是%d' % (p,q)) |
· 参数调优:AIC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | pmax = int ( len (d1_sale ) / 10 ) #一般阶数不超过length/10 qmax = int ( len (d1_sale) / 10 ) #一般阶数不超过length/10 aic_matrix = [] for p in range (pmax + 1 ): tmp = [] for q in range (qmax + 1 ): try : tmp.append(ARIMA( tuple (sale), (p, 1 , q)).fit().aic) except : tmp.append( None ) aic_matrix.append(tmp) aic_matrix = pd.DataFrame(aic_matrix) p,q = aic_matrix.stack().idxmin() #最小值的索引 |
1 | print ( '用AIC方法得到最优的p值是%d,q值是%d' % (p,q)) |
5、建模及预测
· 建模
1 2 3 4 | #创建模型 model = ARIMA( tuple (sale), ( 0 , 1 , 1 )).fit() #查看模型报告 model.summary2() |
· 残差检验
1 2 3 4 5 6 7 8 9 10 11 12 | resid = model.resid #自相关图 plot_acf(resid, lags = 35 ).show() #解读:有短期相关性,但趋向于零。 #偏自相关图 plot_pacf(resid, lags = 10 ).show() #偏自相关图 plot_pacf(resid, lags = 17 ).show() |
· QQ图
1 2 3 | qqplot(resid, line = 'q' , fit = True ).show() #解读:残差服从正态分布,均值为零,方差为常数 |
· D-W检验
德宾-沃森检验,简称D-W检验,是目前检验自相关性最常用的方法,但它只适用于检验一阶自相关性。 因为自相关系数ρ的值介于-1和1之间,所以 0≤DW≤4。
- 并且DW=O <=> ρ=1 即存在正自相关性
- DW=4 <=> ρ=-1 即存在负自相关性
- DW=2 <=> ρ=0 即不存在(一阶)自相关性
因此,当DW值显著的接近于O或4时,则存在自相关性,而接近于2时,则不存在(一阶)自相关性。
1 2 3 | print ( 'D-W检验的结果为:' ,sm.stats.durbin_watson(resid.values)) #解读:不存在一阶自相关 |
· Ljung-Box检验
Ljung-Box test是对randomness的检验,或者说是对时间序列是否存在滞后相关的一种统计检验。对于滞后相关的检验,我们常常采用的方法还包括计算ACF和PCAF并观察其图像,但是无论是ACF还是PACF都仅仅考虑是否存在某一特定滞后阶数的相关。LB检验则是基于一系列滞后阶数,判断序列总体的相关性或者说随机性是否存在。
时间序列中一个最基本的模型就是高斯白噪声序列。而对于ARIMA模型,其残差被假定为高斯白噪声序列,所以当我们用ARIMA模型去拟合数据时,拟合后我们要对残差的估计序列进行LB检验,判断其是否是高斯白噪声,如果不是,那么就说明ARIMA模型也许并不是一个适合样本的模型。
检验的结果就是看最后一列前十二行的检验概率(一般观察滞后1~12阶),如果检验概率小于给定的显著性水平,比如0.05、0.10等就拒绝原假设,其原假设是相关系数为零。
1 2 3 4 | # 方法一 print ( '残差序列的白噪声检验结果为:' ,acorr_ljungbox(resid,lags = 1 )) #返回统计量、P值 #解读:残差是白噪声 |
1 2 3 4 5 | # 方法二 confint,qstat,pvalues = sm.tsa.acf(resid.values, qstat = True ) #qstat is Ljung-Box Q-Statistic. confint is Confidence intervals for the ACF data = np.c_[ range ( 1 , 36 ), confint[ 1 :], qstat, pvalues] table = pd.DataFrame(data, columns = [ 'lag' , "confint" , "qstat" , "pvalues(>Q)" ]) print (table.set_index( 'lag' )) |
· 预测
1 2 3 | #预测 print ( '未来7天的销量预测:' ) model.forecast( 7 ) #预测、标准差、置信区间 |
1 2 | forecast = pd.Series(model.forecast( 7 )[ 0 ], index = pd.date_range( '2015-2-7' , periods = 7 , freq = 'D' )) forecast |
1 2 3 4 5 | data = pd.concat((sale, forecast), axis = 0 ) data.columns = [ '销量' , '未来7天销量' ] plt.figure(figsize = ( 10 , 5 )) data.plot() plt.show() |