1: 什么是ARIMA模型
介绍ARIMA之前,我们首先介绍一下时间序列回归建模和一般回归建模的区别。想象一下我们预测某个人是否会还对应的贷款,即使我们拥有每个用户之前的贷款时间,但是这个时间仅仅表示用户申请贷款的时间,不同用户是否会还贷款和他们申请的时间关系不会很大(经济大萧条除外),显然此类问题即使一个回归问题。在想象一下我们预测某种车型在某省接来四个月的销量,根据我们的常识判断,前几个月的销量如果一直很高的话,那么接下来几个月的销量有很大可能较高,反之亦然,所以此类问题显然是一个时序序列回归建模。简而言之,判断的标准就是预测变量和之前的预测值之间是否彼此独立还是存在一定关系。
ARIMA模型的全称叫做自回归移动平均模型,全称是(ARIMA, Autoregressive Integrated Moving Average Model)是一种常见的时间序列预测的模型。ARIMA模型描述当前值与历史值之间的关系,用变量自身的历史时间数据对自身进行预测,自回归模型必须满足平稳性的要求。
2:ARIMA模型中的相关参数及概念
2.1 相关概念
2.1.1 平稳性
平稳性要求样本时间序列所得到的拟合曲线在未来一段时间内仍能顺着现有的形态地延续下去。平稳性要求序列的均值和方差不发生明显变化。
2.1.2 严平稳
严平稳数据的分布不随时间的改变而改变。如白噪声(正太),无论怎么取,都是期望为0,方差为1。
2.1.3 移动平均法和加权移动平均法
移动平均法是指将前N个值的平均值作为预测值。加权移动平均法是指将前N个值被赋予不同的权重,将加权之后的结果作为预测值。
2.1.4 差分
将当前行减去上一行的数据作为当前行的值。
2.2 相关参数
ARIMA(p,d,q)模型中主要的三个参数是p,d,q,具体说明可见我的下篇博客。
p是自回归(AR)的项数,表示用前p的历史值作为自变量预测当前值
d是差分(I)的系数,其表示差分操作是指后一行减前一行,目的是为了使时间序列变的平稳
q是移动平均(MA)的项数,意思每一行被自身和自身之前的q-1行的平均数取代
3: ARIMA模型实现
首先说明一下,这个模型是我参考比赛群里分享的方案,因为源码中没有任何的注释,我这边学习一下讲述一下他建模的过程h和思想。如果有啥侵权一类的给我说一声,我会加上引用的。okay开始讲解。CCF乘用车细分市场销量预测要求我们预测某个地区某种车型接下来四个月车辆的销售情况。如果我们直接将数据集中的销量作为标签,然后使用ARIMA模型进行建模其会忽略地区和车型这两个特征。一个简单的做法训练数据是某个省某种车型,预测的也是同一个省同样的车型。但是这样的话训练数据为某个省某种车型的2016/01到2017/12总共24个销售数据,显然这种操作的话数据量会很少,效果不一定好。所以可以尝试训练数据为仅仅是某种车型,这样会导致不同地区的同月份的车型销量是一致的,所以肯定不好。
3.1 代码的解释
ARIMA模型的基本流程,首先得到需要预测的属性列,然后使用auto_arima自动调参得到对应的ARIMA模型中(p,d,q)对应的值,最后预测输出结果即可。
# @Time : 2019/11/19 9:13
# @Author : YYLin
# @Email : 854280599@qq.com
# @File : ARIMA_Model.py
import pandas as pd
import numpy as np
import seaborn as sns
from tqdm import tqdm
from pmdarima.arima import auto_arima
import warnings
sns.set()
warnings.filterwarnings('ignore')
path = 'data/'
train = pd.read_csv(path + 'train_sales_data.csv')
train = train.sort_values(['regYear', 'regMonth'])
test = pd.read_csv(path + 'evaluation_public.csv')
# 按照不同的城市和model分批预测
resultDF = []
use_adcode_and_model = False
if use_adcode_and_model:
for adcode in tqdm(test.adcode.drop_duplicates()):
for model in test.model.drop_duplicates():
try:
# 对数据求log 降低两个数据之间的差异性
y_val = np.log(
1 + train[(train['adcode'] == adcode) & (train['model'] == model)][
'salesVolume'])
print(len(y_val))
arima_model = auto_arima(y_val, start_p=1, max_p=9, start_q=1, max_q=9, max_d=5,
start_P=1, max_P=9, start_Q=1, max_Q=9, max_D=5,
m=1, random_state=2018,
trace=False,
seasonal=True,
error_action='ignore',
suppress_warnings=True)
print('finish ..........')
preds = arima_model.predict(n_periods=4)
preds = pd.Series(np.exp(preds) - 1)
# 将结果保存的 resultDF
for k in range(1, 5):
tmpDF = {}
tmpDF['adcode'] = adcode
tmpDF['model'] = model
tmpDF['regMonth'] = k
tmpDF['salesVolume'] = preds[k - 1]
print(tmpDF)
resultDF.append(tmpDF)
except:
pass
# 保存结果
rest = pd.DataFrame(resultDF)
result = pd.merge(test[['id', 'adcode', 'model', 'regYear', 'regMonth']], rest, on=['adcode', 'model', 'regMonth'],
how='left')
result['forecastVolum'] = result['salesVolume'].apply(lambda x: 0 if x < 0 else int(round(x)))
result[['id', 'forecastVolum']].to_csv('./test.csv', index=False)
else:
for model in test.model.drop_duplicates():
try:
# 对数据求log 降低两个数据之间的差异性
y_val = np.log(1 + train[(train['model'] == model)]['salesVolume'])
print(len(y_val))
arima_model = auto_arima(y_val, start_p=1, max_p=9, start_q=1, max_q=9, max_d=5,
start_P=1, max_P=9, start_Q=1, max_Q=9, max_D=5,
m=1, random_state=2018,
trace=False,
seasonal=True,
error_action='ignore',
suppress_warnings=True)
print('finish ..........')
preds = arima_model.predict(n_periods=4)
preds = pd.Series(np.exp(preds) - 1)
# 将结果保存的 resultDF
for k in range(1, 5):
tmpDF = {}
tmpDF['model'] = model
tmpDF['regMonth'] = k
tmpDF['salesVolume'] = preds[k - 1]
print(tmpDF)
resultDF.append(tmpDF)
except:
pass
# 保存结果
rest = pd.DataFrame(resultDF)
result = pd.merge(test[['id', 'model', 'regYear', 'regMonth']], rest, on=['model', 'regMonth'],
how='left')
result['forecastVolum'] = result['salesVolume'].apply(lambda x: 0 if x < 0 else int(round(x)))
result[['id', 'forecastVolum']].to_csv('./test.csv', index=False)