1. 程式人生 > >時間序列的分析和預測ARIMA

時間序列的分析和預測ARIMA

  分析的資料來自一個kaggle的比賽資料,是一組維基百科頁面的瀏覽量資料,對資料進行簡單的分析和處理,預測未來的流量.資料包含部分網頁從2015年7月1日到2016年12月31日的每天的瀏覽量資料,資料有存在缺失,網頁的型別包含多個語種.
下面是資料的部分截圖:
這裡寫圖片描述
Page為網頁的地址,列標籤為日期,值為每日的瀏覽量.

下面倒入用到的python庫和類

import numpy as np 
import pandas as pd 
import re 
import matplotlib.pyplot as plt 
from statsmodels.tsa.arima_model import
ARIMA

讀取資料

train_df = pd.read_csv('webLL/train_1.csv').fillna(0) # 用0來補充缺失值

轉換資料型別,釋放記憶體空間

# 資料為浮點數型別的整數,消耗記憶體較大,轉換為整型資料釋放一些記憶體600M減少到300M
for col in train_df.columns[1:]:
    train_df[col] = pd.to_numeric(train_df[col],downcast='integer')

正則表達提取網頁的語種資訊

# 正則表達匹配的物件是一個不可迭代的物件,可以通過group()轉換為一個字串物件
def get_language(page): res = re.search('[a-z][a-z].wikipedia.org',page) if res: return res.group()[:2] return 'na'

新增語言列

train_df['lang'] = train_df['Page'].map(get_language)

  用一個字典物件來儲存,不同語言的網頁的流量資料,key為語言標記,value為對應的dataFarame物件

lang_sets = {}
lang_sets['en'] = train_df[train_df.lang=='en'
].iloc[:,0:-1] lang_sets['ja'] = train_df[train_df.lang=='ja'].iloc[:,0:-1] lang_sets['de'] = train_df[train_df.lang=='de'].iloc[:,0:-1] lang_sets['na'] = train_df[train_df.lang=='na'].iloc[:,0:-1] lang_sets['fr'] = train_df[train_df.lang=='fr'].iloc[:,0:-1] lang_sets['zh'] = train_df[train_df.lang=='zh'].iloc[:,0:-1] lang_sets['ru'] = train_df[train_df.lang=='ru'].iloc[:,0:-1] lang_sets['es'] = train_df[train_df.lang=='es'].iloc[:,0:-1]

 
計算每種語言wiki頁面的日平均流量

sums = {}
for key in lang_sets:
    sums[key] = lang_sets[key].iloc[:,1:].sum(axis=0) / lang_sets[key].shape[0]
# 字典轉換為DataFrame物件繪圖方便,Nan表示在網頁的地址中沒有明確表示文字格式
traffic_sum = pd.DataFrame(sums) 

更新列名

traffic_sum.columns=['German','English','Spanish','French','Japanese','Nan','Russian','Chinese'] 
traffic_sum.plot(figsize=(12,6))
plt.show()

每種語言wiki頁面15/7/1-16/12/31的日平均瀏覽量
png這裡寫圖片描述

  下面利用上面的資料繪製不用wiki頁面瀏覽資料的自相關和部分自相關圖,以估計用於訓練ARIMA模型的超引數。

from statsmodels.tsa.stattools import pacf
from statsmodels.tsa.stattools import acf

for key in sums:
    fig = plt.figure(1,figsize=[12,4])
    ax1 = fig.add_subplot(121)
    ax2 = fig.add_subplot(122)
    data = np.array(sums[key])
    autocorr = acf(data)
    pac = pacf(data)

    x = [x for x in range(len(pac))]
    ax1.plot(x[1:],autocorr[1:])
    ax1.grid(True)
    ax1.set_xlabel('Lag')
    ax1.set_ylabel('Autocorrelation')

    ax2.plot(x[1:],pac[1:])
    ax2.grid(True)
    ax2.set_xlabel('Lag')
    ax2.set_ylabel('Partial Autocorrelation')
    print(key)
    plt.show()
俄語

這裡寫圖片描述

日語

這裡寫圖片描述

法語

這裡寫圖片描述

德語

這裡寫圖片描述

英語

這裡寫圖片描述

漢語

這裡寫圖片描述

na

這裡寫圖片描述

西班牙

這裡寫圖片描述

觀察上面的圖表

  1. 英語,俄語,法語,Nan語種頁面的瀏覽量的自相關係數都有較快的收斂,序列比較平穩,所以不需要在進行處理.其他的時間序列有明顯的週期性趨勢,並沒有較好的收斂,需要對序列進行處理,這裡通過一階差分來是序列趨於平穩.
  2. 對於日語,漢語,德語和西班牙語他們的流量資料下的自相關係數沒7天左右會出現一個高峰,階數P取7,其他的取3/4都ok,特別在意的話可以查詢更多關於ARIMA模型定階的資料.
  3. 平穩序列的部分相關係數都有較快的收斂,所以q=0,非平穩序列的收斂情況不一,為了方便計算,統一q=1.總之定階的問題,我也比較頭疼,還在摸索.

下面對不同語言的序列用ARIMA模型進行預測未來的流量

params = {'en': [4,1,0], 'ja': [7,1,1], 'de': [7,1,1], 'na': [4,1,0], 
          'fr': [4,1,0], 'zh': [7,1,1], 'ru': [4,1,0], 'es': [7,1,1]}

for key in sums:
    data = np.array(sums[key])
    result = None
    arima = ARIMA(data,params[key])
    result = arima.fit(disp=False)
    #print(result.params)
    pred = result.predict(2,599,typ='levels')
    x = pd.date_range('2015-07-02','2017-02-18')


    print(key)
    plt.figure(figsize=(10,5))
    plt.plot(x[:548],data[2:] ,label='Data')
    plt.plot(x,pred,label='ARIMA Model')
    plt.xlabel('Days')
    plt.ylabel('Views')
    plt.legend()
    plt.show()

俄語

這裡寫圖片描述

日語

這裡寫圖片描述

法語


這裡寫圖片描述

德語

這裡寫圖片描述

英語

這裡寫圖片描述

漢語

這裡寫圖片描述

na

這裡寫圖片描述

西班牙

這裡寫圖片描述