天天看點

常見時序預測模型的R實作 三

常見時序預測模型的R實作 三

ETS模型

接下來說說ETS模型,在R的forecast庫中有實作。

> library(fpp2)
Loading required package: forecast
Loading required package: fma
Loading required package: expsmooth
Loading required package: ggplot2
           

作者Rob Hyndman是個H-index 54,citation過兩萬的大牛。他故意用這三個字母來使這個模型的名字能顧名思義(reminiscent),既可以了解為Error, Trend and Seasonality,又可以解作ExponenTial Smoothing模型。前者揭示了模型的三個組成部分,後者則描述了模型的工作原理。準确的說,ETS實際上是一整個系列的算法,可以基于這三個組成部分任意組合,而Hyndman寫的forecast庫中可以用ets()方法自動選擇三個component的組合。

之是以要從這個模型寫起,是因為這個模型既足夠強大,又足夠簡明。它可以預測以下幾種時間序列:

  • 無趨勢(trend),無季節性(seasonality) 比如我上個月跑了十次5公裡,根據這十次時間估計我接下來一次要跑多久
  • 有趨勢,無季節性 比如我剛開始學打字,一開始打1000個詞要4個小時,以後随着熟練程度遞減,預測下一次時間
  • 有趨勢,有季節性 比如零售業的銷售資料,趨勢展現的可能是整個行業的冷暖,季節性則跟氣溫、假日有關
  • 無趨勢,有季節性 比如近十年某地氣溫的變化,十年這樣的短周期裡也許展現不出大的趨勢變化,但季節性是顯著的

不僅如此,由于它的error component既可以是additive的又可以是multiplicative的,它還能預測有季節性且在每個周期内幅度有變化的序列。比如電力供應,由于用的起空調之類制冷裝置的家庭變多了,季節性的振幅可能是逐漸遞增的。

最簡單的ETS

最簡單的ETS是ses模型,即simple exponential smoothing。這個模型隻能解決沒趨勢也沒季節性的時序。它的公式如下:

常見時序預測模型的R實作 三

公式是從Hyndman的書上抄來的。這個公式的設計基于怎樣的考慮呢?Hyndman是這麼說的。設想兩個極端情況,一個情況是永遠隻采用當下的值來預測下一個值。假設資料完全沒有任何規律,這也不失為一個方案吧。另一個情況是,對所有觀測到的點作平均,這樣預測值其實是樣本集的均值。起碼這樣搞能讓訓練集上的方差小,而且用到所有點了,但不能反映出很多序列裡recency很重要的特點。近期的觀測值的确往往比遠古觀測值更有意義。然後ses就出現了:hey,我就是折中方案。我給近期的觀測值更高的權重,但也用到所有過去的點。如果alpha值為1,則相當于把除當下值Yt以外的所有點權重都賦為0了。假如alpha為0.5,那權重就是個标準的底為0.5的指數函數。而無論alpha是多少,權重decay的速度都是由(1-alpha)的指數函數決定的,是以叫exponential smoothing。讓alpha充分的接近0的話,各個點位的權重就會更平均,衰減速度更慢。

雖然應用場景有限,ses的确是個很精緻的方案。非常不幸的是,它完全木有辦法對趨勢模組化。看個例子

> x_st = ts(1:10,start=c(1,1),frequency=5)
> autoplot(x_st)
           
常見時序預測模型的R實作 三

上ses會發生什麼呢?ses可以用h參數指定預測多少個時間點,用alpha指定公式中的權重參數。我們先看一下alpha=1的情況,也即使用前一個值預測下一個值。注意由于alpha值域在0和1之間,這裡用了0.9999作為近似

> autoplot(ses(x_st,h=4,alpha=0.9999))
           
常見時序預測模型的R實作 三

如所預料,它取了最近的值,10,作為接下來4個點的預測值。再換alpha=0.5試試

> autoplot(ses(x_st,h=4,alpha=0.5))
           
常見時序預測模型的R實作 三

當alpha充分接近0時,預測值逼近觀測值均值。這一點在公式中看不出來,但應該跟y0有關。具體可以看源碼,這裡不深入。

總結一下,ses對未來的預測來自對過去觀測值賦予不同權重的求和,權重衰減函數是個指數函數,展現的其實是觀測值的分布特性。它的預測曲線是個常數,與X軸平行,無法反映出曆史資料中的趨勢。

關于趨勢 Trend

不能處理趨勢,這可用性就相當不靠譜了。為了解決這個問題,有個叫Holt Winter的人給ses的模型加了一個component,

常見時序預測模型的R實作 三

公式依然抄自Hyndman的書。這裡公式已經略有些複雜,可以在紙上自己展開,但不太友善打字了。這裡了解的關鍵在于,alpha依然是用于确定觀測值衰減速度的參數,但對于過去的點還考慮了每個點處的趨勢量。趨勢量本身也是采用了權重來估計的,并不僅采用過去一個點到目前點的變化趨勢,而是把之前每個點的趨勢都用一個指數衰減函數引入。這樣的設計可以使曲線平滑。看一下案例,還是用之前的資料例子

autoplot(hw(x_st,h=4))
           
常見時序預測模型的R實作 三

可見這個線形趨勢被很好地capture了。換個資料集

> x_st = ts((1:10)^2,start=c(1,1),frequency=5)
> autoplot(hw(x_st,h=4))
           
常見時序預測模型的R實作 三

顯然,非線性趨勢也可以被capture到,隻是由于未指定alpha值,自動選擇的alpha顯然考慮了比最近一個值更多的點,故而第一個預測值小于最後一個觀測到的值,這和人類的直覺不符。我們可以通過調整hw()方法的參數來解決這個問題。

關于季節 Seasonality

解決了trend,是否就完滿了呢?顯然不是這樣。再來一個資料集

> x = ts(rep((-2:2)^2,4),start=c(1,1),frequency = 5)
> autoplot(x)
           
常見時序預測模型的R實作 三

認為制造了一個周期為5的seasonal的資料集。上holt-winter算法試試看:

常見時序預測模型的R實作 三

第一眼會覺得很奇怪,我們并沒有給出seasonal component啊,為什麼這個模型會成功重構曆史資料的模式?注意到Holt-Winters' additive method了麼?原來forecast這個庫裡實作的是改進後的holt-winters方法,這個版本有一個seasonality的component,而且整出倆版本:

常見時序預測模型的R實作 三

常見時序預測模型的R實作 三

公式依然是從Hyndman祖師爺那裡抄來的。第一個是multiplicative版本,第二個是additive版本。前者能更好的解決振幅動蕩迅速變大的時序資料。

看到這裡,ets的故事基本講完了。漏過了一個次元:dampened trend,但這個component也是ets方法能夠自動估計是否需要的,大緻含義就是允許趨勢逐漸減弱回歸到水準。

總結

用祖師爺Hyndman的表格做個總結

常見時序預測模型的R實作 三

實際應用中我們隻需要ets()基本就夠了

> fit = ets(x)
> checkresiduals(fit)
           

由于是用完美的數學函數生成的資料集,可以看到罕見的0殘值:

常見時序預測模型的R實作 三

注意圖中提到的ETS(A,N,A),對應上表可以搞清楚這個自動估計的ETS模型用了哪些components。第一個A是error,說明用的是additive error,第二個N表示沒有trend,第三個A表示有additive seasonality。這完美比對我們之前手動用hw()得到的預測模型。

局限與不足

在應用中,我發覺ETS起碼有兩個不足。第一,對周期長的序列,由于要估計的參數極多,會無法handle或異常慢。第二,無法友善的嵌入external variables。這些在下一篇讨論ARIMA時再進一步讨論。

上一篇 常用時序預測模型之準備知識    下一篇 常用時序預測模型之ARIMA

繼續閱讀