Aikasarjaennustaminen 2

Tämä artikkeli on jatkoa yksinkertaista eksponentiaalista tasoitusta käsittelevälle artikkelille Aikasarjaennustaminen 1. Tässä artikkelissa käytän kaksinkertaista eksponentiaalista tasoitusta eli Holtin mallia, joka huomioi myös trendin.

Holtin mallissa aikasarjan tason L (level) hetkellä t määrittää lauseke

Lt = alfa * Yt + (1 – alfa) * (Lt-1 + Tt-1)

Yllä Yt on viimeisin havainto ja Tt-1 on edellinen trendi. Trendille hetkellä t saadaan arvio lausekkeesta

Tt = beta * (Lt – Lt-1) + (1 – beta) * Tt-1

Ennuste hetkelle t+p saadaan

Lt + pTt

Mallin parametrit alfa ja beta pyritään määrittämään siten että virheiden keskihajonta RMSE saa pienimmän mahdollisen arvonsa.

Python toteutus

Tämän artikkelin ohjelmakoodin ja tulosteet löydät GitHubista:

https://github.com/taanila/tilastoapu/blob/master/forecast2.ipynb

Jos kopioit koodia itsellesi, niin kannattaa käyttää GitHubia. Tästä artikkelista kopioidut koodit eivät välttämättä toimi oikein (esimerkiksi sisennykset voivat kopioitua virheellisesti).

Oletan, että lukijalla on asennettuna Anaconda ja sen mukana tuleva Jupyter notebook.

Kirjastot

Tarvitsen monia ohjelmakirjastoja: pandas dataframen käsittelyyn, matplotlib kuvioiden tekemiseen, statsmodels eksponentiaaliseen tasoitukseen, sklearn ennustevirhettä kuvaavien tunnuslukujen laskemiseen ja math neliöjuuren laskemiseen.

import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from statsmodels.tsa.api import Holt
from sklearn.metrics import mean_squared_error, mean_absolute_error
from math import sqrt

Aikasarja

Tallennan vuosineljänneksittäisiä myyntilukuja sisältävän aikasarjan data-nimiseen dataframeen:

series=[500,350,250,400,450,350,200,300,350,200,150,
   400,550,350,250,550,550,400,350,600,750,500,400,650,850]
index=pd.date_range('2000-03-31', periods=25, freq='Q')
data=pd.DataFrame(series, index=index)
data.columns=['Demand']

Ennustemalli

Tämän jälkeen sovitan eksponentiaalisen mallin aikasarjaan ja tallennan mallin mukaiset sovitetut arvot datan Predict-sarakkeeseen. Viivakuviosta voin arvioida silmämäärin mallin sopivuutta havaintoihin.

fit1 = Holt(data['Demand']).fit()
data['Predict']=fit1.fittedvalues
data.plot()

holt1

Silmämäärin katsottuna Holtin malli ei vaikuta juurikaan paremmalta kuin yksinkertainen eksponentiaalinen tasoitus. Tarkistan asian vielä virheiden suuruutta kuvaavista tunnusluvuista. Ensiksi RMSE:

sqrt(mean_squared_error(data['Demand'], data['Predict']))

Tulokseksi saan RMSE = 147 ( yksinkertaisessa eksponentiaalisessa tasoituksessa 150)

MAD:

mean_absolute_error(data['Demand'], data['Predict'])

Tulokseksi saan MAD = 125 (yksinkertaisessa eksponentiaalisessa tasoituksessa 128)

Tunnuslukujenkaan valossa malli ei vaikuta paljoa paremmalta.

Ennuste

Lasken vielä ennusteet neljälle seuraavalle neljännekselle omaan dataframeen ja piirrän samaan kuvioon alkuperäisen aikasarjan ja neljän neljänneksen ennusteet.

index=pd.date_range('2006-06-30', periods=4, freq='Q')
datap=pd.DataFrame(fit1.forecast(4), index=index)
datap.columns=['Predict']
data['Demand'].plot()
datap['Predict'].plot()

holt3

Se, että ennusteessa on huomioitu trendi, näkyy kuviossa hyvin.

Mallin parametreista selviävät alfan (smoothing_level) ja betan (smoothing_slope) arvot:

fit1.params

{’damping_slope’: nan,
’initial_level’: 409.18761409566923,
’initial_seasons’: array([], dtype=float64),
’initial_slope’: 0.0,
’lamda’: None,
’remove_bias’: False,
’smoothing_level’: 0.25213126982732664,
’smoothing_seasonal’: nan,
’smoothing_slope’: 0.2521311899925906,
’use_boxcox’: False}

Aikasarjan tasoon liittyvä alfa on noin 0,25 ja trendiin liittyvä beta on noin 0,25.

Aikasarjan lähempää tarkastelua

Löytääkseni paremman ennustemallin tarkastelen aikasarjaa hieman lähemmin purkamalla sen komponentteihin.

from statsmodels.tsa.api import seasonal_decompose
seasonal_decompose(data['Demand']).plot()

Tuloksena saan neljä kuviota:

  • alkuperäinen aikasarja
  • aikasarjasta erotettu trendi
  • aikasarjan kausivaihtelu
  • aikasarjan jäljelle jäänyt osa trendin ja kausivaihtelun poistamisen jälkeen.

holt4

Aikasarjassa on erotettavissa selkeä neljän vuosineljänneksen jaksoissa toistuva kausivaihtelu, jota ennustemallini ei huomioinut. Asiaa voin tarkastella myös autokorrelaatioiden avulla. Autokorrelaatio tarkoittaa aikasarjan korrelaatiota viivästetyn aikasarjan kanssa, esimerkiksi aikasarjan korrelaatio neljän vuosineljänneksen takaisiin aikasarjan arvoihin. Autokorrelaatio voidaan laskea eri viiveille. Tämän voin tehdä pandas-kirjaston autocorrelation_plot-toiminnolla:

from pandas.plotting import autocorrelation_plot
autocorrelation_plot(data['Demand'])

holt5

Vaaka-akselilla on viive (lag) ja pystyakselilla autokorrelaatiokertoimen arvo. Huomaan, että viiveen 4 kohdalla on suurehko korrelaatio. Tämä viittaa 4 vuosineljänneksen mittaiseen kausivaihtelujaksoon. Kuvion katkoviivat edustavat tilastollisesti merkitsevän korrelaation rajoja. Viiveen 4 kohdalla korrelaatio on katkoviivan yläpuolella ja näin ollen tilastollisesti merkitsevä.

Seuraavassa artikkelissa Aikasarjaennustaminen 3 laadin ennustemallin, jossa myös 4 vuosineljänneksen jaksoissa toistuva kausivaihtelu on huomioitu.

 

Mainokset