R語言自學日記(8) - 處理季節性問題:傅立葉變換與STL分解

Edward Tung
R 語言自學系列
8 min readJul 25, 2018

前言

前面的文章我們提到時間序列資料可能是有季節性的,廣泛一點來說叫做週期性變化,比如我們常說的淡季旺季就是週期性變化,假設今天我們觀察汽車行業的月銷售資料,我們就能夠觀察到很明顯地淡旺季現象,12月1月通常是買車的最佳時機,因為12月常常會有各種促銷活動以因應廠商的銷售年結束,而1月買車比較不會讓汽車這麼快變成第二年度的舊車,下圖是吉利汽車的月銷售量數字,我們可以看到很明顯的淡旺季之分:

吉利汽車月銷售資料

對於這樣的季節性,實際上會給我們的預測造成一些麻煩,舉例來說,如果我們建立了一個不考慮季節性的自迴歸模型,對於前一兩期的資料有高度相關性,可能在旺季的末端會高估了下一時間段的預測資料,因此對於季節性資料,我們會提出兩個疑惑:怎麼樣檢驗季節性是否存在?以及,如何消除季節性對資料的影響?

檢驗季節性行為:傅立葉變換(Fourier Transform)

傅立葉變換是非常偉大的數學突破,本身意義在將時間資料轉換為頻率資料,而應用在時間資料科學時,我們就可以根據頻率輸出的變化去檢視季節性或是週期性,在開始解釋傅立葉變換以前,我們先用R語言實作看看,首先,我們為了避免範疇問題,將剛才的銷售資料轉換成成長率:

吉利汽車月銷售成長率(Period: 2007/1~2018/6)

我們想要知道吉利汽車的週期出現在甚麼時候,但這樣的圖表實在難以準確預估,因此,我們在這裡引入快速傅立葉變換(Fast Fourier Transform,FFT)並把我們的圖表轉換成頻譜圖,使用TSA套件:

我們可以看到有五個比較明顯的高峰,這張圖的橫軸代表的實際上是頻率,也代表了我們實際上可以從其倒數去推得週期,因此,我們將最大的五個輸出值排序,並針對每個輸出值作倒數:

以上,我們可以看到每兩到三個月會出現連續三波大的趨勢,接下來則是每六個月每十二個月都會出現次要趨勢,而我們會認為這非常合理因為符合一般財報年份每三個月設定成一個季度的意義,並且每半年、每年都有固定的週期變化,因此我們可以說吉利汽車的月銷售量會有季度趨勢、半年趨勢以及年趨勢的周期性變化。

而傅立葉變換到底是怎麼運行的,由於背後的數學原理太過複雜,必須要求使用者對微積分、傅立葉級數與線性代數有一定的了解,我們僅在這邊附上參考連結,就不再一併說明,而值得一提的是,我們取樣的資料大多是離散型資料(除非今天要做的是股票的日內交易價格變化),因此這裡的傅立葉變換是離散型的,如果是連續型傅立葉變換,則需要經過一定的轉換才行,以下附上相關的參考資料:

處理季節性行為:STL分解(STL Decomposition)

知道如何檢驗週期性行為之後,接著我們要著手進行一些處理,這裡我們使用的概念叫做STL Decompostion,中文叫做基於Loess函數的季節-趨勢分解方法,這個方法的核心概念在於,我們認為某時刻的分量Y可以被分解成:

其中提到的LOESS叫做局部迴歸,迴歸的平滑值是由二次權重最小平方迴歸,簡單來說就是對局部資料作一次迴歸擬和,但針對選定的x資料其附近的資料點作權重加乘處理之後再放入迴歸方程之中,詳情可一併參考下方連結:

此時,針對這個方程式我們會建立兩個循環(Loop),可以想像成兩個for迴圈,針對內部的迴圈,我們有以下步驟,內部的每個算法比較複雜比如剛才提到的LOESS,我不會一一敘述,但把參考連結附在下方:

  1. 先消除掉T的趨勢成分(Y-T),假定初始(t=0)的時候T=0
  2. 引入LOESS對每一個子序列作回歸並向前向後各一個週期延展,這個組成的平滑曲線我們稱作週期序列
  3. 對剛才得到的週期序列作移動平均並再作一次LOESS回歸,像當於提取該序列的低通量,並且把剛才得到的序列減去其低通量,得到去除平滑趨勢以後的週期序列
  4. 減去週期序列以後,就得到趨勢序列,並且重新繞回外部第二個迴圈

此時外部的迴圈會多出一個懲罰項,如果數據序列的殘餘項過大,下一次循環時LOESS抓取附近變數的權重必須乘上這個懲罰項來減少離群值的影響

詳細的參數,可以參考:

接下來我們要將理論付諸實踐,也可以讓我們一窺上面循環的組成方式,這邊我們透過decompose()函數來實現拆解,並接著使用stl()函數,為了方便觀測,我們取樣2015年1月到2017年12月共三年間的資料:

我們可以很明顯看出端倪,最上方的觀測資料可以被分解為趨勢(Trend)、週期性(Seasonal)以及剩餘項(Remainder),並且使用stl()函數去得到具體的資料資訊,我們分別將它儲存成seasonal與trend資料。

這樣做的好處是,我們可以分別將趨勢資料與季節資料用以做預測,以得到更準確的預測結果,或是單純對於季節成長率做出預測,比如我們可能認為汽車產業的季節成長變動是有一定規律的,市場只會受到大趨勢和隨機誤差的影響,我們就可以對大趨勢作出預估,並準確地補上季節變動值,以作為精準生產量的拿捏,避免過度倉儲或是生產不足等問題。

最後,我們可以分別看一下趨勢資料與季節資料:

Multiplicative Seasonality versus Additive Seasonality

細心的讀者也許注意到,我們在使用decompose函數的時候,指定了一個參數叫做'mult’,其實這個參數是Multiplicative的意思,他代表我們認為週期性是乘法模型,而另外一種週期性實際上是加法模型(Additive)。

乘法模型的意思是季節性會隨著時間逐漸增長,在STL分解上可以寫成 Y = S x T x L。而加法模型的意思是隨著數據增長,季節性模式並不隨之增長,也就是說,我們認為的分解方式屬於 Y = T+S+R,隨著趨勢增長(也就是數據增長),實際上季節性資料的方式是獨立的。一般來說,選擇乘法模型與加法模型得到的結果差異並不會太大,但實際上我們會觀察隨著時間進行的季節性變化,當數據量增大,季節性出現明顯的增長時,我們會偏好乘法模型。

總結

談完季節性問題,接下來我們應該理論上要進入趨勢性問題,但趨勢性中牽涉到的檢驗與性值,必須我們先對於一個非常重要的數值模型,也就是迴歸模型有非常深入的理解之後才好進行,因此,下回我會開始談關於資料的迴歸模型與預測,如果你喜歡我的文章,還請不吝幫我拍手喔!

--

--

Edward Tung
R 語言自學系列

Columbia Student || 2 yrs of data scientist and 1 yr of business consultant experience