Debe usar el paquete de pronóstico , que admite todos estos modelos (y más) y hace que ajustarlos sea muy fácil:
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)
Aconsejaría no suavizar los datos antes de ajustar su modelo. Su modelo intentará inherentemente suavizar los datos, por lo que el preajuste solo complica las cosas.
Edición basada en nuevos datos:
En realidad, parece que Arima es uno de los peores modelos que podría elegir para este conjunto de entrenamiento y prueba.
Guarde sus datos en una llamada de archivo coil.csv
, los cargué en R y los dividí en un conjunto de entrenamiento y prueba:
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))
A continuación, me ajusto a un montón de modelos de series de tiempo: arima, suavizado exponencial, red neuronal, tbats, murciélagos, descomposición estacional y series de tiempo estructurales:
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)
)
Luego hice algunos pronósticos y los comparé con el conjunto de prueba. Incluí un pronóstico ingenuo que siempre predice una línea plana y horizontal:
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')
}
Como puede ver, el modelo arima se equivoca en la tendencia, pero me gusta el aspecto del "Modelo estructural básico"
Finalmente, medí la precisión de cada modelo en el conjunto de prueba:
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
Las métricas utilizadas se describen en Hyndman, RJ y Athanasopoulos, G. (2014) "Predicción: principios y práctica" , quienes también son los autores del paquete de predicción. Le recomiendo que lea su texto: está disponible de forma gratuita en línea. La serie de tiempo estructural es el mejor modelo por varias métricas, incluida MASE, que es la métrica que tiendo a preferir para la selección del modelo.
Una última pregunta es: ¿tuvo suerte el modelo estructural en este conjunto de pruebas? Una forma de evaluar esto es mirar los errores del conjunto de entrenamiento. Los errores del conjunto de entrenamiento son menos confiables que los errores del conjunto de prueba (porque pueden ser demasiado ajustados), pero en este caso el modelo estructural sigue siendo el primero:
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
(Tenga en cuenta que la red neuronal se sobreajusta, con un rendimiento excelente en el conjunto de entrenamiento y mal en el conjunto de prueba)
Finalmente, sería una buena idea hacer una validación cruzada de todos estos modelos, tal vez entrenando en 2008-2009 / probando en 2010, entrenando en 2008-2010 / probando en 2011, entrenando en 2008-2011 / probando en 2012, entrenando en 2008-2012 / pruebas en 2013, y promediando errores en todos estos períodos de tiempo. Si deseas seguir esa ruta, tengo un paquete parcialmente completo para la validación cruzada de modelos de series temporales en github que me encantaría que pruebe y me envíe comentarios / solicitudes de extracción sobre:
devtools::install_github('zachmayer/cv.ts')
library(cv.ts)
Edición 2: ¡Veamos si recuerdo cómo usar mi propio paquete!
En primer lugar, instale y cargue el paquete desde github (ver arriba). Luego, realice una validación cruzada de algunos modelos (utilizando el conjunto de datos 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)
(Tenga en cuenta que reduje la flexibilidad del modelo de red neuronal, para tratar de ayudar a evitar que se ajuste demasiado)
Una vez que hayamos ajustado los modelos, podemos compararlos por MAPE (cv.ts aún no admite 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
Ay. Parece que nuestro pronóstico estructural tuvo suerte. A largo plazo, el pronóstico ingenuo hace los mejores pronósticos, promediados en un horizonte de 12 meses (el modelo arima sigue siendo uno de los peores modelos). Comparemos los modelos en cada uno de los 12 horizontes de pronóstico y veamos si alguno de ellos supera al modelo 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")
)
De manera reveladora, el modelo de suavizado exponencial siempre elige el modelo ingenuo (la línea naranja y la línea azul se superponen al 100%). En otras palabras, el pronóstico ingenuo de "los precios de la bobina del próximo mes será el mismo que los precios de la bobina de este mes" es más preciso (en casi todos los horizontes de pronóstico) que 7 modelos de series temporales extremadamente sofisticados. A menos que tenga alguna información secreta que el mercado de bobinas aún no conoce, superar el ingenuo pronóstico del precio de la bobina será extremadamente difícil .
Nunca es la respuesta que alguien quiere escuchar, pero si su objetivo es la precisión del pronóstico, debe usar el modelo más preciso. Usa el modelo ingenuo.