R語言自學日記(10) - 時間序列預測方法

Edward Tung
R 語言自學系列
8 min readJul 29, 2018
Photo by Chris Ried on Unsplash

前言

**題外話:有人建議我縮圖弄好看一點點擊率會更高,決定從善如流,於是今後開始圖文不符:))))

上一章我們介紹了迴歸模型,但實際上該模型卻與時間序列資料的關聯性不大,簡而言之並非為了時間資料所精心設計的模型,因此回到時間序列資料上,我們今天會介紹以下幾種模型:

指數平滑法(Exponential Smoothing)

與後續會介紹到的自迴歸模型相似的一個觀念是,它們都認為對於時間序列資料而言,過去的資料會在一定程度上影響到近期的未來,因此在模型的建立上,會將很大比重放在最近的資料上。

另外一個概念是平滑值,在先前我們介紹過的移動平均法(Moving Average)上我們知道,移動平均是拿近幾期的資料取平均值,這個近幾期可以任意選擇,比方說取落後60期資料,就是MA60,如果取全部資料,當然就是全期平均。而平滑值的概念實際上就是將全期平均與移動平均綜合起來,我們將所有資料作為平均值考慮,並對於近期的資料放更大的權重,因此,指數平滑法的公式如下:

簡單來說,第t期的平滑值St會是上一期平滑值與當期資料的加權平均,其中的 α值越大,就越偏重當期資料而忽略上期平滑值,這樣的公式我們稱做一期指數平滑值,我們可以自由推廣到二期、三期與多期指數平滑等。這樣的方法被非常廣泛地運用,比方說在Microsoft Excel中,就可以直接使用內建的方法去做指數平滑預測。

在R語言中要實現這樣的預測自然也非常容易,這一次我們拿出台灣加權指數(TAIEX)資料來做預測,而方法我們使用三次指數平滑法(也稱Holt-Winters方法),其代碼如下,並把參數解釋附在下方:

我們將資料做差分定態以符合指數平滑法的前提假設,之後我們可以再透過積分還原。從上圖我們看到,以藍色線為核心,我們會得到一個上下區間,這就是指數平滑法認為可能未來資料會出現的上下範圍,對於定態資料,指數平滑法得到的結果相當不錯,當然,這樣的方法會有一些限制,首先是因為考慮了全期均值,指數平滑法通常需要比較完整的歷史資料才可能有好的表現,另外,對於季節性過於明顯的資料,STL分解後再分別預測的效果會好的許多,最後就是,因為該方法對於定態的要求很大,也就是對於變異數可能隨時間變動,或是出現隨機趨勢的資料預測能力較差,在現實世界中往往就只能預測短期變化,對於長期變化的預測能力比較弱一些。

季節性預測 — Naive Method

還記得我們在第八章的時候學會了如何利用STL分解去抽取出時間序列的趨勢資料與季節資料,然而,我們要怎麼針對該筆資料做出正確的預估呢?這裡我們可以使用Naive方法來嘗試,首先,我們試圖將台積電的股價做STL分解,並得到其季節性資料來做預測:

如上,由圖表可以看到大致的變化,季節性出現得非常漂亮。接著,我們要來使用Naive Method來預測季節資料,但首先我們先講一講Naive Method是在做些甚麼:

這方法的假設前提是,下一期的需求/價格/銷量...跟這一期是一樣的,簡單來說,如果今天台積電股價是240元,我們可以猜測明天的股價也會是240元,這是一個非常非常Naive的預設,事實情況顯然會複雜的多,但這在預測上是非常Cost-Effective的,在這裡我們就用Naive方法並加上Random Walk 來試試看:

我們用代碼來預測365期後的資料看看:

我們可以看到分別的變化,上圖是以原始股價資料做Naive預測,而下圖是僅抽取出季節性資料來做預測,兩張圖的差異告訴我們一個重要的訊息是,Naive預測因為其前提假設的原因,在變動不大的穩定資料上會有很好的預測能力,但對於變動量大的資料,比方說第一張圖包含了趨勢,就很難以準確預測,因此在使用時必須特別注意。

趨勢性預測 —Simple Moving Average

我們在第六篇練習繪圖的章節就講過移動平均的概念,而該方法非常適合拿來預測趨勢性資料,這是因為它背後一個很直覺的概念:趨勢其實就是近期資料的變化幅度,因此,我們可以用MA的方法來實作,先看一下MA的圖是長怎樣的,避免資料過大,我們只擷取一段顯示:

接著,我們透過20期的簡單移動平均去預測120期的資料,我們這邊創建一個holdout值=120,透過拿掉最後120期的資料去比較真實資料與預測情況的差距,代碼如下:

紫色的Fitted Values就是用20天移動平均去配適的結果,紅色的直線是我們開始預測的起始點,可以看到程式給出了預測區間,在95%的常態分布信賴區間下,價格的變動會落在以藍色為平均數,灰色的上下兩個標準差之內的範圍中,當然你可以縮小預測期間讓預測準確度更高一些。

當然最後你可以拿季節性預測去結合這裡的趨勢預測,加上Random Walk之後就會變成最後的價格預測段,以下我們再來看一個新的模型:

Combine Altogether : Linear Regression with TS Components

我們在上一章談到了線性迴歸,然而,對於一筆時間資料來說,能夠有的相關性資料基本上只有他自己,舉例來說,對於股票的每日價格波動,我們應該要拿什麼樣的資料來做線性迴歸預測才是合適的呢?

還記得我們一直在談的季節性與趨勢性問題,如果將這兩者拆解出來實際上會得到兩筆資料集,這時候我們就可以用這兩個資料去對價格做線性迴歸,簡單來說,我們的公式會長成這樣:

接下來我們來實際演示一下,這邊我們使用台積電的股價資料來創建時間序列資料,為了演示方便,我們在ts()函數下將頻率設定為12,也就是每一單位時間下觀察12筆資料,並讓資料變成月資料,從2217筆縮減到107筆(要扣掉沒開盤的時間),我們看一下資料分布:

首先,我們在一般的線性迴歸資料中放入趨勢性資料去預測看看價格的變化,這邊使用的是tslm(),這個函數會自動幫你創建seansonal與trend的資料,使用的方法是從ts_data裡面的frequency預設的期間數,因此在這邊我們的資料就會被拆成12期,邊代碼比較複雜一點,但整體上就是去透過lubridate包將日期的年,月,周去分開,並且黏貼到原有的DataFrame之中,再重新創建ts_data,這邊我們將日資料變成月資料看看,每個月價格就是當月價格的平均:

右下角為Temps_month資料

資料大概如上,mutate()函數可以將計算過後的資料補進去,基本上tsmc$MonthYear = … 跟 tsmc <- mutate(tsmc, MonthYear=…)的意思是相同的,接下來我們就拿這筆資料去做tslm:

我們可以看到預測結果,表現得非常好,我們可以給未來的波動範圍一個非常合理的區間,其中,因為我們剛才花時間將資料變成月資料,我們參數設定的h=60就代表著我們要預測未來60/12=5年的資料,這個模型基本上具有0.9以上的R平方。當然,如果按照我們之前所說的變數篩選,完全可以按照檢定的方式只保留趨勢資料即可。

總結

我們文章提到過很多次的R語言中的forecast包,其實同時還支援像是ARIMA、RWDRIFT等方法,這個我們會留到之後介紹,而說完了這麼多,下一篇我們要正式進入時間序列預測的大核心,也就是AR模型,會提到一個很重要的概念就做滯後回歸(Lagged Regression)。如果你喜歡我的文章,還請不吝下方按拍手喔 :)

--

--

Edward Tung
R 語言自學系列

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