常見時序預測模型的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。這個模型只能解決沒趨勢也沒季節性的時序。它的公式如下:


公式是從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)

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

> autoplot(ses(x_st,h=4,alpha=0.9999))

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

> autoplot(ses(x_st,h=4,alpha=0.5))

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

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

關於趨勢 Trend

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


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

autoplot(hw(x_st,h=4))

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

> x_st = ts((1:10)^2,start=c(1,1),frequency=5)
> autoplot(hw(x_st,h=4))

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

關於季節 Seasonality

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

> x = ts(rep((-2:2)^2,4),start=c(1,1),frequency = 5)
> autoplot(x)

認爲製造了一個週期爲5的seasonal的數據集。上holt-winter算法試試看:


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



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

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

總結

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


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

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

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


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

侷限與不足

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章