2  Holt Winters exponencálne vyrovnávanie

Údaje môžete načítať do R pomocou funkcie read.csv(), ktorá predpokladá, že vaše údaje sú po sebe idúce časové body v jednoduchom textovom súbore s jedným stĺpcom. Keď načítate údaje časových radov do R, ďalším krokom je uloženie údajov do objektu časových radov v R, aby ste mohli použiť mnohé funkcie R na analýzu údajov časových radov. Na uloženie údajov do objektu časového radu používame funkciu ts() v R. Napríklad na uloženie údajov do premennej ‘bike’ ako objektu časového radu v R napíšeme:

library(tseries)
Registered S3 method overwritten by 'quantmod':
  method            from
  as.zoo.data.frame zoo 
library(TTR)
bike <- read.csv("dayBike.csv", header=TRUE, stringsAsFactors=FALSE)
str(bike)
'data.frame':   731 obs. of  16 variables:
 $ instant   : int  1 2 3 4 5 6 7 8 9 10 ...
 $ dteday    : chr  "2011-01-01" "2011-01-02" "2011-01-03" "2011-01-04" ...
 $ season    : int  1 1 1 1 1 1 1 1 1 1 ...
 $ yr        : int  0 0 0 0 0 0 0 0 0 0 ...
 $ mnth      : int  1 1 1 1 1 1 1 1 1 1 ...
 $ holiday   : int  0 0 0 0 0 0 0 0 0 0 ...
 $ weekday   : int  6 0 1 2 3 4 5 6 0 1 ...
 $ workingday: int  0 0 1 1 1 1 1 0 0 1 ...
 $ weathersit: int  2 2 1 1 1 1 2 2 1 1 ...
 $ temp      : num  0.344 0.363 0.196 0.2 0.227 ...
 $ atemp     : num  0.364 0.354 0.189 0.212 0.229 ...
 $ hum       : num  0.806 0.696 0.437 0.59 0.437 ...
 $ windspeed : num  0.16 0.249 0.248 0.16 0.187 ...
 $ casual    : int  331 131 120 108 82 88 148 68 54 41 ...
 $ registered: int  654 670 1229 1454 1518 1518 1362 891 768 1280 ...
 $ cnt       : int  985 801 1349 1562 1600 1606 1510 959 822 1321 ...
head(bike,n=10)
   instant     dteday season yr mnth holiday weekday workingday weathersit
1        1 2011-01-01      1  0    1       0       6          0          2
2        2 2011-01-02      1  0    1       0       0          0          2
3        3 2011-01-03      1  0    1       0       1          1          1
4        4 2011-01-04      1  0    1       0       2          1          1
5        5 2011-01-05      1  0    1       0       3          1          1
6        6 2011-01-06      1  0    1       0       4          1          1
7        7 2011-01-07      1  0    1       0       5          1          2
8        8 2011-01-08      1  0    1       0       6          0          2
9        9 2011-01-09      1  0    1       0       0          0          1
10      10 2011-01-10      1  0    1       0       1          1          1
       temp    atemp      hum windspeed casual registered  cnt
1  0.344167 0.363625 0.805833 0.1604460    331        654  985
2  0.363478 0.353739 0.696087 0.2485390    131        670  801
3  0.196364 0.189405 0.437273 0.2483090    120       1229 1349
4  0.200000 0.212122 0.590435 0.1602960    108       1454 1562
5  0.226957 0.229270 0.436957 0.1869000     82       1518 1600
6  0.204348 0.233209 0.518261 0.0895652     88       1518 1606
7  0.196522 0.208839 0.498696 0.1687260    148       1362 1510
8  0.165000 0.162254 0.535833 0.2668040     68        891  959
9  0.138333 0.116175 0.434167 0.3619500     54        768  822
10 0.150833 0.150888 0.482917 0.2232670     41       1280 1321
bike$Date  <- as.Date(bike$dteday)
countBike <- ts(bike[, c('cnt')])

Prvá vec, ktorú budete chcieť urobiť pri analýze údajov časových radov, bude načítať ich do R a vykresliť časový rad.

plot.ts(countBike)

2.1 Jednoduché exponenciálne vyrovnávanie

Ak máte časový rad, ktorý možno opísať pomocou aditívneho modelu s konštantnou úrovňou a bez sezónnosti, môžete použiť jednoduché exponenciálne vyhladzovanie na vytváranie krátkodobých predpovedí.

Jednoduchá metóda exponenciálneho vyhladzovania poskytuje spôsob odhadu úrovne v aktuálnom časovom bode. Vyhladzovanie je riadené parametrom alfa; pre odhad úrovne v aktuálnom časovom bode. hodnota alfa; leží medzi 0 a 1. Hodnoty alfa, ktoré sú blízke 0, znamenajú, že pri predpovediach budúcich hodnôt sa prikladá malá váha najnovším pozorovaniam.

Na vytváranie predpovedí pomocou jednoduchého exponenciálneho vyhladzovania v jazyku R môžeme použiť jednoduchý prediktívny model exponenciálneho vyhladzovania pomocou funkcie „HoltWinters()“ v jazyku R. Ak chcete použiť HoltWinters() na jednoduché exponenciálne vyhladzovanie, musíme nastaviť parametre beta=FALSE a gamma=FALSE vo funkcii HoltWinters() (parametre beta a gama sa používajú na Holtovo exponenciálne vyhladzovanie alebo Holt-Wintersovo exponenciálne vyhladzovanie, ako je popísané nižšie). Alfa je “základná hodnota”. Vyššie alfa prikladá väčšiu váhu najnovším pozorovaniam. Beta je “trendová hodnota”. Vyššia beta znamená, že sklon trendu je viac závislý od posledných sklonov trendu. Gama je “sezónna zložka”. Vyššia gama dáva väčšiu váhu najnovším sezónnym cyklom.

Funkcia HoltWinters() vracia premennú zoznamu, ktorá obsahuje niekoľko pomenovaných prvkov.

Napríklad, ak chcete použiť jednoduché exponenciálne vyhladzovanie na vytváranie predpovedí pre časový rad počtu požičaných bicyklov za deň, napíšeme:

countBikeHW <- HoltWinters(countBike, beta=FALSE, gamma=FALSE)

Výstup HoltWinters() nám hovorí, že odhadovaná hodnota parametra alfa je približne 0.28. To je celkom ďalje od nuly, čo nám hovorí, že predpovede sú založené na nedávnych pozorovaniach.

Vo vyššie uvedenom príklade sme uložili výstup funkcie HoltWinters() do premennej zoznamu „countBikeHW“. Prognózy vytvorené HoltWinters() sú uložené v pomenovanom objekte tejto premennej listu pod názvom „fitted“, takže ich hodnoty môžeme získať zadaním:

head(countBikeHW$fitted)
         xhat    level
[1,]  985.000  985.000
[2,]  932.748  932.748
[3,] 1050.954 1050.954
[4,] 1196.080 1196.080
[5,] 1310.785 1310.785
[6,] 1394.619 1394.619

Pôvodný časový rad môžeme vykresliť oproti expoeneciálnemu vyrovnávanémuu radu zadaním:

plot(countBikeHW)
lines(countBike)

countBikeHW$SSE
[1] 680114835

Graf zobrazuje pôvodný časový rad čiernou farbou a prognózy ako červenou čiaru. Časový rad predpovedí je oveľa plynulejší ako časový rad pôvodných údajov.

Ako mieru presnosti prognóz môžeme použiť súčet štvorcov chýb pre chyby prognóz vo vzorke, t. j. chyby prognóz za časové obdobie, ktoré pokrýva náš pôvodný časový rad. Suma štvorcov chýb je uložená v pomenovanom prvku premennej zoznamu “countBikeHW” s názvom “SSE”, takže jej hodnotu môžeme získať zadaním “countBikeHW$SSE”. Súčet štvorcov chýb je dosť vysoký.

2.2 Holt Winters prognózovanie

Pri jednoduchom exponenciálnom vyhladzovaní je bežné použiť prvú hodnotu v časovom rade ako počiatočnú hodnotu pre úroveň. Napríklad v časovom rade pre požičané bicykle je prvá dňová hodnota 985 sledovaného dvojročného obdobia. Počiatočnú hodnotu pre úroveň môžete určiť vo funkcii HoltWinters() pomocou parametra “l.start”. Ak chceme napríklad vytvoriť predpoveď s počiatočnou hodnotou hladiny nastavenou na 985, zadáme:

HoltWinters(countBike, beta=FALSE, gamma=FALSE,l.start=985)
Holt-Winters exponential smoothing without trend and without seasonal component.

Call:
HoltWinters(x = countBike, beta = FALSE, gamma = FALSE, l.start = 985)

Smoothing parameters:
 alpha: 0.2839781
 beta : FALSE
 gamma: FALSE

Coefficients:
      [,1]
a 2121.331

Ako bolo vysvetlené vyššie, v predvolenom nastavení HoltWinters() sa predpovede vytvárajú len pre časové obdobie, ktoré pokrývajú pôvodné údaje, čo je v prípade časového radu pre požičané bicykle obdobie dvoch seldovaných rokov. Predpovede pre ďalšie časové body môžeme vytvoriť pomocou funkcie “forecast.HoltWinters()” v balíku R “forecast”. Ak chceme použiť funkciu forecast.HoltWinters(), musíme si najprv nainštalovať balík R “forecast”.

Pri použití funkcie forecast.HoltWinters() jej ako prvý argument (vstup) odovzdáte predikčný model, ktorý ste už zostavili pomocou funkcie HoltWinters(). Napríklad v prípade časového radu pre požičané bicykle sme predikčný model vytvorený pomocou funkcie HoltWinters() uložili do premennej “countBikeHW”. Pomocou parametra “h” vo funkcii forecast.HoltWinters() určíte, pre koľko ďalších časových bodov chcete vytvoriť prognózy. Napríklad, ak chceme vytvoriť predpoveď požičané bicykle na ďalšie dni (ďalších 7 dní) pomocou funkcie forecast.HoltWinters(), zadáme:

countBikeHWforecast <- forecast:::forecast.HoltWinters(countBikeHW, h=7)
countBikeHWforecast
    Point Forecast    Lo 80    Hi 80      Lo 95    Hi 95
732       2121.331 883.5143 3359.148  228.25360 4014.409
733       2121.331 834.5710 3408.092  153.40116 4089.262
734       2121.331 787.4222 3455.240   81.29333 4161.369
735       2121.331 741.8840 3500.779   11.64867 4231.014
736       2121.331 697.8018 3544.861  -55.76922 4298.432
737       2121.331 655.0443 3587.618 -121.16119 4363.824
738       2121.331 613.4988 3629.164 -184.69959 4427.362
subset(countBike, start=724)
Time Series:
Start = 724 
End = 731 
Frequency = 1 
[1]  920 1013  441 2114 3095 1341 1796 2729
tail(countBikeHW$fitted,n=7)
Time Series:
Start = 725 
End = 731 
Frequency = 1 
        xhat    level
725 2519.953 2519.953
726 2092.011 2092.011
727 1623.160 1623.160
728 1762.548 1762.548
729 2140.935 2140.935
730 1913.771 1913.771
731 1880.327 1880.327

Funkcia forecast.HoltWinters() vám poskytne predpoveď pre daný deň, 80% interval predpovede pre predpoveď a 95% interval predpovede pre predpoveď. Napríklad predpovedané dňové požičanie bicyklov na 732 deň je približne 2121 s 95 % intervalom predpovede (228, 4014).

Na vykreslenie predpovedí vykonaných funkciou forecast.HoltWinters() môžeme použiť funkciu “plot.forecast()”:

forecast:::plot.forecast(countBikeHWforecast)

forecast:::plot.forecast(countBikeHWforecast)

Predpovede na 7 dní sú tu znázornené modrou čiarou, 80 % interval predpovedí viac tmavším sivým tieňom a 95 % interval predpovedí beldším sivým tieňom.

2.2.1 Holt Winters prognózovanie s odstránenou trendovou zložkou

Predpoveď časového radu požičiavania bicyklov v prípade, že povôdný rad vyhladíme 30 dňovým jednoduchým kĺzavým priemerom:

countBikeSMA30 <- SMA(countBike,n=30)
tail(countBikeSMA30,n=10)
Time Series:
Start = 722 
End = 731 
Frequency = 1 
 [1] 4746.167 4675.400 4630.167 4583.133 4428.267 4366.767 4294.600 4161.867
 [9] 4032.800 3950.733
countBikeNoTrend <- countBike - countBikeSMA30
tail(countBikeNoTrend,n=10)
Time Series:
Start = 722 
End = 731 
Frequency = 1 
 [1] -2997.167 -2888.400 -3710.167 -3570.133 -3987.267 -2252.767 -1199.600
 [8] -2820.867 -2236.800 -1221.733
plot.ts(countBikeNoTrend)

countBikeNoTrendHW <- HoltWinters(subset(countBikeNoTrend, start=30), beta=FALSE, gamma=FALSE)
countBikeNoTrendHWforecast <- forecast:::forecast.HoltWinters(countBikeNoTrendHW, h=7)
countBikeNoTrendHWforecast
    Point Forecast     Lo 80     Hi 80     Lo 95      Hi 95
732       -2095.39 -3320.816 -869.9639 -3969.517 -221.26258
733       -2095.39 -3353.882 -836.8982 -4020.087 -170.69292
734       -2095.39 -3386.101 -804.6793 -4069.362 -121.41834
735       -2095.39 -3417.535 -773.2453 -4117.436  -73.34416
736       -2095.39 -3448.239 -742.5415 -4164.393  -26.38670
737       -2095.39 -3478.261 -712.5192 -4210.308   19.52842
738       -2095.39 -3507.645 -683.1350 -4255.248   64.46768
forecast:::plot.forecast(countBikeNoTrendHWforecast)

subset(countBike, start=724)
Time Series:
Start = 724 
End = 731 
Frequency = 1 
[1]  920 1013  441 2114 3095 1341 1796 2729
subset(countBikeSMA30, start=724)
Time Series:
Start = 724 
End = 731 
Frequency = 1 
[1] 4630.167 4583.133 4428.267 4366.767 4294.600 4161.867 4032.800 3950.733

Potom od pôvodných hodnôt časového radu uložených v premennej “countBike” odpočítame hodnoty kĺzavého priemeru uložených v premennej “countBikeSMA30” a dostaneme nový časový rad z pôvodného, ktorý bol očistený od trendovej zložky a je uložený v premennej “countBikeNoTrend”. Nový časový trend náhodne kolíše okolo hodnoty 0, čo znamená kolísanie hodnôt okolo trendu teda hodnôt jednoduchého kĺzavého priemeru.

2.2.2 Holt Winters prognózovanie s Box Cox transformáciou dát

Na pôvodný časový rad požičaných biczklov uplatníme BoxCos transformáciu, kde uvažujeme lambdu=0, čo v skotočnosti je logaritmická transformácia dát a vieme, že časový rad je nazáporný a všetky hodnoty sú rôzne od nuly, potom môžme uplatniť danú transformáciu.

countBikeTransform <- forecast::BoxCox(countBike,lambda=0)
plot.ts(countBikeTransform)

countBikeTransformHW <- HoltWinters(countBikeTransform,beta=FALSE, gamma=FALSE)
countBikeTransformHW$SSE
[1] 98.21021
countBikeTransformHWforecast <- forecast:::forecast.HoltWinters(countBikeTransformHW, h=7)
countBikeTransformHWforecast
    Point Forecast    Lo 80    Hi 80    Lo 95    Hi 95
732       7.547625 7.077270 8.017979 6.828280 8.266970
733       7.547625 7.065362 8.029888 6.810068 8.285182
734       7.547625 7.053741 8.041509 6.792295 8.302955
735       7.547625 7.042387 8.052863 6.774931 8.320319
736       7.547625 7.031283 8.063967 6.757948 8.337302
737       7.547625 7.020412 8.074837 6.741323 8.353927
738       7.547625 7.009762 8.085488 6.725034 8.370216
forecast:::plot.forecast(countBikeTransformHWforecast)

2.2.3 Chyba prognózy

Chyby prognózy sa vypočítajú ako pozorované hodnoty mínus predpovedané hodnoty pre každý časový bod. Chyby predpovede môžeme vypočítať len pre časové obdobie, ktoré pokrýva náš pôvodný časový rad. Ako už bolo uvedené, jedným z meradiel presnosti predpovedného modelu je súčet štvorcov chýb (SSE) pre chyby predpovede vo vzorke.

Chyby predpovede vo vzorke sú uložené v pomenovanom prvku “residuals” premennej zoznamu vrátenej funkciou forecast.HoltWinters(). Ak sa predpovedný model nedá zlepšiť, nemali by existovať žiadne korelácie medzi chybami predpovede pre po sebe nasledujúce predpovede. Inými slovami, ak existujú korelácie medzi chybami predpovedí pre po sebe nasledujúce predpovede, je pravdepodobné, že jednoduché predpovede s exponenciálnym vyhladzovaním by sa dali zlepšiť inou predpovednou technikou.

Aby sme zistili, či je to tak, môžeme získať korelogram chýb prognóz vo vzorke pre oneskorenia 1-20. Korelogram chýb prognózy môžeme vypočítať pomocou funkcie “acf()” v jazyku R. Na určenie maximálneho oneskorenia, na ktoré sa chceme pozrieť, použijeme parameter “lag.max” v funkcii acf().

Napríklad na výpočet korelogramu chýb predpovede vo vzorke pre dňové údaje požičiavania bicyklov pre oneskorenia 1-20 zadáme:

acf(subset(countBikeHWforecast$residuals,start=2), lag.max=20)

Z korelogramu vzorky vidíte, že autokorelácia pri oneskorení 1 a 3 presahuje hranice významnosti. Ak chceme otestovať, či existuje významný dôkaz nenulovej korelácie pri oneskoreniach 1 až 20, môžeme vykonať Ljung-Boxov test. To sa dá urobiť v programe R pomocou funkcie “Box.test()”. Maximálne oneskorenie, na ktoré sa chceme pozrieť, sa špecifikuje pomocou parametra “lag” vo funkcii Box.test(). Napríklad, ak chceme otestovať, či existujú nenulové autokorelácie pri oneskoreniach 1-20, pre chyby predpovede vo vzorke požičaných bicyklov zadáme:

 Box.test(subset(countBikeHWforecast$residuals,start=2), lag=20, type="Ljung-Box")

    Box-Ljung test

data:  subset(countBikeHWforecast$residuals, start = 2)
X-squared = 98.84, df = 20, p-value = 2.03e-12

V tomto prípade je Ljung-Boxova testovacia štatistika 98,84 a p-hodnota je 2.03e-12, takže existuje dôkaz nenulovej autokorelácie v chybách prognózy vo vzorke s oneskorením 1-20.

Aby sme si boli istí, že prognostický model nemožno zlepšiť, je tiež dobré skontrolovať, či sú chyby prognózy normálne rozdelené so strednou hodnotou nula a konštantným rozptylom. Na overenie, či chyby prognózy majú konštantný rozptyl, môžeme urobiť časový graf chýb prognózy vo vzorke:

plot.ts(subset(countBikeHWforecast$residuals,start=2))

Z grafu vyplýva, že chyby predpovedí vo vzorke majú v čase zrejme približne konštantný rozptyl, hoci veľkosť výkyvov na začiatku časového radu môže byť o niečo menšia ako v neskorších obdobiach.

Na overenie, či sú chyby predpovedí normálne rozdelené so strednou hodnotou nula, môžeme vykresliť histogram chýb predpovedí s prekrytou normálnou krivkou, ktorá má strednú hodnotu nula a rovnakú štandardnú odchýlku ako rozdelenie chýb predpovedí. Na tento účel môžeme definovať funkciu R “plotForecastErrors()”, ktorá je uvedená nižšie:

plotForecastErrors <- function(forecasterrors)
  {
     # histogram rezidui:
     mybinsize <- IQR(forecasterrors)/4
     mysd   <- sd(forecasterrors)
     mymin  <- min(forecasterrors) - mysd*5
     mymax  <- max(forecasterrors) + mysd*3
     # generované štandardné normálne dáta s 0 priemerom a std 1
     mynorm <- rnorm(10000, mean=0, sd=mysd)
     mymin2 <- min(mynorm)
     mymax2 <- max(mynorm)
     if (mymin2 < mymin) { mymin <- mymin2 }
     if (mymax2 > mymax) { mymax <- mymax2 }
     # červen sú reziduá a modrým sú normálne rozdelené dáta
     mybins <- seq(mymin, mymax, mybinsize)
     hist(forecasterrors, col="red", freq=FALSE, breaks=mybins)
     # freq=FALSE zaistí, že obsah pod histogramom bude rovný  1
     myhist <- hist(mynorm, plot=FALSE, breaks=mybins)
     points(myhist$mids, myhist$density, type="l", col="blue", lwd=2)
}

plotForecastErrors(subset(countBikeHWforecast$residuals,start=2))

shapiro.test(subset(countBikeHWforecast$residuals,start=2))

    Shapiro-Wilk normality test

data:  subset(countBikeHWforecast$residuals, start = 2)
W = 0.90756, p-value < 2.2e-16

Z grafu vyplýva, že rozdelenie chýb predpovede je približne v strede nuly a je viac-menej normálne rozložené, hoci sa zdá, že v porovnaní s normálnou krivkou je mierne vychýlené doprava. Pravé skreslenie je však relatívne malé, a preto je pravdepodobné, že chyby predpovede sú normálne rozdelené so strednou hodnotou nula.

Ljungov-Boxov test ukázal, že v chybách prognózy vo vzorke existuje dôkaz nenulovej autokorelácie a zdá sa, že rozdelenie chýb prognózy je normálne rozdelené so strednou hodnotou nula. Výsledky naznačujú, že jednoduchá metóda exponenciálneho vyhladzovania neposkytuje primeraný predpovedný model pre požičiavanie bicyklov, ktorý pravdepodobne vieme inými metódami zlepšiť.

Predpoklad ,že v chybách predpovede neexistujú autokorelácie, na ktorej boli založené 80 % a 95 % intervaly predpovedí sú neplatné. Prepoklad normality máme len graficky zatiaľ oevrenú a mali bz sme použiť test normality. Sahpiro=Wilk normality test ukázal, že dáta nie sú normlané rozdelené. Preto musíme otestovať stacionaritu radu a použiť ine nástroje časových raodv na určenie predpovede.