其他
干货 | 携程如何基于ARIMA时序分析做业务量的预测
作者简介
June,携程数据分析经理,对数仓搭建,数据治理,数据分析等方面有较浓厚的兴趣。
一、 前言
根据指标的平稳性,分为平稳时间序列和非平稳时间序列;
根据指标的性质分类,分为总量指标时间序列,相对指标和平均指标时间序列;
根据指标的时间属性分类,分为时期指标时间序列,时点指标时间序列;
具有业务特征的周期性影响
节假日等特定时序节点的变异
地域差异,空间的相互作用
受到库存、实际市场容量的影响
其他外生变量,不可控自然或社会因素
二、 时间序列分析实践
2.1 ARIMA模型简介
同样的,当
2.2 ARIMA模型实践分析步骤
df = pd.read_csv('testdata.csv', encoding='gbk', index_col='ddate')
#时间序列索引转换为日期格式
df.index = pd.to_datetime(df.index)
#指标量转为float类型
df['cnt'] = df['cnt'].astype(float)
plt.figure(facecolor='white',figsize=(20,8))
plt.plot(df.index,df['cnt'],label='Time Series')
plt.legend(loc='best')
plt.show()
from statsmodels.tsa.stattools import adfuller
def test_stationarity(timeseries):
dftest = adfuller(timeseries, autolag='AIC')
return dftest[1]
pred_day = 7
train_start = datetime(2017,3,1)
train_end = datetime(2019,8,16)
pred_start = train_end+timedelta(1)
pred_end = train_end+timedelta(pred_day)
train_diff=df[train_start:train_end]
train_diff['cnt']=train_diff.diff()
print(test_stationarity(train_diff['cnt'][train_start+timedelta(1):train_end]))
plt.figure(facecolor='white',figsize=(20,8))
plt.plot(train_diff.index,train_diff['cnt'],label='Time Series after diff')
plt.legend(loc='best')
plt.show()
import statsmodels.api as sm
fig = plt.figure(figsize=(12,8))
ax1 = fig.add_subplot(211)
fig = sm.graphics.tsa.plot_acf(train_diff['cnt'][1:], lags=20, ax=ax1)
ax1.xaxis.set_ticks_position('bottom')
fig.tight_layout()
ax2 = fig.add_subplot(212)
fig = sm.graphics.tsa.plot_pacf(train_diff['cnt'][1:], lags=20, ax=ax2)
ax2.xaxis.set_ticks_position('bottom')
fig.tight_layout()
plt.show()
#定阶
warnings.filterwarnings("ignore") # specify to ignore warning messages
pmax = 8
qmax = 8
aic_matrix = [] #aic矩阵
for p in range(1,pmax+1):
tmp = []
for q in range(1,qmax+1):
try: #存在部分报错,所以用try来跳过报错。
model = ARIMA(endog=df['cnt'],order=(p,1,q))
results = model.fit(disp=-1)
tmp.append(results.aic)
print('ARIMA p:{} q:{} - AIC:{}'.format(p, q, results.aic))
except:
tmp.append(None)
aic_matrix.append(tmp)
aic_matrix = pd.DataFrame(aic_matrix) #从中可以找出最小值
p,q = aic_matrix.stack().idxmin() #先用stack展平,然后用idxmin找出最小值位置。
print(u'AIC最小的p值和q值为:%s、%s' %(p+1,q+1))
model = ARIMA(endog=df['cnt'], order=(p,1,q)) #建立ARIMA(7, 1,7)模型
result_ARIMA = model.fit(disp=-1,method='css')
predict_diff=result_ARIMA.predict()
#一阶差分还原
df_shift=df['cnt'].shift(1)
predict=predict_diff+df_shift
plt.figure(figsize=(18,5),facecolor='white')
predict[train_start+timedelta(p+1):train_end].plot(color='blue', label='Predict')
df['cnt'][train_start+timedelta(p+1):train_end].plot(color='red', label='Original')
err=sum(np.sqrt((predict[train_start+timedelta(p+1):train_end]-df['cnt'][train_start+timedelta(p+1):train_end])**2)/df['cnt'][train_start+timedelta(p+1):train_end])/df['cnt'][train_start+timedelta(p+1):train_end].size
plt.legend(loc='best')
plt.title('Error: %.4f'%err)
plt.show()
图7
y_forecasted =result_ARIMA.forecast(steps=pred_day, alpha=0.01)[0] #作为期7天的预测
y_truth = df[pred_start:pred_end]['cnt']
# 均方根误差 #平均错误率
mse = np.sqrt( ((y_forecasted - y_truth) ** 2) ).mean()
error_rate = ( abs(y_forecasted - y_truth)/y_truth ).mean()
print('\nThe Mean Error rate of our forecasts is {}'.format(round(error_rate, 4)))
resid = result_ARIMA_improve.resid #赋值
plt.figure(figsize=(12,8))
qqplot(resid,line='q',fit=True)
#利用D-W检验,检验残差的自相关性
print('D-W检验值为{}'.format(durbin_watson(resid.values)))
图9
三、总结与展望
对于时间序列的分析一定做好前期评估工作,直观的图表分析会助力我们的决策。多探索优秀的开源工具库,往往会使我们事半功倍。
模型选择至关重要,明确模型的适用场景,根据自身的时序选择适合的模型分析。
ARIMA模型在短时间内的预期效果还算可以,但是长时间比如未来一年的预测不太适用,因为偏差会逐渐增大。
现实中的复杂场景,单一模型很难解决,需要考虑多模型结合的方式实现分析预测。
【推荐阅读】
“携程技术”公众号后台回复“新书”,
可免费获得两本书的试读样章~
《携程架构实践》
京东
当当
《携程人工智能实践》
京东
当当
“携程技术”公众号
分享,交流,成长