CCF乘用车细分市场销量预测之ARIMA模型

2020-04-15 17:18:41 浏览数 (2)

微信公众号: AI那点小事 作者:YYLin CSDN:https://blog.csdn.net/qq_41776781 如果你觉得有帮助,欢迎点赞[1]

1:什么是ARIMA模型

介绍ARIMA之前,我们首先介绍一下时间序列模型和一般建模的区别。想象一下我们预测某个人贷款是否会违约,我们已知的特征中包含用户贷款时间以及用户的个人信息。虽然数据中保存时间信息,但是显然此类问题不是一个时序问题。在想象一下我们预测某种车型在某省接来四个月的销量,根据我们的常识判断,前几个月的销量如果一直很高的话,那么接下来几个月的销量有很大可能较高,反之亦然,也即是说我们要预测的值可能会受到历史数据的影响,显然此时一个时序问题。简而言之,判断的标准就是预测变量和之前的预测值之间是否彼此独立还是存在一定关系。

ARIMA模型的全称叫做自回归移动平均模型,全称是(ARIMA, Autoregressive Integrated Moving Average Model)是一种常见的时间序列预测的模型。ARIMA模型描述当前值与历史值之间的关系,用变量自身的历史时间数据对自身进行预测,自回归模型必须满足平稳性的要求。

2:ARIMA模型中的相关参数及概念

2.1 平稳性

平稳性要求样本时间序列所得到的拟合曲线在未来一段时间内仍能顺着现有的形态地延续下去。平稳性要求序列的均值和方差不发生明显变化。

2.2 严平稳

严平稳数据的分布不随时间的改变而改变。如白噪声(正太),无论怎么取,都是期望为0,方差为1。

2.3 移动平均法和加权移动平均法

移动平均法是指将前N个值的平均值作为预测值。加权移动平均法是指将前N个值被赋予不同的权重,将加权之后的结果作为预测值。

2.4 差分

将当前行减去上一行的数据作为当前行的值

2.5 相关参数

ARIMA(p,d,q)模型中主要的三个参数是p,d,q,具体说明可见我的下篇博客。 p是自回归(AR)的项数,表示用前p的历史值作为自变量预测当前值 d是差分(I)的系数,其表示差分操作是指后一行减前一行,目的是为了使时间序列变的平稳 q是移动平均(MA)的项数,意思每一行被自身和自身之前的q-1行的平均数取代

3:ARIMA模型实现

本次CCF乘用车销量预估我们团队数海拾贝的成员有东南大学的AI蜗牛车,贝壳er和京东算法工程师zhangqibot。最后取得了初赛第六,复赛A榜第五,B榜15的成绩。因为本次比赛并不适合使用ARIMA模型,所以在该比赛中并没有花时间在ARIMA模型上。下面的代码是比赛群中分享的一个baseline,我这边讲述一下他建模的过程和思想。如果有啥侵权一类的给我说一声,我会加上引用的。

okay开始讲解。CCF乘用车细分市场销量预测要求我们预测某个地区某种车型接下来四个月车辆的销售情况。如果我们直接将数据集中的销量作为标签,然后使用ARIMA模型进行建模其会忽略地区和车型这两个特征。一个简单的做法训练数据是某个省某种车型,预测的也是同一个省同样的车型。但是这样的话训练数据为某个省某种车型的2016/01到2017/12总共24个销售数据,显然这种操作的话数据量会很少,效果不一定好。

4:代码的解释

ARIMA模型需要指定三个参数p,d,q。d差分系数非常容易设置,我们从一阶差分开始逐渐向上增加,保证最后预测数据的波动不大即可。但是p和q的指定就较为麻烦。所以源码之中使用了auto_arima这个工具,只需要我们输入p,d,q的范围即可自动求的最优解。

如果测试集中某种车型和省份的组合(例如奥迪车和北京市)出现在训练数据之中,则将其销售量提取出来作为ARIMA模型的训练数据。最后将其训练数据放到auto_arima()之中设置好对应的参数开始训练,最后预测窗口设置是4表示预测接下来四个月的销量。

代码语言:javascript复制
# @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)

0 人点赞