1. 程式人生 > >時間序列分析-python(一、自相關係數的意義)

時間序列分析-python(一、自相關係數的意義)

最近在學習時間序列預測銷量,做一些筆記。

參考:

自相關係數

平穩時間序列

時間序列必須是平穩的才可以做後續分析,差分和log都是為了使時間序列平穩。

一個時間序列,如果均值和方差沒有系統變化或週期性變化(均值無變化:沒有明顯趨勢,方差無變化:波動比較穩定),就稱之為平穩的。

自相關係數

平穩序列的自相關係數會快速收斂,從哪一階開始快速收斂(忽然從一個較大的值降到0附近)就說明是哪一階模型,例如自相關函式圖拖尾,偏自相關函式圖截尾,n從2或3開始控制在置信區間之內,因而可判定為AR(2)模型或者AR(3)模型。

從自相關係數原理來講,“n從2或3開始”的含義是指:自相關係數的階數為2階或3階時迅速降為0附近,即在剔除了中間的2或3個變數後,序列開始穩定

下面是自相關係數的原理(點選開啟連結):

自相關係數是不變的,是引數,不會衰減至零。xt=rho*xt-1+eslion,其中rho為自相關係數。自迴歸方程本質就是一個差分方程,解這個方程的根就可得到xt隨著t的變化的解,如果根的模大於1,xt就是爆炸或趨於無窮的,不收斂。當自相關係數約等於1,就是單位根,也是不收斂。


我們手算一個自相關係數就明白了:


並動手編成了一個小函式,加深理解

def get_auto_corr(timeSeries,k):
    '''
    Descr:輸入:時間序列timeSeries,滯後階數k
            輸出:時間序列timeSeries的k階自相關係數
        l:序列timeSeries的長度
        timeSeries1,timeSeries2:拆分序列1,拆分序列2
        timeSeries_mean:序列timeSeries的均值
        timeSeries_var:序列timeSeries的每一項減去均值的平方的和
        
    '''
    l = len(timeSeries)
    #取出要計算的兩個陣列
    timeSeries1 = timeSeries[0:l-k]
    timeSeries2 = timeSeries[k:]
    timeSeries_mean = timeSeries.mean()
    timeSeries_var = np.array([i**2 for i in timeSeries-timeSeries_mean]).sum()
    auto_corr = 0
    for i in range(l-k):
        temp = (timeSeries1[i]-timeSeries_mean)*(timeSeries2[i]-timeSeries_mean)/timeSeries_var
        auto_corr = auto_corr + temp  
    return auto_corr

看到最後計算的那部分,如果舉個反例,有一個序列A{1,10,100,1000,10000}和序列B{100,1,1000,10,10000}

序列A和B的方差和均值都是相等的,所以自相關係數的取值關鍵看拆分的兩個序列。但是序列A具有明顯的遞增趨勢,按照前面的理解,序列A不穩定的概率要比B大。

額,結果好像有點出人意料。

我們再編一個函式畫出它們的自相關係數圖看看,結果好像也沒有差別。

def plot_auto_corr(timeSeries,k):
    '''
    Descr:需要計算自相關函式get_auto_corr(timeSeries,k)
            輸入時間序列timeSeries和想繪製的階數k,k不能超過timeSeries的長度
            輸出:k階自相關係數圖,用於判斷平穩性
    '''
    timeSeriestimeSeries = pd.DataFrame(range(k))
    for i in range(1,k+1):
        timeSeriestimeSeries.loc[i-1] =get_auto_corr(timeSeries,i)
    plt.bar(range(1,len(timeSeriestimeSeries)+1),timeSeriestimeSeries[0])


拆分一下序列A和B:

A1:{1,10,100,1000}

A2:{10,100,1000,10000}

B1:  {100,1,1000,10}

B2: {1,1000,10,10000}

感覺自相關係數圖不按照設想的反例的原因是分子沒有加絕對值,有些項減去均值後為正,有些項減去均值後為負,抵消了。

所以為什麼自相關係數迅速收斂可以判斷序列平穩呢,序列平穩是沒有趨勢性的,而上面反例中A比B的趨勢性要明顯。

自相關係數應該描述的不是趨勢性,而是序列1和序列2的相關性,顯然如果序列1和序列2完全相同,自相關係數為0,以序列C為例{1,1,1,1,1},顯然不管多少階的自相關係數都為0

序列D{1,1,1,1,2},自相關係數的值會比較小,而且如果有序列E{2,1,1,1,1},我們可以發現D和E的自相關係數圖是一樣的!如果有F{1,1,2,1,1},把2放在中間才會有改變,那麼再有G{2,2,3,2,2},會發現F和G的自相關係數圖又會保持一致,A{2,2,2,2,3}會和序列D、E的自相關係數圖一致。




從前面可以看出,自相關係數在{1,1,1,1,1}的時候最小為0,在序列{1,2,3,4,5}的時候會比較大。所以自相關係數到底有沒有一個具體的確切含義呢?

第2個例子,這3個序列的自相關係數是近似的,不完全相等,例如A的一階相關係數大概是0.2999999999,B是3.00000000004

A=np.array([1,1,2,1,1])
B=np.array([100,100,200,100,100])
C=np.array([100,100,101,100,100])

plot_auto_corr(A,4)
Out[10]: 
      0
0 -0.30
1 -0.35
2  0.10
3  0.05
plot_auto_corr(B,4)
Out[11]: 
      0
0 -0.30
1 -0.35
2  0.10
3  0.05
plot_auto_corr(C,4)
Out[12]: 
      0
0 -0.30
1 -0.35
2  0.10
3  0.05

目前得出來的結論就是自相關係數可以用來衡量序列的值的差異性,但是為什麼隨著自相關係數的階數增加,自相關係數迅速下降到0附近的序列就是穩定時間序列的證明。需要查閱專業書籍。

(補充“https://uqer.io/community/share/5790a091228e5b90cda2e2ea”,這個連結裡面說得很清楚了,解決了許多自相關係數的疑問)先到這裡,去看arch包吧。

根據自相關係數圖判斷使用模型

完整程式:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt  
timeSeries = np.array([2,3,4,3,7])
k = 1 
timeSeries1 = np.array([1,10,100,1000,10000])
timeSeries2 = np.array([100,1,1000,10,10000])
def get_auto_corr(timeSeries,k):
    '''
    Descr:輸入:時間序列timeSeries,滯後階數k
            輸出:時間序列timeSeries的k階自相關係數
        l:序列timeSeries的長度
        timeSeries1,timeSeries2:拆分序列1,拆分序列2
        timeSeries_mean:序列timeSeries的均值
        timeSeries_var:序列timeSeries的每一項減去均值的平方的和
        
    '''
    l = len(timeSeries)
    #取出要計算的兩個陣列
    timeSeries1 = timeSeries[0:l-k]
    timeSeries2 = timeSeries[k:]
    timeSeries_mean = timeSeries.mean()
    timeSeries_var = np.array([i**2 for i in timeSeries-timeSeries_mean]).sum()
    auto_corr = 0
    for i in range(l-k):
        temp = (timeSeries1[i]-timeSeries_mean)*(timeSeries2[i]-timeSeries_mean)/timeSeries_var
        auto_corr = auto_corr + temp  
    return auto_corr

#畫出各階自相關係數的圖
k=4
def plot_auto_corr(timeSeries,k):
    '''
    Descr:需要計算自相關函式get_auto_corr(timeSeries,k)
            輸入時間序列timeSeries和想繪製的階數k,k不能超過timeSeries的長度
            輸出:k階自相關係數圖,用於判斷平穩性
    '''
    timeSeriestimeSeries = pd.DataFrame(range(k))
    for i in range(1,k+1):
        timeSeriestimeSeries.loc[i-1] =get_auto_corr(timeSeries,i)
    plt.bar(range(1,len(timeSeriestimeSeries)+1),timeSeriestimeSeries[0])
    return timeSeriestimeSeries