Você deve usar o pacote de previsão , que suporta todos esses modelos (e mais) e facilita o encaixe deles:
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)
Eu recomendaria não suavizar os dados antes de ajustar seu modelo. Seu modelo tentará inerentemente suavizar os dados; portanto, a pré-suavização apenas complica as coisas.
Edite com base em novos dados:
Na verdade, parece que o arima é um dos piores modelos que você pode escolher para este treinamento e conjunto de testes.
Salvei seus dados em uma chamada de arquivo coil.csv
, carreguei-os no R e os dividi em um conjunto de treinamento e teste:
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))
Em seguida, ajustei vários modelos de séries temporais: arima, suavização exponencial, rede neural, tbats, morcegos, decomposição sazonal e séries temporais estruturais:
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)
)
Então eu fiz algumas previsões e comparei com o conjunto de testes. Incluí uma previsão ingênua que sempre prevê uma linha horizontal plana:
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 você pode ver, o modelo Arima erra a tendência, mas eu meio que gosto da aparência do "Modelo estrutural básico"
Por fim, medi a precisão de cada modelo no conjunto de testes:
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
As métricas utilizadas são descritas em Hyndman, RJ e Athanasopoulos, G. (2014) "Forecasting: princípios e práticas" , que também são os autores do pacote de previsão. Eu recomendo que você leia o texto deles: está disponível gratuitamente online. A série temporal estrutural é o melhor modelo para várias métricas, incluindo MASE, que é a métrica que eu prefiro para a seleção de modelos.
Uma pergunta final é: o modelo estrutural teve sorte com este conjunto de testes? Uma maneira de avaliar isso é olhar para os erros do conjunto de treinamento. Os erros do conjunto de treinamento são menos confiáveis do que os erros do conjunto de teste (porque eles podem ter excesso de ajuste), mas, neste caso, o modelo estrutural ainda se destaca:
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
(Observe que a rede neural superajustada, executando excelente no conjunto de treinamento e mal no conjunto de teste)
Por fim, seria uma boa idéia validar cruzadamente todos esses modelos, talvez treinando em 2008-2009 / testando em 2010, treinando em 2008-2010 / testando em 2011, treinando em 2008-2011 / testando em 2012, treinando em 2008-2012 / testes em 2013, e a média de erros em todos esses períodos. Se você deseja seguir esse caminho, eu tenho um pacote parcialmente completo para validação cruzada de modelos de séries temporais no github que eu adoraria que você experimentasse e me desse feedback / solicitações sobre:
devtools::install_github('zachmayer/cv.ts')
library(cv.ts)
Edit 2: Vamos ver se me lembro de como usar meu próprio pacote!
Primeiro, instale e carregue o pacote no github (veja acima). Em seguida, valide cruzadamente alguns modelos (usando o conjunto de dados 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)
(Observe que reduzi a flexibilidade do modelo de rede neural, para tentar evitar que ele se encaixe demais)
Depois de ajustar os modelos, podemos compará-los pelo MAPE (o cv.ts ainda não suporta o 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
Ai. Parece que nossa previsão estrutural teve sorte. A longo prazo, a ingênua previsão faz as melhores previsões, com média em um horizonte de 12 meses (o modelo arima ainda é um dos piores modelos). Vamos comparar os modelos em cada um dos 12 horizontes de previsão e ver se algum deles superou o modelo ingênuo:
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 maneira reveladora, o modelo de suavização exponencial está sempre escolhendo o modelo ingênuo (a linha laranja e a linha azul se sobrepõem 100%). Em outras palavras, a ingênua previsão de "preços da bobina no próximo mês será igual à da bobina deste mês" é mais precisa (em quase todos os horizontes previstos) do que 7 modelos de séries temporais extremamente sofisticados. A menos que você tenha alguma informação secreta que o mercado de bobinas ainda não conhece, vencer a ingênua previsão de preço da bobina será extremamente difícil .
Nunca é a resposta que alguém deseja ouvir, mas se a precisão da previsão for o seu objetivo, use o modelo mais preciso. Use o modelo ingênuo.