En aquest apartat, explicarem algunes eines generals que són útils per a moltes situacions de predicció diferents. Descriurem alguns mètodes de predicció de referència, procediments per comprovar si un mètode de predicció ha utilitzat adequadament la informació disponible, tècniques per calcular intervals de predicció i mètodes per avaluar la precisió de la predicció.
Cadascuna de les eines que es presenten aquí s’utilitzarà més endavant a mesura que es vagi desenvolupant i explorant tota la gamma de mètodes de predicció.
G. J. Hyndman and G. Athanasopoulos, Forecasting: Principles and Practice,3rd edition, Chapter 5, 2021, OTexts: Melbourne, Australia. Disponible a otexts.com/.
La llibreria fp3 conté tots els conjunts de dades
necessaris per als exemples i exercicis del llibre “Forecasting:
principles and practice, 3d ed.” de Rob J Hyndman i George
Athanasopoulos. Per aixo s’utilitzarà principalment datasets d’aquest
paquest.
La llibreria tsibbledata proporciona diversos conjunts
de dades a l’estructura de dades “tsibble”. Aquests conjunts de dades
són útils per aprendre i demostrar com es poden ordenar, visualitzar i
preveure les dades temporals ordenades.
La lliberia fma conté tots els conjunts de dades de
“Forecasting: methods and applications” de Makridakis, Wheelwright i
Hyndman (Wiley, 3a ed., 1998).
library(fpp2)
library(fpp3)
library(tsibbledata)
library(fma)
Possiblement se n’utilitzaran d’altres, però aquestes seran la més usades.
A més de les llibreries base de R, atilitzarem algunes
llibreria de l’entorn tidyverse::dplyr per a
la manipulació de dades, ggplot2 per a gràfics i
patchwork per a gràfics múltiples. Puntualment, n’hem
utilitzat d’altres, que apareixeran indicades al codi.
library(ggplot2)
library(dplyr)
library(patchwork)
Pel que fa a les funcions estadístiques, a més de stats
que ve per defecte amb R, farem servir en vàries ocasions
forecast (veure) i astsa que són llibreries
específiques per anàlisi de sèries temposrals. També es podran fer
servir altres paquets quan no estigui disponible alguna funció o les
disponibles no tinguin totes les característiques desitjades. En tot
cas, en el codi sempre es trobarà indicada la llibreria que
correspongui.
Ateses le nombroses ambigüitats que sovint es poden generar, sovint
les funcions i els datasets van acompanyats pel nom del paque d’origen
(per exemple, ggplot2::autoplot(),
stats::acf(), etc.).
Alguns mètodes de predicció són extremadament senzills i sorprenentment eficaços. Farem servir quatre mètodes de predicció senzills com a punts de referència al llarg d’aquest llibre. Per il·lustrar-los, farem servir la producció trimestral de maons d’argila australians entre el 1970 i el 2004.
Aquí, les previsions de tots els valors futurs són iguals a la mitjana de les dades històriques. Si denotem les dades històriques per \(y_1,…,y_T\), aleshores podem escriure les previsions com \[ \hat y_{T+h|T}=\bar y=(y_1+⋯+y_T)/T. \]
La notació \(\hat y_{T+h|T}\) és una abreviatura per a l’estimació de \(y_{T+h}\) basada en les dades \(y_1,…,y_T\).
# El dataset aus_production està en format tstibble. El convertim a ts, seleccionnem el
# periode amb stats::window() i seleccionem la variable amb '['.
maons <- window(ts(aus_production, start = 1956, frequency = 4),
start = 1970, end = c(2004,4))[,4]
mmaons <- mean(maons) # La mitjana tal qual
autoplot(maons) +
geom_segment(aes(x = min(time(maons)), y = mmaons,
xend = max(time(maons)), yend = mmaons), color= "darkred",
linetype = 2, linwidth=1) +
geom_segment(aes(x = max(time(maons)), y = mmaons,
xend = max(time(maons))+2, yend = mmaons), color= "darkred",
linewidth = 1) +
ggtitle("Predicció amb mètode de la mitjana")+
ylab("Producció de maons") +
theme_bw()
Figura 1
Per a les previsions “naive”, simplement establim totes les previsions com el valor de l’última observació. És a dir, \(\hat y_{T+h|T}=y_T\).
Aquest mètode funciona notablement bé per a moltes sèries temporals econòmiques i financeres.
# Mètode manual
#ggplot2::autoplot(maons) +
# geom_segment(aes(x = max(time(maons)),
# y = tail(maons, n=1),
# xend = max(time(maons))+2,
# yend = tail(maons, n=1)),
# color= "blue",
# linewidth = 1) +
# theme_bw()
naif <- forecast::naive(maons,h=12, level = F)
plot(naif, col = "dodgerblue3", fcol= "darkred", panel.first=grid(), flwd = 2.5,lwd=2.5,
main = "Predicció amb mètode naïf", ylab = "Producció de maons")
abline(h=tail(maons, n=1),col= "grey70", lty=2)
Figura 2
Un mètode similar és útil per a dades altament estacionals. En aquest cas, establim cada previsió perquè sigui igual a l’últim valor observat de la mateixa temporada (per exemple, el mateix mes de l’any anterior). Formalment, la previsió per al temps \(T+h\) s’escriu com \(\hat y_{T+h|T}=y_{T+h−m(k+1)},\) on \(m=\) el període estacional, i \(k\) és la part entera de \((h−1)/m\) (és a dir, el nombre d’anys complets en el període de previsió anterior al temps \(T+h\)). Això sembla més complicat del que realment és. Per exemple, amb dades mensuals, la previsió per a tots els valors futurs del febrer és igual a l’últim valor observat del febrer. Amb dades trimestrals, la previsió de tots els valors futurs del Q2 és igual a l’últim valor observat del Q2 (on Q2 significa el segon trimestre). Regles similars s’apliquen per a altres mesos i trimestres, i per a altres períodes estacionals.
snaif <- forecast::snaive(maons,h=12, level = F)
plot(snaif, col = "dodgerblue3", fcol= "darkred", panel.first=grid(),flwd = 2.5,
main = "Predicció amb mètode naïf estacional", ylab = "Producció de maons")
Figura 3
# veure:https://cran.r-project.org/web/packages/forecast/refman/forecast.html
Una variació del mètode naïf és permetre que les previsions augmentin o disminueixin amb el temps, on la quantitat de canvi al llarg del temps (anomenada deriva o drift*) s’estableix com el canvi mitjà observat a les dades històriques. Així, la previsió per al temps \(T+h\) ve donada per \[\hat y_{T+h|T}=y_{T}+\frac{h}{T−1}∑_{t=2}^T (y_t−y_{t-1})=y_T+h\bigg(\frac{y_T−y_1}{T−1}\bigg).\] Això és equivalent a dibuixar una línia entre la primera i l’última observació i extrapolar-la al futur.
dr <- forecast::rwf(maons, h=12, level = F, drift = T)
plot(dr, col = "dodgerblue3", fcol= "darkred", panel.first=grid(),flwd = 2.5,
main = "Predicció amb mètode de deriva", ylab = "Producció de maons")
segments(min(time(maons)), as.vector(head(maons,1)),
max(time(maons)), as.vector(tail(maons,1)), col = "darkgreen")
Cada observació d’una sèrie temporal es pot predir utilitzant totes les observacions prèvies. Anomenem aquests valors ajustats i es denoten per \(\hat y{t|t−1}\), és a dir, la predicció de \(y_t\) basada en observacions \(y_1,…,y_{t−1}\). Els fem servir tan sovint que de vegades ometem part del subíndex i simplement escrivim \(\hat y_t\) en lloc de \(\hat y_{t|t−1}\).
Els “residuals” en un model de sèries temporals són el que queda després d’ajustar un model. Els residuals són iguals a la diferència entre les observacions i els valors ajustats corresponents: \[e_t=y_t−\hat y_t.\]
Si s’ha utilitzat una transformació al model, sovint és útil mirar els residuals a l’escala transformada. Anomenem aquests “residuals d’innovació”. Per exemple, suposem que hem modelat els logaritmes de les dades, \(w_t = \text{log}(y_t)\). Aleshores, els residus d’innovació es donen per \(wt−\hat w_t\), mentre que els residus regulars es donen per \(y_t−\hat y_t\). (Vegeu més endavant per saber com utilitzar les transformacions en fer previsions.) Si no s’ha utilitzat cap transformació, els residus d’innovació són idèntics als residus regulars i, en aquests casos, simplement els anomenarem “residus”.
Un bon mètode de previsió produirà residus d’innovació amb les propietats següents:
Els residus d’innovació no estan correlacionats. Si hi ha correlacions entre els residus d’innovació, aleshores hi ha informació als residus que s’hauria d’utilitzar en el càlcul de les previsions.
Els residus d’innovació tenen una mitjana zero. Si tenen una mitjana diferent de zero, les previsions estan esbiaixades.
Qualsevol mètode de previsió que no compleixi aquestes propietats es pot millorar. Tanmateix, això no vol dir que els mètodes de previsió que compleixen aquestes propietats no es puguin millorar. És possible tenir diversos mètodes de previsió diferents per al mateix conjunt de dades, tots els quals compleixen aquestes propietats. Comprovar aquestes propietats és important per veure si un mètode utilitza tota la informació disponible, però no és una bona manera de seleccionar un mètode de previsió.
Si alguna d’aquestes propietats no es compleix, el mètode de previsió es pot modificar per donar millors previsions. Ajustar el biaix és fàcil: si els residus tenen una mitjana m, simplement afegiu m a totes les previsions i el problema del biaix es resol. Solucionar el problema de la correlació és més difícil i no l’abordarem fins més endavant.
A més d’aquestes propietats essencials, és útil (però no necessari) que els residuals també tinguin les dues propietats següents.
Aquestes dues propietats faciliten el càlcul dels intervals de predicció (vegeu més endavan). Tanmateix, un mètode de predicció que no compleixi aquestes propietats no es pot millorar necessàriament. De vegades, aplicar una transformació de Box-Cox pot ajudar amb aquestes propietats, però en cas contrari, normalment hi ha poc que pugueu fer per assegurar-vos que els vostres residuals d’innovació tinguin una variància constant i una distribució normal. En canvi, cal un enfocament alternatiu per obtenir intervals de predicció.
Exemple: Previsió dels preus de tancament diari de les accions de Google Continuarem amb l’exemple del preu de tancament diari de les accions de Google de la secció 5.2. Per als preus i índexs del mercat de valors, el millor mètode de predicció sovint és el mètode naïf. És a dir, cada previsió és simplement igual a l’últim valor observat, o ^yt=yt−1. Per tant, els residuals són simplement iguals a la diferència entre observacions consecutives: et=yt−^yt=yt−yt−1.
El gràfic següent mostra el preu de tancament diari de les accions de Google per als dies de negociació durant el 2015. El gran salt correspon al 17 de juliol de 2015, quan el preu va augmentar un 16% a causa dels resultats inesperadament forts del segon trimestre.
# Re-index based on trading days
google_stock <- tsibbledata::gafa_stock |>
filter(Symbol == "GOOG", year(Date) >= 2015) |>
mutate(day = row_number()) |>
tsibble::update_tsibble(index = day, regular = TRUE) # el paquet disposa
# Filtrar l'any
google_2015 <- google_stock |> filter(year(Date) == 2015)
plot(ts(google_2015, start = c(2015,1),frequency = 2052)[,6], panel.first=grid(),
main = "Valor de tancament diari de Google", ylab = "$US", xlab= "Dia")
Figura 4
goog <- forecast::naive(ts(google_2015, start = c(2015,1),frequency = 2052)[,6], level = F)
plot(resid(goog), panel.first=grid(),
main = "Residus amb el mètode naïf", ylab = "", xlab= "Dia")
Figura 4: : Residus de la previsió del preu de les accions de Google utilitzant el mètode naïf.
hist(resid(goog), breaks = 30, panel.first=grid(),
main = "Histograma de residus", ylab = "Freqüència", xlab= "Residus")
Figura 5: Histograma dels residus del mètode naïf aplicat al preu de les accions de Google.
forecast::Acf(resid(goog), lag.max = 25, panel.first=grid(),
main = "Correlograma del residus (ACF)", ylab = "Freqüència", xlab= "Residus")
Figura 6: ACF dels residus d’ajustament del mètode naïf sobre la sèri del preu de les accions de Google. Es visualitza molt poca correlació i per tant un ajustament de la predicció.
Histograma dels residuals del mètode naïf aplicat al preu de les accions de Google. La cua dreta sembla una mica massa llarga per a una distribució normal.
Aquests gràfics mostren que el mètode naïf produeix previsions que semblen tenir en compte tota la informació disponible. La mitjana dels residus és propera a zero i no hi ha cap correlació significativa a la sèrie de residus. El diagrama temporal dels residus mostra que la variació dels residus es manté pràcticament igual a través de les dades històriques, tret d’un valor atípic, i per tant la variància residual es pot tractar com a constant. Això també es pot veure a l’histograma dels residu. L’histograma suggereix que els valors residuals poden no ser normals: la cua dreta sembla una mica massa llarga, fins i tot quan ignorem el valor atípic. Globalment doncs, les previsions d’aquest mètode probablement seran força bones, però els intervals de predicció que es calculen assumint una distribució normal poden ser inexactes.
Una bona drecera per produir aquests gràfics de diagnòstic de valors
residuals és la funció gg_tsresiduals() de
feasts, que produirà un diagrama temporal, un diagrama ACF
i un histograma dels residuals.
google_2015 |>
model(NAIVE(Close)) |>
feasts::gg_tsresiduals()
Figura 7
A més de mirar el gràfic ACF, també podem fer una prova més formal per a l’autocorrelació considerant un conjunt complet de valors \(r_k\) com un grup, en lloc de tractar cadascun per separat.
Recordem que \(r_k\) és l’autocorrelació per al retard \(k\). Quan mirem el gràfic ACF per veure si cada pic està dins dels límits requerits, estem duent a terme implícitament múltiples proves d’hipòtesi, cadascuna amb una petita probabilitat de donar un fals positiu. Quan es fan prou d’aquestes proves, és probable que almenys una doni un fals positiu, i per tant podem concloure que els residuals tenen alguna autocorrelació restant, quan en realitat no en tenen.
Per superar aquest problema, provem si les primeres autocorrelacions \(ℓ\) són significativament diferents del que s’esperaria d’un procés de soroll blanc. Una prova per a un grup d’autocorrelacions s’anomena prova de portmanteau, d’una paraula francesa que descriu una maleta o un penja-robes que porta diverses peces de roba.
Una d’aquestes proves és el test de Box-Pierce, basat en l’estadístic següent
\[ Q=T∑_{k=1}^ℓ r_k^2, \] on \(ℓ\) és el retard màxim que es considera i \(T\) és el nombre d’observacions. Si cada \(r_k\) és proper a zero, \(Q\) serà petit. Si alguns valors de \(r_k\) són grans (positius o negatius), \(Q\) serà gran. Suggerim utilitzar \(ℓ=10\) per a dades no estacionals i \(ℓ=2m\) per a dades estacionals, on \(m\) és el període d’estacionalitat. Tanmateix, la prova no és bona quan \(ℓ\) és gran, de manera que si aquests valors són més grans que \(T/5\), utilitzeu \(ℓ=T/5\)
Una prova relacionada (i més precisa) és el test de Ljung-Box, basat en \[ Q^∗=T(T+2)∑_{k=1}^ℓ (T−k)^{−1}r_k^2. \]
De nou, valors grans de \(Q^*\) suggereixen que les autocorrelacions no provenen d’una sèrie de soroll blanc.
Però, com de gran és massa gran? Si les autocorrelacions provinguessin d’una sèrie de soroll blanc, tant \(Q\) com \(Q^∗\) tindrien una distribució \(χ^2\) amb \(ℓ\) graus de llibertat.. En el codi següent, \(\tt lag = ℓ\).
Box.test(resid(goog), lag =10, type = "Box-Pierce")
##
## Box-Pierce test
##
## data: resid(goog)
## X-squared = 7.7445, df = 10, p-value = 0.6538
Box.test(resid(goog), lag =10, type = "Ljung-Box")
##
## Box-Ljung test
##
## data: resid(goog)
## X-squared = 7.9141, df = 10, p-value = 0.6372
Tant per a \(Q\) com per a \(Q^∗\), els resultats no són significatius (és a dir, els valors p són relativament grans). Per tant, podem concloure que els residuals no es distingeixen d’una sèrie de soroll blanc.
Un enfocament senzill alternatiu que pot ser apropiat per predir el preu de tancament diari de les accions de Google és el mètode de deriva. Es veu l’únic paràmetre estimat, el coeficient de deriva, que mesura el canvi mitjà diari observat a les dades històriques.
googdrift <- forecast::rwf(ts(google_2015, start = c(2015,1),frequency = 2052)[,6],
drift = T)
googdrift$model$par$drift
## [1] 0.9439931
Aplicant la prova de Ljung-Box, obtenim el següent resultat.
Box.test(resid(googdrift), lag = 10, type = "Ljung-Box")
##
## Box-Ljung test
##
## data: resid(googdrift)
## X-squared = 7.9141, df = 10, p-value = 0.6372
Igual que amb el mètode naïf, els residuals del mètode de deriva són indistingibles d’una sèrie de soroll blanc.
En estadística, expressem la incertesa de les nostres previsions mitjançant una distribució de probabilitat. Descriu la probabilitat d’observar possibles valors futurs mitjançant el model ajustat. La previsió en un punt és la mitjana d’aquesta distribució. La majoria dels models de sèries temporals produeixen previsions amb distribució normal, és a dir, assumim que la distribució de possibles valors futurs segueix una distribució normal. Més endavant en aquesta secció, analitzarem un parell d’alternatives a les distribucions normals.
Un interval de predicció proporciona un interval dins del qual esperem que \(y_t\) tingui una probabilitat especificada. Per exemple, suposant que la distribució d’observacions futures és normal, un interval de predicció del 95% per a la previsió de pas h és \[\hat y_{T+h|T}±1.96\hat σ_h,\] on \(\hat σ_h\) és una estimació de la desviació estàndard de la distribució de previsió del pas \(h\).
De manera més general, un interval de predicció es pot escriure com \[ \hat {yT+h|T}±c\hat σ_h \] on el multiplicador \(c\) depèn de la probabilitat de cobertura.
El valor dels intervals de predicció rau en el fet que expressen la incertesa de les previsions. Si només produïm previsions sobre el punt, no hi ha manera de saber la precisió de les previsions. Tanmateix, si també produïm intervals de predicció, queda clar quanta incertesa hi ha associada a cada previsió. Per aquest motiu, les prediccions del punt gairebé no tenen cap valor sense els intervals de predicció que les acompanyen.
Tabla 4.1: Multiplicadors per a intervals de predicció.
| Percentatge | Multiplicador |
|---|---|
| 50 | 0.67 |
| 55 | 0.76 |
| 60 | 0.84 |
| 65 | 0.93 |
| 70 | 1.04 |
| 75 | 1.15 |
| 80 | 1.28 |
| 85 | 1.44 |
| 90 | 1.64 |
| 95 | 1.96 |
| 96 | 2.05 |
| 97 | 2.17 |
| 98 | 2.33 |
| 99 | 2.58 |
Quan es preveu un pas endavant, la desviació estàndard de la distribució de la previsió es pot estimar utilitzant la desviació estàndard dels residuals donada per \[ \hat σ=\sqrt{\frac{1}{T−K−M}∑_{t=1}^T e_t^2},\tag{4.1} \] on \(K\) és el nombre de paràmetres estimats en el mètode de previsió i \(M\) és el nombre de valors que falten als residuals. (Per exemple, \(M=1\) per a una previsió naive, perquè no podem predir la primera observació.)
Per exemple, considerem una previsió naïf per a les dades
del preu de les accions de Google google_2015 (que es
mostren a la Figura 9). L’últim valor de la sèrie observada és 758,88,
de manera que la previsió del següent valor del preu és 758,88. La
desviació estàndard dels residuals del mètode naïf, tal com
dóna l’Equació (4.1), és 11,19. Per tant, un interval de predicció del
95% per al següent valor del GSP és \[
758,88±1,96(11,19)=[736,9,780,8].
\]
De la mateixa manera, un interval de predicció del 80% ve donat per \[ 758,88±1,28(11,19)=[744,5,773,2]. \] El valor del multiplicador (1,96 o 1,28) és conforme a taula de normalitat.
Una característica comuna dels intervals de predicció és que solen augmentar de longitud a mesura que augmenta l’horitzó de previsió. Com més endavant preveiem, més incertesa hi ha associada a la previsió i, per tant, més amplis són els intervals de predicció. És a dir, σh sol augmentar amb h (tot i que hi ha alguns mètodes de previsió no lineals que no tenen aquesta propietat).
Per produir un interval de predicció, cal tenir una estimació de \(σ_h\). Com ja s’ha assenyalat, per a les previsions d’un pas \((h=1)\), l’equació (4.1) proporciona una bona estimació de la desviació estàndard de la previsió \(σ_1\). Per a les previsions de diversos passos, es requereix un mètode de càlcul més complicat. Aquests càlculs assumeixen que els residuals no estan correlacionats.
Per als quatre mètodes de referència, és possible derivar matemàticament la desviació estàndard de la predicció presuposant valors residuals no correlacionats. Si \(\hat σ_h\) denota la desviació estàndard de la distribució de previsió en \(h\) passos, i \(\hatσ\) és la desviació estàndard residual donada per (4.1), aleshores podem utilitzar les expressions que es mostren a la Taula 4.2. Cal tenir en compte que quan \(h=1\) i \(T\) és gran, totes donen el mateix valor aproximat \(\hatσ\).
Taula 4.2: Desviació estàndard de la previsió multipas per als quatre mètodes de referència, on \(σ\) és la desviació estàndard residual, \(m\) és el període estacional i \(k\) és la part entera de \((h−1)/m\) (és a dir, el nombre d’anys complets del període de previsió anterior al temps \(T+h\)).
| Mètode de referència | Desviació estàndard als passos h |
|---|---|
| Mitjana | \(\hat\sigma_h = \hat\sigma\sqrt{1 + 1/T}\) |
| Naïf | \(\hat\sigma_h = \hat\sigma\sqrt{h}\) |
| Naïf estacional | \(\hat\sigma_h = \hat\sigma\sqrt{k+1}\) |
| Deriva (drift) | \(\hat\sigma_h = \hat\sigma\sqrt{h(1+h/(T-1))}\) |
Els intervals de predicció es poden calcular fàcilment utilitzant diferents llibreries de R. Per exemple, aquí teniu el resultat quan s’utilitza el mètode naïve per al preu de les accions de Google.
plot(forecast::naive(ts(google_2015, start = c(2015,1),frequency = 252)[,6], h=10),
col = "dodgerblue3", fcol= "darkred", panel.first=grid(), flwd = 2.5,lwd=2.5,
main = "Preu diari de les accions de Google", ylab = "$US")
legend("topleft", title = "Interval de confiança",
legend=c("80%", "95%"), fill = c("grey65","grey85"),
bg="white",cex = 0.7, box.lty = NULL)
Figura 8: Intervals de predicció del 80% i 95% per al preu de tancament de les accions de Google basats en el mètode naïf.
És important avaluar la precisió de la previsió mitjançant previsions reals. En conseqüència, la mida dels residuals no és una indicació fiable de la probabilitat que tinguin els errors de previsió reals. La precisió de les previsions només es pot determinar considerant el rendiment d’un model amb dades noves que no es van utilitzar en ajustar el model.
A l’hora de triar models, és una pràctica habitual separar les dades disponibles en dues parts, dades d’entrenament i dades de prova, on les dades d’entrenament s’utilitzen per estimar qualsevol paràmetre d’un mètode de previsió i les dades de prova s’utilitzen per avaluar la seva precisió. Com que les dades de prova no s’utilitzen per determinar les previsions, haurien de proporcionar una indicació fiable de la probabilitat que el model faci una previsió amb dades noves.
La mida del conjunt de prova sol ser d’aproximadament el 20% de la mostra total, tot i que aquest valor depèn de la longitud de la mostra i de la distància amb què es vulgui fer la previsió. Idealment, el conjunt de prova hauria de ser almenys tan gran com l’horitzó màxim de previsió requerit. Cal tenir en compte els punts següents.
Un model que s’ajusta bé a les dades d’entrenament no necessàriament farà una bona previsió. Sempre es pot obtenir un ajust perfecte utilitzant un model amb prou paràmetres. Sobreajustar un model a les dades és tan dolent com no identificar un patró sistemàtic a les dades.
Algunes referències descriuen el conjunt de prova com el “conjunt reservat” perquè aquestes dades es “retenen fora” de les dades utilitzades per a l’ajust. Altres referències anomenen el conjunt d’entrenament “dades dins de la mostra” i el conjunt de prova “dades fora de la mostra”. Preferim utilitzar “dades d’entrenament” i “dades de prova”.
Un “error” de previsió és la diferència entre un valor observat i la seva previsió. Aquí “error” no no tiene sentido de “falta”, sinó que és la part imprevisible d’una observació. Es pot escriure com
\[ e_{T+h} = y_{T+h} - \hat{y}_{T+h|T}, \]
on les dades d’entrenament vénen donades per \(\{y_1,\dots,y_T\}\) i les dades de prova vénen donades per \(\{y_{T+1},y_{T+2},\dots\}\).
Tingueu en compte que els errors de previsió són diferents dels valors residuals de dues maneres. Primer, els residuals es calculen al conjunt d’entrenament mentre que els errors de previsió es calculen al conjunt de prova. En segon lloc, els residuals es basen en previsions d’un sol pas, mentre que els errors de previsió poden implicar previsions de diversos passos.
Podem mesurar la precisió de la previsió resumint els errors de previsió de diferents maneres.
Els errors de previsió estan a la mateixa escala que les dades. Les mesures de precisió que es basen només en \(e_t\) són, per tant, dependents de l’escala i no es poden utilitzar per fer comparacions entre sèries que impliquen diferents unitats.
Les dues mesures dependents de l’escala més utilitzades es basen en els errors absoluts o errors quadràtics: \[ \begin{align*} \text{Mean absolute error: MAE} & = \text{mean}(|e_{t}|),\\ \text{Root mean squared error: RMSE} & = \sqrt{\text{mean}(e_{t}^2)}. \end{align*} \] Quan es comparen mètodes de previsió aplicats a una sola sèrie temporal o a diverses sèries temporals amb les mateixes unitats, el MAE és popular, ja que és fàcil d’entendre i calcular. Un mètode de previsió que minimitza el MAE conduirà a previsions de la mediana, mentre que minimitzar el RMSE conduirà a previsions de la mitjana. En conseqüència, el RMSE també s’utilitza àmpliament, tot i ser més difícil d’interpretar.
L’error percentual ve donat per \(p_t=100e_t/y_t\). Els errors percentuals tenen l’avantatge de no tenir unitats i, per tant, s’utilitzen sovint per comparar el rendiment de les previsions entre conjunts de dades. La mesura més utilitzada és: Error percentual absolut mitjà: \[ \text{Error percentual absolut mitjà: MAPE} = \text{mean}(|p_{t}|). \] Les mesures basades en errors percentuals tenen el desavantatge de ser infinites o indefinides si \(y_t=0\)per a qualsevol \(t\) en el període d’interès, i de tenir valors extrems si \(y_t\) és proper a zero. Un altre problema amb els errors percentuals que sovint es passa per alt és que assumeixen que la unitat de mesura té un zero significatiu. Per exemple, un error percentual no té sentit quan es mesura la precisió de les previsions de temperatura a les escales Fahrenheit o Celsius, perquè la temperatura té un punt zero arbitrari.
També tenen el desavantatge que penalitzen més els errors negatius que els positius. Aquesta observació va conduir a l’ús de l’anomenat MAPE “simètric” (sMAPE) proposat per Armstrong (1978, p. 348), que es va utilitzar a la competició de predicció M3. Es defineix per
\[ \text{sMAPE} = \text{mean}\left(200|y_{t} - \hat{y}_{t}|/(y_{t}+\hat{y}_{t})\right). \]
Tanmateix, si \(y_t\) és proper a zero, \(\text y_t\) també és probable que sigui proper a zero. Per tant, la mesura encara implica la divisió per un nombre proper a zero, cosa que fa que el càlcul sigui inestable. A més, el valor de sMAPE pot ser negatiu, de manera que no és realment una mesura d’“errors percentuals absoluts”.
Hyndman i Koehler (2006) recomanen que no s’utilitzi el sMAPE. S’inclou aquí només perquè s’utilitza àmpliament, tot i que no l’utilitzarem.
Hyndman i Koehler (2006) van proposar els errors escalats com a alternativa a l’ús d’errors percentuals en comparar la precisió de la predicció entre sèries amb diferents unitats. Van proposar escalar els errors basant-se en l’arrel quadràtica mitjana (MAE) d’entrenament a partir d’un mètode de previsió simple.
Per a una sèrie temporal no estacional, una manera útil de definir un error escalat utilitza previsions naïves: \[ q_{j} = \frac{\displaystyle e_{j}} {\displaystyle\frac{1}{T-1}\sum_{t=2}^T |y_{t}-y_{t-1}|}. \]
Com que tant el numerador com el denominador impliquen valors a l’escala de les dades originals, \(q_j\) és independent de l’escala de les dades. Un error escalat és inferior a 1 si prové d’una previsió millor que la previsió naïve mitjana d’un pas calculada sobre les dades d’entrenament. Per contra, és superior a 1 si la previsió és pitjor que la previsió naïve mitjana d’un pas calculada sobre les dades d’entrenament.
Per a sèries temporals estacionals, es pot definir un error escalat utilitzant previsions naïves estacionals:
\[ q_{j} = \frac{\displaystyle e_{j}} {\displaystyle\frac{1}{T-m}\sum_{t=m+1}^T |y_{t}-y_{t-m}|}. \]
L’error absolut escalat mitj[a serà \[ \text{MASE} = \text{mean}(|q_{j}|). \]
De la mateixa manera, l’arrel quadràtica mitjana de l’error escalat ve donada per \[ \text{RMSSE} = \sqrt{\text{mean}(q_{j}^2)}, \]
on \[ q^2_{j} = \frac{\displaystyle e^2_{j}} {\displaystyle\frac{1}{T-m}\sum_{t=m+1}^T (y_{t}-y_{t-m})^2}, \]
i establim \(m=1\) per a dades no estacionals.
Crearem dos conjunts de dades: un conjunt d’entrenamen amb dades trimestrals de 1992 fins a 2010, i un conjunt de prova que dades des del primer trimestre de 2007 fins al 2010.
recent_production <- aus_production |>
filter(year(Quarter) >= 1992)
beer_train <- recent_production |>
filter(year(Quarter) <= 2007)
av <- forecast::meanf(ts(beer_train, start = c(1992,1),frequency = 4)[,2], level = F)
naiv <- forecast::naive(ts(beer_train, start = c(1992,1),frequency = 4)[,2], level = F)
snaiv <- forecast::snaive(ts(beer_train, start = c(1992,1),frequency = 4)[,2], level = F)
drift <- forecast::rwf(ts(beer_train, start = c(1992,1),frequency = 4)[,2], drift = T, level = F)
plot(ts(recent_production, start = c(1992,1),frequency = 4)[,2],
lwd=1.8, col="dodgerblue3", panel.first=grid(), xlab="",ylab="",
main= "Producció de cervesa 1990 - 2010: sèrie temporal i previsions")
lines(av$mean, col= "darkred",lwd= 1.8)
lines(naiv$mean, col = "red",lwd=1.8)
lines(drift$mean, col = "green",lwd=1.8)
lines(snaiv$mean,col = "orange3",lwd=1.8)
legend("topright", title = "Models de predicció",
legend=c("Dades brutes", "Mitjana", "Naïf", "Drift", "Naïf estac."),
fill = c("dodgerblue3","darkred","red","green","orange"),
bg="white",cex = 0.7, box.lty = NULL)
Figura 9
La figura 9 mostra quatre mètodes de previsió aplicats a la producció trimestral de cervesa australiana utilitzant només dades fins a finals del 2007. També es mostren els valors reals per al període 2008–2010. Calculem les diferent mesures de precisió de la previsió per a aquest període.
pred_birra <- list(
Mitjana <- forecast::meanf(ts(beer_train, start = c(1992,1),frequency = 4)[,2], level = F),
Naif <- forecast::naive(ts(beer_train, start = c(1992,1),frequency = 4)[,2], level = F),
`Naif est.` <- forecast::snaive(ts(beer_train, start = c(1992,1),frequency = 4)[,2], level = F),
Drift <- forecast::rwf(ts(beer_train, start = c(1992,1),frequency = 4)[,2], drift = T, level = F)
)
accur_birra <- lapply(pred_birra, function(x) as.data.frame(forecast::accuracy(
x,ts(recent_production, start = c(1992,1),frequency = 4)[,2]))[2,]) |>
bind_rows() |>
select(2,3,5,6)
accur_birra$Mètode <- c("Mitjana", "Naif", "Naif est.", "Drift")
accur_birra[,c(5,1:4)] |>
flextable::flextable() %>%
flextable::set_caption("Diferents mesures de la precisió de les previsions respecte a les dades reals")
Mètode | RMSE | MAE | MAPE | MASE |
|---|---|---|---|---|
Mitjana | 38.44724 | 34.82500 | 8.283390 | 2.435315 |
Naif | 62.69290 | 57.40000 | 14.184424 | 4.013986 |
Naif est. | 14.99166 | 14.00000 | 3.267315 | 0.979021 |
Drift | 64.90129 | 58.87619 | 14.577487 | 4.117216 |
Pel gràfic és obvi que el mètode naïf estacional és el millor per a aquestes dades, tot i que encara es pot millorar, com descobrirem més endavant. De vegades, diferents mesures de precisió donaran lloc a resultats diferents quant a quin mètode de previsió és millor. Tanmateix, en aquest cas, tots els resultats assenyalen el mètode naïf estacional com el millor d’aquests quatre mètodes per a aquest conjunt de dades.
Considerant un exemple no estacional, considereu el preu de les accions de Google. El gràfic següent mostra les cotitzacions de tancament de les accions de 2015, juntament amb les previsions per al gener de 2016 obtingudes per tres mètodes diferents.
tsgoogle_2015 <- ts(google_2015, start = c(2015,1),frequency = 1)[,6]
googleJan_2016 <- google_stock %>% filter(Date>="2015-12-31" & Date<="2016-01-31")
tsgoogleJan_2016 <- ts(googleJan_2016, start = c(2016,1),frequency = 1)[,6]
# Unió de dues TS consecutives per poder-les reresenta: ojo, que té la seva somplicació
google1516 <- ts(c(tsgoogle_2015,tsgoogleJan_2016),
start = start(tsgoogle_2015), frequency = frequency(tsgoogle_2015))
# Models de previsió
googleav <- forecast::meanf(ts(google_2015, start = c(2015,1))[,6],
h=19, level = F)
googlenaiv <- forecast::naive(ts(google_2015, start = c(2015,1),frequency = 1)[,6],
h=19, level = F)
googledrift <- forecast::rwf(ts(google_2015, start = c(2015,1),frequency = 1)[,6],
h=19, drift = T, level = F)
plot(google1516,
lwd=2, col="blue", panel.first=grid(), xlab="",ylab="", xaxt = "n",
main= "Preu de l'acció de Google: sèrie de 2015 amb previsions de gener 2016")
lines(googleav$mean, col= "darkred",lwd= 2)
lines(googlenaiv$mean, col = "red",lwd=2)
lines(googledrift$mean, col = "green",lwd=2)
legend("topleft", title = "Models de predicció",
legend=c("Dades brutes", "Mitjana", "Naïf", "Drift"),
fill = c("blue","darkred","red","green"),
bg="white",cex = 0.7, box.lty = NULL)
Figura 10
pred_google <- list(
googleav,googlenaiv, googledrift
)
accur_google <- lapply(pred_google, function(x) {
as.data.frame(forecast::accuracy(
x, google1516))
}) |>
bind_rows() |>
select(2,3,5,6) |>
slice(2,4,6)
accur_google$Mètode <- c("Mitjana", "Naif", "Drift")
accur_google[,c(5,1:4)] |>
flextable::flextable() |>
flextable::set_caption("Diferents mesures de la precisió de les previsions respecte a les dades reals")
Mètode | RMSE | MAE | MAPE | MASE |
|---|---|---|---|---|
Mitjana | 119.08847 | 117.78367 | 16.324624 | 16.524118 |
Naif | 43.27748 | 39.54579 | 5.559824 | 5.547962 |
Drift | 53.36301 | 48.98572 | 6.883532 | 6.872310 |
Els resultats anterior els hem obtingut amb unes funcions
d’R ja consolidades. Tanmateix ara amb le llibreries
fable i fabletools és possibles estalviar molt
de codi, tot treballant amb format tidy.
google_fit <- google_2015 |>
fabletools::model(
Mean = MEAN(Close),
`Naïve` = NAIVE(Close),
Drift = RW(Close ~ drift())
)
google_jan_2016 <- google_stock %>% filter(Date >="2016-01-01" & Date <= "2016-01-31")
google_fc <- google_fit |>
fabletools::forecast(google_jan_2016)
google_fc |>
fabletools::autoplot(bind_rows(google_2015, google_jan_2016),
level = NULL) +
labs(y = "$US",
title = "Google closing stock prices from Jan 2015") +
guides(colour = guide_legend(title = "Forecast"))
fabletools::accuracy(google_fc, google_stock) |> select(1,5,6,8,9) |>
flextable::flextable() |>
flextable::set_caption("Taula 1: avaluació de la precisió amb diferent mesures")
.model | RMSE | MAE | MAPE | MASE |
|---|---|---|---|---|
Drift | 53.06958 | 49.82414 | 6.992133 | 6.989934 |
Mean | 118.03221 | 116.94525 | 16.235169 | 16.406494 |
Naïve | 43.43152 | 40.38421 | 5.672675 | 5.665586 |
Les mesures anteriors mesuren totes la precisió de la previsió puntual. Quan avaluem les previsions distribucionals, hem d’utilitzar altres mesures.
Considereu l’exemple del preu de les accions de Google de la secció anterior. La figura 5.23 mostra un interval de predicció del 80% per a les previsions del mètode naïf.
google_fc |>
dplyr::filter(.model == "Naïve") |>
autoplot(bind_rows(google_2015, google_jan_2016), level=80)+
labs(y = "$US",
title = "Google closing stock prices")
El límit inferior d’aquest interval de predicció dóna el percentil 10 (o quantil 0,1) de la distribució de la previsió, de manera que esperaríem que el valor real estigués per sota del límit inferior aproximadament el 10% del temps i per sobre del límit inferior aproximadament el 90% del temps. Quan comparem el valor real amb aquest percentil, hem de tenir en compte el fet que és més probable que estigui per sobre que per sota.
De manera més general, suposem que estem interessats en la previsió quantílica (és a dir, el valor ajustat) amb probabilitat \(p\) en el temps futur \(t\), i denotem això per \(f_{p,t}\). És a dir, esperem que l’observació \(y_t\) sigui inferior a \(f_{p,t}\) amb probabilitat \(p\). Per exemple, el percentil 10 seria \(f_{0.10,t}\). Si \(y_t\) denota l’observació en el moment \(t\), aleshores la puntuació quantílica és
\[ Q_{p,t} = \begin{cases} 2(1 - p) \big(f_{p,t} - y_{t}\big), & \text{if $y_{t} < f_{p,t}$}\\ 2p \big(y_{t} - f_{p,t}\big), & \text{if $y_{t} \ge f_{p,t}$} \end{cases} \]
Això de vegades s’anomena “funció de pèrdua de pinball” perquè un gràfic sembla la trajectòria d’una bola sobre una taula de pinball. El multiplicador de 2 sovint s’omet, però incloure’l facilita una mica la interpretació. Un valor baix de \(Q_{p,t}\) indica una millor estimació del quantil.
La puntuació quantílica es pot interpretar com un error absolut. De fet, quan \(p = 0,5\), la puntuació quantil \(Q_{0.5,t}\) és la mateixa que l’error absolut. Per a altres valors de \(p\), l’“error” \((y_t − f_{p,t})\) es pondera per tenir en compte la probabilitat que sigui positiu o negatiu. Si \(p > 0,5\), \(Q_p,t\) dóna una penalització més greu quan l’observació és més gran que el quantil estimat que quan l’observació és menor que el quantil estimat. El contrari és cert per a \(p < 0,5\).
A la figura 5.23, la previsió quantílica del \(10%\) amb un pas d’antelació (per al 4 de gener de 2016) és \(f_{0,1,t} = 744,54\) i el valor observat és \(y_t = 741,84\). Aleshores \[ Q_{0.1,t} = 2(1-0.1) (744.54 - 741.84) = 4.86. \]
Això es calcula fàcilment utilitzant accuracy() amb la
funció quantile_score(), ambdues del paquet
fabletools:::
google_fc |>
filter(.model == "Naïve", Date == "2016-01-04") |>
fabletools::accuracy(google_stock,
list(qs = fabletools::quantile_score),
probs=0.10)
## # A tibble: 1 × 4
## .model Symbol .type qs
## <chr> <chr> <chr> <dbl>
## 1 Naïve GOOG Test 4.86
Sovint és interessant avaluar un interval de predicció, en lloc d’uns quants quantils, i la puntuació de Winkler proposada per Winkler (1972) està dissenyada per a aquest propòsit. Si l’interval de predicció del \(100(1−α)\%\) en el temps \(t\) ve donat per \([ℓ_{α,t},u_{α,t}]\), aleshores la puntuació de Winkler es defineix com la longitud de l’interval més una penalització si l’observació està fora de l’interval
Per a les observacions que cauen dins de l’interval, la puntuació de Winkler és simplement la longitud de l’interval. Per tant, les puntuacions baixes s’associen amb intervals estrets. Tanmateix, si l’observació cau fora de l’interval, s’aplica la penalització, i la penalització és proporcional a la distància que l’observació està fora de l’interval.
google_fc |>
filter(.model == "Naïve", Date == "2016-01-04") |>
accuracy(google_stock,
list(winkler = winkler_score), level = 80)
## # A tibble: 1 × 4
## .model Symbol .type winkler
## <chr> <chr> <chr> <dbl>
## 1 Naïve GOOG Test 55.7
Sovint ens interessa tota la distribució de previsió, en lloc de quantils o intervals de predicció particulars. En aquest cas, podem fer la mitjana de les puntuacions de quantils sobre tots els valors de p per obtenir la puntuació de probabilitat classificada contínua o CRPS (Gneiting & Katzfuss, 2014).
A l’exemple del preu de les accions de Google, podem calcular el valor mitjà de CRPS per a tots els dies del conjunt de prova. Un valor CRPS és una mica com un error absolut ponderat calculat a partir de tota la distribució de la previsió, on la ponderació té en compte les probabilitats.
google_fc |>
accuracy(google_stock, list(crps = CRPS))
## # A tibble: 3 × 4
## .model Symbol .type crps
## <chr> <chr> <chr> <dbl>
## 1 Drift GOOG Test 33.5
## 2 Mean GOOG Test 76.7
## 3 Naïve GOOG Test 26.5
Igual que amb les previsions puntuals, és útil poder comparar la precisió de la previsió distribucional de diversos mètodes entre sèries a diferents escales. Per a les previsions puntuals, hem utilitzat errors escalats per a aquest propòsit. Un altre enfocament és utilitzar puntuacions d’habilitat. Aquestes es poden utilitzar tant per a la precisió de la previsió puntual com per a la precisió de la previsió distribucional.
Amb les puntuacions d’habilitat, calculem una mesura de precisió de la previsió en relació amb algun mètode de referència. Per exemple, si utilitzem el mètode naïf com a referència i també calculem previsions mitjançant el mètode de deriva, podem calcular la puntuació d’habilitat CRPS del mètode de deriva en relació amb el mètode naïf com a
\[ \frac{\text{CRPS}_{\text{Naïve}} - \text{CRPS}_{\text{Drift}}}{\text{CRPS}_{\text{Naïve}}}. \]
google_fc |>
accuracy(google_stock, list(skill = skill_score(CRPS)))
## # A tibble: 3 × 4
## .model Symbol .type skill
## <chr> <chr> <chr> <dbl>
## 1 Drift GOOG Test -0.266
## 2 Mean GOOG Test -1.90
## 3 Naïve GOOG Test 0
La funció skill_score() sempre calcularà el CRPS per a
les previsions de referència adequades, fins i tot si aquestes no
s’inclouen a l’objecte fable. Quan les dades són
estacionals, el punt de referència utilitzat és el mètode naïf
estacional en lloc del mètode naïf. Per garantir que s’utilitzen les
mateixes dades d’entrenament per a les previsions de referència,
és important que les dades proporcionades a la funció
accuracy() comencin al mateix temps que les dades
d’entrenament.
La funció skill_score() es pot utilitzar amb
qualsevol mesura de precisió. Per exemple,
skill_score(MSE) proporciona una manera de comparar els
valors de MSE entre diverses sèries. Tanmateix, és important que
el conjunt de test sigui prou gran per permetre un
càlcul fiable de la mesura d’error, especialment al
denominador. Per aquest motiu, MASE o
RMSSE sovint són mesures sense escala preferibles per a
la precisió de la previsió puntual.
Una versió més sofisticada dels conjunts d’entrenament/test és la validació creuada (cross validation) de sèries temporals. En aquest procediment, hi ha una sèrie de conjunts de proves, cadascun format per una única observació. El conjunt d’entrenament corresponent només consta d’observacions que es van produir abans de l’observació que forma el conjunt de prova. Per tant, no es poden utilitzar observacions futures per construir la previsió. Com que no és possible obtenir una previsió fiable basada en un petit conjunt d’entrenament, les observacions més primerenques no es consideren com a conjunts de prova.
El diagrama següent il·lustra la sèrie de conjunts d’entrenament i proves, on les observacions blaves formen els conjunts d’entrenament i les observacions taronges formen els conjunts de prova.
Diagrama 1: From https://otexts.com/fpp3/tscv.html
La precisió de la previsió es calcula fent la mitjana dels conjunts de prova. Aquest procediment de vegades es coneix com a “avaluació sobre un origen de previsió en moviment” perquè l’“origen” en què es basa la previsió es mou en el temps.
Amb les previsions de sèries temporals, és possible que les
previsions d’un sol pas (h=1) no siguin tan rellevants com
les de diversos passos. En aquest cas, el procediment de validació
creuada basat en un origen de previsió en moviment es pot modificar per
permetre l’ús d’errors de diversos passos. Suposem que estem interessats
en models que produeixen bones previsions a 4 passos. A continuació es
mostra el diagrama corresponent a continuació.
Diagrama 2: From https://otexts.com/fpp3/tscv.html
A l’exemple següent, comparem la precisió de la previsió obtinguda
mitjançant la validació creuada de sèries temporals amb la precisió
residual. La funció stretch_tsibble() s’utilitza per crear
molts conjunts d’entrenament. En aquest exemple, comencem amb un conjunt
d’entrenament de longitud .init=3 i augmentem la mida dels
conjunts d’entrenament successius en .step=1.
google_2015_tr <- google_2015 |>
stretch_tsibble(.init = 3, .step = 1) |>
relocate(Date, Symbol, .id)
head(google_2015_tr)
## # A tsibble: 6 x 10 [1]
## # Key: Symbol, .id [2]
## Date Symbol .id Open High Low Close Adj_Close Volume day
## <date> <chr> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int>
## 1 2015-01-02 GOOG 1 526. 528. 521. 522. 522. 1447600 1
## 2 2015-01-05 GOOG 1 520. 521. 510. 511. 511. 2059800 2
## 3 2015-01-06 GOOG 1 512. 513. 498. 499. 499. 2899900 3
## 4 2015-01-02 GOOG 2 526. 528. 521. 522. 522. 1447600 1
## 5 2015-01-05 GOOG 2 520. 521. 510. 511. 511. 2059800 2
## 6 2015-01-06 GOOG 2 512. 513. 498. 499. 499. 2899900 3
dim(google_2015_tr)
## [1] 31875 10
La columna .idproporciona una nova clau que indica els
diferents conjunts d’entrenament. La funció accuracy() es
pot utilitzar per avaluar la precisió de la previsió en els conjunts
d’entrenament.
# TSCV accuracy
a <- google_2015_tr |>
model(RW(Close ~ drift())) |>
forecast(h = 1) |>
accuracy(google_2015)
a[,-1] %>%
select(2,4,5,7,8) %>%
mutate(.type= case_match(.type,
"Test"~"Cross validation",
.default = as.character(.type))) %>%
flextable::flextable() %>%
flextable::set_caption("Taula 2: Avaluació de la precisió de la 'Validació creuada', amb diferent mesures")
.type | RMSE | MAE | MAPE | MASE |
|---|---|---|---|---|
Cross validation | 11.26819 | 7.26124 | 1.194024 | 1.018695 |
Com era d’esperar, les mesures de precisió dels residus són més petites que les que hem vist a la Taula 1, ja que les “previsions” corresponents es basen en un model ajustat a tot el conjunt de dades, en lloc de ser previsions genuines.
Una bona manera d’escollir el millor model de previsió és trobar el model amb l’RMSE més petit calculat mitjançant la validació creuada de sèries temporals.