数据分析之利用arma算法对销售进行预测

一、目标

     销售数据是随着时间变化的序列,通过对未来的销售进行预测,方便对人员、物料等各种资源投入的把控,控制好库存,减少浪费,也可以制定未来的营运策略,提高管理效率。

    这里使用ARMA(AutoRegressive Moving Average)算法,不仅与前P期的序列值有关,也与前q期的随机扰动有关。

二、数据采集和处理

  • 1.数据采集

采集随着时间变化的销售数据,为了数据保护需要,销售数据做了特殊处理,不代表真实销售。 image

  • 2.平稳性检验

平稳ARMA(p,q)的均值和方差都是常数,用什么模型主要看自相关系数和偏自相关系数。如果自相关拖尾,偏自相关截尾,即p<>0 &q=0 则用AR,反之MA,如果p阶拖尾,q阶也拖尾,则ARMA。p代表周期、q代表噪音。

这里采用两种方法来检验:

a.画时序图

image

通过时序图可以发现数据是平稳的。

b.画自相关图

image  

 x 轴表示滞后值,y 轴上 -1 和 1 之间则表现了这些滞后值的正负相关性。蓝色区域为置信区间,默认情况下,置信区间这被设置为95%,这表明,这段代码之外的相关值很可能是相关的,而不是统计上的意外。滞后值为 0 相关性为 1 的点表示观察值与其本身 100% 正相关。自相关系数会很快衰减向0,所以可认为是平稳序列

c.单位根ADF检验的方法。如果存在单位根,则说明是非平稳时间序列

image

可以看出这里的ADF结果为-4.3, p-value小于0.05,  1%的结果-3.45>ADF的结果-4.3,所以说明极其显著拒绝原假设,不存在单位根,所以可以得出结论本数据是平稳的。

  • 3.随机性检验

image

可以看出延迟1期后,p值为3.87e-19小于0.05,因此95%可以拒绝原假设,认为该序列为非白噪声序列,有信息可以提取。

代码

import  pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import adfuller as ADF
from statsmodels.stats.diagnostic import acorr_ljungbox
#画时序图
data=pd.read_excel(r'C:\Users\Administrator\Desktop\data.xlsx')
data.day=pd.to_datetime(data.day)
plt.plot(data.day,data.sales)
plt.xlabel('day')
plt.ylabel('sales')
plt.title('Time Series')
plt.show()
#平稳性检测
print('ADF result is',ADF(data.sales))
#纯随机检查
print('纯随机检查结果为',acorr_ljungbox(data.sales,lags=1)) #lags表示延迟期数

#三、建模

计算ARMA(p,q)

这里采用BIC(贝叶斯信息量 bayesian information criterion ) = -2 ln(L) + ln(n)*k来定阶段

为了节省运算时间(其实也消耗了很多时间),这里p最大设置为10,q最大设置为6

from statsmodels.tsa.stattools import arma_order_select_ic
print('BIC求解的模型阶次为',arma_order_select_ic(data.sales,max_ar=10,max_ma=6,ic='bic')['bic_min_order'])

![image](https://raw.githubusercontent.com/lbship/lbship.github.io/master/img/ads/ar6.png) 

这个过程相当耗时,可以看到这里输出是1,0,所以选用ARMA(1,0)这个模型。

model = ARMA(data.sales,(1,0)).fit()
print(model.summary2()) #给出一份模型报告
print(model.forecast(10)) #作为期10天的预测,返回预测结果、标准误差、置信区间。  

image

看看误差有多少

forcast=pd.DataFrame(model.forecast(10)[0],index=x,columns=['forcastsales']) #作为期10天的预测,返回预测结果、标准误差、置信区间。
actual=pd.DataFrame(list(file.iloc[90:100].sales),index=x,columns=['actualsales'])
delta=((forcast.forcastsales-actual.actualsales)/actual.actualsales).mean()*100
print('误差为%0.2f%%'%delta)

image

完整代码:


import  pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import adfuller as ADF
from statsmodels.stats.diagnostic import acorr_ljungbox
from statsmodels.tsa.arima_model import ARMA
from statsmodels.tsa.stattools import arma_order_select_ic
from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.graphics.tsaplots import plot_pacf
 
file=pd.read_excel(r'C:\Users\Administrator\Desktop\data.xlsx')
data=file.iloc[:90]#取到12月21号的数据,留下10天验证
data.day=pd.to_datetime(data.day)
#画时序图
plt.plot(data.day,data.sales)
plt.xlabel('day')
plt.ylabel('sales')
plt.title('Time Series')
plt.show()
#画自相关图 和偏自相关图
plot_acf(data.sales).show()
plot_pacf(data.sales).show()
#平稳性检测
print('ADF result is',ADF(data.sales))
#纯随机检查
print('纯随机检查结果为',acorr_ljungbox(data.sales,lags=1)) #lags表示延迟期数
 
#定阶
print('BIC求解的模型阶次为',arma_order_select_ic(data.sales,max_ar=10,max_ma=6,ic=['aic', 'bic', 'hqic'])['bic_min_order'])
model = ARMA(data.sales,(1,0)).fit()
model.summary2() #给出一份模型报告
x=file.iloc[90:100].day
forcast=pd.DataFrame(model.forecast(10)[0],index=x,columns=['forcastsales']) #作为期10天的预测,返回预测结果、标准误差、置信区间。
actual=pd.DataFrame(list(file.iloc[90:100].sales),index=x,columns=['actualsales'])
delta=((forcast.forcastsales-actual.actualsales)/actual.actualsales).mean()*100
print('误差为%0.2f%%'%delta)
# plt.plot(x,forcast)
# plt.plot(x,actual,color='red')
# plt.show()