È necessario utilizzare il pacchetto di previsione , che supporta tutti questi modelli (e altro) e semplifica l'adattamento:
library(forecast)
x <- AirPassengers
mod_arima <- auto.arima(x, ic='aicc', stepwise=FALSE)
mod_exponential <- ets(x, ic='aicc', restrict=FALSE)
mod_neural <- nnetar(x, p=12, size=25)
mod_tbats <- tbats(x, ic='aicc', seasonal.periods=12)
par(mfrow=c(4, 1))
plot(forecast(mod_arima, 12), include=36)
plot(forecast(mod_exponential, 12), include=36)
plot(forecast(mod_neural, 12), include=36)
plot(forecast(mod_tbats, 12), include=36)
Vorrei sconsigliare di uniformare i dati prima di adattare il modello. Il tuo modello cercherà intrinsecamente di lisciare i dati, quindi il pre-smoothing complica semplicemente le cose.
Modifica in base a nuovi dati:
In realtà sembra che Arima sia uno dei peggiori modelli che potresti scegliere per questo set di allenamento e test.
Ho salvato i tuoi dati in una chiamata di file coil.csv
, li ho caricati in R e li ho divisi in un set di addestramento e test:
library(forecast)
dat <- read.csv('~/coil.csv')
x <- ts(dat$Coil, start=c(dat$Year[1], dat$Month[1]), frequency=12)
test_x <- window(x, start=c(2012, 3))
x <- window(x, end=c(2012, 2))
Quindi inserirò un sacco di modelli di serie storiche: arima, livellamento esponenziale, rete neurale, pipistrelli, pipistrelli, decomposizione stagionale e serie temporali strutturali:
models <- list(
mod_arima = auto.arima(x, ic='aicc', stepwise=FALSE),
mod_exp = ets(x, ic='aicc', restrict=FALSE),
mod_neural = nnetar(x, p=12, size=25),
mod_tbats = tbats(x, ic='aicc', seasonal.periods=12),
mod_bats = bats(x, ic='aicc', seasonal.periods=12),
mod_stl = stlm(x, s.window=12, ic='aicc', robust=TRUE, method='ets'),
mod_sts = StructTS(x)
)
Quindi ho fatto alcune previsioni e confrontato con il set di test. Ho incluso una previsione ingenua che prevede sempre una linea piatta e orizzontale:
forecasts <- lapply(models, forecast, 12)
forecasts$naive <- naive(x, 12)
par(mfrow=c(4, 2))
for(f in forecasts){
plot(f)
lines(test_x, col='red')
}
Come puoi vedere, il modello Arima sbaglia la tendenza, ma mi piace un po 'l'aspetto del "Modello strutturale di base"
Infine, ho misurato l'accuratezza di ciascun modello sul set di test:
acc <- lapply(forecasts, function(f){
accuracy(f, test_x)[2,,drop=FALSE]
})
acc <- Reduce(rbind, acc)
row.names(acc) <- names(forecasts)
acc <- acc[order(acc[,'MASE']),]
round(acc, 2)
ME RMSE MAE MPE MAPE MASE ACF1 Theil's U
mod_sts 283.15 609.04 514.46 0.69 1.27 0.10 0.77 1.65
mod_bats 65.36 706.93 638.31 0.13 1.59 0.12 0.85 1.96
mod_tbats 65.22 706.92 638.32 0.13 1.59 0.12 0.85 1.96
mod_exp 25.00 706.52 641.67 0.03 1.60 0.12 0.85 1.96
naive 25.00 706.52 641.67 0.03 1.60 0.12 0.85 1.96
mod_neural 81.14 853.86 754.61 0.18 1.89 0.14 0.14 2.39
mod_arima 766.51 904.06 766.51 1.90 1.90 0.14 0.73 2.48
mod_stl -208.74 1166.84 1005.81 -0.52 2.50 0.19 0.32 3.02
Le metriche utilizzate sono descritte in Hyndman, RJ e Athanasopoulos, G. (2014) "Previsioni: principi e pratica" , che sono anche gli autori del pacchetto di previsioni. Consiglio vivamente di leggere il loro testo: è disponibile gratuitamente online. La serie temporale strutturale è il modello migliore per diverse metriche, tra cui MASE, che è la metrica che tendo a preferire per la selezione del modello.
Un'ultima domanda è: il modello strutturale è stato fortunato in questo set di test? Un modo per valutare questo è guardare gli errori impostati nella formazione. Gli errori del set di addestramento sono meno affidabili degli errori del set di test (perché possono essere troppo adatti), ma in questo caso il modello strutturale risulta ancora in primo piano:
acc <- lapply(forecasts, function(f){
accuracy(f, test_x)[1,,drop=FALSE]
})
acc <- Reduce(rbind, acc)
row.names(acc) <- names(forecasts)
acc <- acc[order(acc[,'MASE']),]
round(acc, 2)
ME RMSE MAE MPE MAPE MASE ACF1 Theil's U
mod_sts -0.03 0.99 0.71 0.00 0.00 0.00 0.08 NA
mod_neural 3.00 1145.91 839.15 -0.09 2.25 0.16 0.00 NA
mod_exp -82.74 1915.75 1359.87 -0.33 3.68 0.25 0.06 NA
naive -86.96 1936.38 1386.96 -0.34 3.75 0.26 0.06 NA
mod_arima -180.32 1889.56 1393.94 -0.74 3.79 0.26 0.09 NA
mod_stl -38.12 2158.25 1471.63 -0.22 4.00 0.28 -0.09 NA
mod_bats 57.07 2184.16 1525.28 0.00 4.07 0.29 -0.03 NA
mod_tbats 62.30 2203.54 1531.48 0.01 4.08 0.29 -0.03 NA
(Si noti che la rete neurale si sovrappone, con prestazioni eccellenti sul set di allenamento e scarsamente sul set di test)
Infine, sarebbe una buona idea convalidare in modo incrociato tutti questi modelli, magari allenandosi su 2008-2009 / test sul 2010, training su 2008-2010 / test sul 2011, training su 2008-2011 / test sul 2012, training nel periodo 2008-2012 / test nel 2013 e errori medi in tutti questi periodi di tempo. Se desideri seguire questa strada, ho un pacchetto parzialmente completo per la validazione incrociata di modelli di serie temporali su github che ti piacerebbe provare e darmi feedback / richieste di pull su:
devtools::install_github('zachmayer/cv.ts')
library(cv.ts)
Modifica 2: vediamo se ricordo come usare il mio pacchetto!
Prima di tutto, installa e carica il pacchetto da github (vedi sopra). Quindi convalidare in modo incrociato alcuni modelli (utilizzando il set di dati completo):
library(cv.ts)
x <- ts(dat$Coil, start=c(dat$Year[1], dat$Month[1]), frequency=12)
ctrl <- tseriesControl(stepSize=1, maxHorizon=12, minObs=36, fixedWindow=TRUE)
models <- list()
models$arima = cv.ts(
x, auto.arimaForecast, tsControl=ctrl,
ic='aicc', stepwise=FALSE)
models$exp = cv.ts(
x, etsForecast, tsControl=ctrl,
ic='aicc', restrict=FALSE)
models$neural = cv.ts(
x, nnetarForecast, tsControl=ctrl,
nn_p=6, size=5)
models$tbats = cv.ts(
x, tbatsForecast, tsControl=ctrl,
seasonal.periods=12)
models$bats = cv.ts(
x, batsForecast, tsControl=ctrl,
seasonal.periods=12)
models$stl = cv.ts(
x, stl.Forecast, tsControl=ctrl,
s.window=12, ic='aicc', robust=TRUE, method='ets')
models$sts = cv.ts(x, stsForecast, tsControl=ctrl)
models$naive = cv.ts(x, naiveForecast, tsControl=ctrl)
models$theta = cv.ts(x, thetaForecast, tsControl=ctrl)
(Si noti che ho ridotto la flessibilità del modello di rete neurale, per cercare di evitare che si adatti eccessivamente)
Una volta che abbiamo adattato i modelli, possiamo confrontarli con MAPE (cv.ts non supporta ancora MASE):
res_overall <- lapply(models, function(x) x$results[13,-1])
res_overall <- Reduce(rbind, res_overall)
row.names(res_overall) <- names(models)
res_overall <- res_overall[order(res_overall[,'MAPE']),]
round(res_overall, 2)
ME RMSE MAE MPE MAPE
naive 91.40 1126.83 961.18 0.19 2.40
ets 91.56 1127.09 961.35 0.19 2.40
stl -114.59 1661.73 1332.73 -0.29 3.36
neural 5.26 1979.83 1521.83 0.00 3.83
bats 294.01 2087.99 1725.14 0.70 4.32
sts -698.90 3680.71 1901.78 -1.81 4.77
arima -1687.27 2750.49 2199.53 -4.23 5.53
tbats -476.67 2761.44 2428.34 -1.23 6.10
Ahia. Sembrerebbe che le nostre previsioni strutturali siano state fortunate. A lungo termine, la previsione ingenua fornisce le migliori previsioni, calcolate in media in un orizzonte di 12 mesi (il modello arima è ancora uno dei modelli peggiori). Confrontiamo i modelli in ciascuno dei 12 orizzonti di previsione e vediamo se qualcuno di loro ha mai battuto il modello ingenuo:
library(reshape2)
library(ggplot2)
res <- lapply(models, function(x) x$results$MAPE[1:12])
res <- data.frame(do.call(cbind, res))
res$horizon <- 1:nrow(res)
res <- melt(res, id.var='horizon', variable.name='model', value.name='MAPE')
res$model <- factor(res$model, levels=row.names(res_overall))
ggplot(res, aes(x=horizon, y=MAPE, col=model)) +
geom_line(size=2) + theme_bw() +
theme(legend.position="top") +
scale_color_manual(values=c(
"#1f78b4", "#ff7f00", "#33a02c", "#6a3d9a",
"#e31a1c", "#b15928", "#a6cee3", "#fdbf6f",
"#b2df8a")
)
In modo evidente, il modello di livellamento esponenziale sceglie sempre il modello ingenuo (la linea arancione e la linea blu si sovrappongono al 100%). In altre parole, l'ingenua previsione dei "prezzi delle bobine del mese prossimo sarà la stessa dei prezzi delle bobine di questo mese" è più accurata (in quasi tutti gli orizzonti delle previsioni) rispetto a 7 modelli di serie temporali estremamente sofisticati. A meno che tu non abbia alcune informazioni segrete che il mercato delle bobine non conosce già, battere l'ingenua previsione dei prezzi delle bobine sarà estremamente difficile .
Non è mai la risposta che qualcuno vuole sentire, ma se la precisione delle previsioni è il tuo obiettivo, dovresti usare il modello più accurato. Usa il modello ingenuo.