某游戏主要用户为青少年,公司的用户活跃、新增、留存等数据受寒暑假影响,出现非常明显的季节性波动,为了提前做好暑假部署,需根据历史数据预测暑假期间留存用户数量。
时间序列模型根据原序列是否平稳以及回归中所含部分的不同,可分为移动平均模型(MA)、自回归模型(AR)、自回归移动平均模型(ARMA)、自回归差分移动平均模型(ARIMA)。其中季节ARIMA模型是将受季节影响的非平稳时间序列通过消除季节影响转化为平稳时间序列,然后将平稳时间序列建立ARMA模型。
1、数据准备
import pmdarima as pm
import pandas as pd
import matplotlib.pyplot as plt
#导入数据
data=pd.read_excel(r"C:\Users\csdn\Desktop\test.xlsx",sheet_name="OG",index_col = u'month')['liucun']
data=pd.DataFrame(data)
#查看原始数据时序图
plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号
data.plot()
plt.show()
2、查看数据基本情况
#查看原始数据自相关系数
from statsmodels.graphics.tsaplots import plot_acf
plot_acf(data).show()
#定义ADF输出格式化函数,结果中Test Statistic大于1%置信水平值,P>0.05,liucun存在单位根,序列不平稳
from statsmodels.tsa.stattools import adfuller
def adf_test(timeseries):
print ('ADF检验结果:')
dftest = adfuller(timeseries, autolag='AIC')
dfoutput = pd.Series(dftest[0:4], index=['Test Statistic','p-value','Number of Lags Used','Number of Observations Used'])
for key,value in dftest[4].items():
dfoutput['Critical Value (%s)'%key] = value
print (dfoutput)
#对数据集使用ADF检验
adf_test(data[u'liucun'])
3、如果时间序列不平稳,需进行差分转换,得到差分之后的平稳序列再进行预测
(1)如果明确需一阶差分的话
#ADF检验结果说明原始序列不平稳,需进行差分,一阶 差分
D_data = data.diff(1).dropna()
D_data.columns = [u'liucun差分']
D_data.plot() #时序图
plt.show()
plot_acf(D_data).show() #自相关图
#对一阶差分后的序列进行单位根检验,P值小于0.05,一阶差分后的序列平稳
from statsmodels.graphics.tsaplots import plot_pacf
plot_pacf(D_data).show() #偏自相关图
adf_test(D_data[u'liucun差分'])
(2)如果不明确需进一步确定需几阶差分,再进行AR、MA定阶
#定好差分阶数后,对模型p,q定阶,可用aic或bic指标,ARIMA(data, (0, 0, 1)).fit().bic
from statsmodels.tsa.arima_model import ARIMA
pmax =int(len(data) / 5) #一般阶数不超过 length /10
qmax = int(len(data) / 5)
aic_matrix = []
for p in range(pmax +1):
temp= []
for q in range(qmax+1):
try:
temp.append(ARIMA(data, (p, 1, q)).fit().aic)
except:
temp.append(None)
aic_matrix.append(temp)
aic_matrix = pd.DataFrame(aic_matrix) #将其转换成Dataframe 数据结构
print(aic_matrix)
p,q = aic_matrix.stack().idxmin() #先使用stack 展平, 然后使用 idxmin 找出最小值的位置
print(u'AIC 最小的p值 和 q 值:%s,%s' %(p,q))
4、定好阶后可带入ARIMA模型进行拟合
#找到是AIC/BIC最小的p,q参数,代入ARIMA模型中,进行拟合
from statsmodels.tsa.arima_model import ARIMA
print(ARIMA(data, (5,1,0)).fit().bic)
model=ARIMA(data, (5,1,0)).fit()
model.summary2()
#model.fittedvalues
fittedvalues = pd.Series(model.fittedvalues, copy=True)
plt.figure(figsize=(10, 6))
plt.plot(fittedvalues,label="forecast")
plt.plot(data,label="real")
plt.plot(D_data,label="diff")
plt.xlabel('month',fontsize=12,verticalalignment='top')
plt.ylabel('avgdau',fontsize=14,horizontalalignment='center')
plt.legend()
plt.show()
5、对拟合的模型效果进行评价
# 计算R平方值
import numpy as np
yhat =model.fittedvalues # or [p(z) for z in x]
ybar = np.sum(D_data[u'liucun差分'])/len(D_data[u'liucun差分']) # or sum(y)/len(y)
ssreg = np.sum((D_data[u'liucun差分']-ybar)**2) # or sum([ (yihat - ybar)**2 for yihat in yhat])
sstot = np.sum((D_data[u'liucun差分'] -yhat)**2) # or sum([ (yi - ybar)**2 for yi in y])
R =1- (sstot/ssreg)
R
6、利用拟合出来的模型进行预测
#利用模型进行预测
model.forecast(7) #为未来8个月进行预测, 返回预测结果, 标准误差, 和置信区间