CCF乘用車細分市場銷量預測之ARIMA模型

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   : [email protected]
# @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)

 

發佈了99 篇原創文章 · 獲贊 75 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章