Procedimento e métodos de análise de séries temporais usando R

13

Estou trabalhando em um pequeno projeto em que estamos tentando prever os preços de commodities (petróleo, alumínio, estanho, etc.) nos próximos 6 meses. Eu tenho 12 variáveis ​​para prever e tenho dados de abril de 2008 a maio de 2013.

Como devo fazer previsões? Eu fiz o seguinte:

  • Dados importados como um conjunto de dados do Timeseries
  • A sazonalidade de todas as variáveis ​​tende a variar com a Tendência, então eu vou para o modelo multiplicativo.
  • Peguei o log da variável para converter em modelo aditivo
  • Para cada variável decompôs os dados usando STL

Estou planejando usar a suavização exponencial de Holt Winters, o ARIMA e a rede neural para prever. Dividi os dados como treinamento e teste (80, 20). Planejando escolher o modelo com menos MAE, MPE, MAPE e MASE.

Eu estou fazendo a coisa certa?

Também uma pergunta que eu tinha era: antes de passar para o ARIMA ou para a rede neural, devo suavizar os dados? Se sim, usando o que? Os dados mostram sazonalidade e tendência.

EDITAR:

Anexando a plotagem e os dados das séries temporais insira a descrição da imagem aqui

Year  <- c(2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2009, 2009, 
           2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2010, 
           2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 
           2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 
           2011, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 
           2012, 2012, 2013, 2013)
Month <- c(4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 
           12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 
           8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2) 
Coil  <- c(44000, 44500, 42000, 45000, 42500, 41000, 39000, 35000, 34000, 
           29700, 29700, 29000, 30000, 30000, 31000, 31000, 33500, 33500, 
           33000, 31500, 34000, 35000, 35000, 36000, 38500, 38500, 35500, 
           33500, 34500, 36000, 35500, 34500, 35500, 38500, 44500, 40700, 
           40500, 39100, 39100, 39100, 38600, 39500, 39500, 38500, 39500, 
           40000, 40000, 40500, 41000, 41000, 41000, 40500, 40000, 39300, 
           39300, 39300, 39300, 39300, 39800)
coil <- data.frame(Year = Year, Month = Month, Coil = Coil)

EDIT 2: Uma pergunta, você pode me dizer se meus dados têm alguma sazonalidade ou tendência? E também, por favor, me dê algumas dicas sobre como identificá-las. insira a descrição da imagem aqui insira a descrição da imagem aqui

Niranjan Sonachalam
fonte
2
Se você está tentando prever grupos de mercadorias, como vários tipos de metal (aço A, aço B, aço C etc.), pode valer a pena testar a existência de cointegração. Por exemplo, algo como isto: Os preços do aço se movem juntos? . Isso pode fornecer previsões melhores de 6 meses (médio / longo prazo) do que métodos univariados, mas esse é, de fato, um jogo difícil que você está tentando jogar. ;-)
Graeme Walsh
1
Como aponta o @GraemeWalsh, a extrapolação univariada de tendências pode não ser ideal para esse tipo de dados. Existem métodos bem estabelecidos na literatura para prever o preço do petróleo e do aço que talvez valha a pena explorar.
forecaster
1
Você pode postar novas edições como uma pergunta separada? Como você já aceitou uma resposta, as novas perguntas podem não receber a atenção necessária. Ao observar os dados, posso dizer que nenhum deles tem tendências ou padrões sazonais. Como observado no meu post abaixo, parece que a tendência de queda antes de 2009 é um fenômeno macroeconômico como a recessão?
forecaster
@ previsão, @ GraemeWalsh: Obrigado. Estou planejando usar o método de cointegração usando testes do ADF.
Niranjan Sonachalam 04/03
1
Você forneceu o contexto em sua nova pergunta e isso faz mais sentido agora. Portanto, a queda antes de 2009 foi de fato alguns fenômenos macroeconômicos. Nesse exemplo utilize o método passeio aleatório com deriva ou (Arima (0,1,0) + deriva
previsor

Respostas:

21

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.

insira a descrição da imagem aqui

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')
}

insira a descrição da imagem aqui

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")
    )

modelo comparar

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.

Zach
fonte
É interessante observar as diferenças entre esses modelos. NNAR em particular parece diferente. Dado que este é um conjunto de dados famoso (e historicamente antigo, acredito), sabe-se qual é o correto e se um tipo de modelo tem desempenho superior? (Nb, eu sei relativamente pouco sobre TS.)
gung - Reinstate Monica
@gung A melhor maneira de fazer isso seria separar um conjunto de validação e testar o modelo. Note-se que o modelo que faz as melhores previsões de curto prazo pode não ser o modelo que faz as melhores previsões a longo prazo ....
Zach
Muito obrigado, mas não estou recebendo boas previsões para o conjunto de dados acima (acho que estou perdendo uma etapa importante aqui). Você pode por favor deixe-me saber se eu estou faltando alguma coisa
Niranjan Sonachalam
@Niranjan Você pode nos dizer / mostrar como você conclui que não está recebendo uma boa previsão?
previsor
@forecaster: Por favor, verifique aqui pbrd.co/1DRPRsq . Eu sou novo na previsão. Entre em contato se precisar de informações específicas. Eu tentei com o modelo Arima.
Niranjan Sonachalam 04/03/2015
12

A abordagem que você adotou é razoável. Se você é novo na previsão, recomendo os seguintes livros:

  1. Métodos e aplicações de previsão por Makridakis, Wheelright e Hyndman
  2. Previsão: princípios e práticas de Hyndman e Athanasopoulos.

O primeiro livro é um clássico que eu recomendo fortemente. O segundo livro é um livro de código aberto que você pode consultar para métodos de previsão e como é aplicado usando a previsão deR pacotes de software de código aberto . Ambos os livros fornecem bons antecedentes sobre os métodos que usei. Se você é sério em relação à previsão, eu recomendaria Princípios de Previsão por Armstrong, que é uma coleção de uma tremenda quantidade de pesquisas na previsão de que os profissionais podem achar isso muito útil.

Chegando ao seu exemplo específico de bobina, ele me lembra um conceito de previsibilidade que a maioria dos livros didáticos geralmente ignora. Algumas séries, como a sua, simplesmente não podem ser previstas porque são menos padronizadas, pois não apresentam padrões de tendência ou sazonais ou qualquer variação sistemática. Nesse caso, eu categorizaria uma série como menos previsível. Antes de me aventurar nos métodos de extrapolação, eu examinava os dados e fazia a pergunta: minha série é previsível? Neste exemplo específico, uma extrapolação simples, como a previsão de caminhada aleatória, que usa o último valor da previsão, é mais precisa .

Também um comentário adicional sobre a rede neural: sabe-se que as redes neurais falham em competições empíricas . Eu tentaria métodos estatísticos tradicionais para séries temporais antes de tentar usar redes neurais para tarefas de previsão de séries temporais.

Tentei modelar seus dados R's forecast package, espero que os comentários sejam auto-explicativos.

coil <- c(44000, 44500, 42000, 45000, 42500, 41000, 39000, 35000, 34000, 
          29700, 29700, 29000, 30000, 30000, 31000, 31000, 33500, 33500, 
          33000, 31500, 34000, 35000, 35000, 36000, 38500, 38500, 35500, 
          33500, 34500, 36000, 35500, 34500, 35500, 38500, 44500, 40700, 
          40500, 39100, 39100, 39100, 38600, 39500, 39500, 38500, 39500, 
          40000, 40000, 40500, 41000, 41000, 41000, 40500, 40000, 39300, 
          39300, 39300, 39300, 39300, 39800)


coilts <- ts(coil,start=c(2008,4),frequency=12)

library("forecast")

# Data for modeling
coilts.mod <- window(coilts,end = c(2012,3))

#Data for testing
coil.test <- window(coilts,start=c(2012,4))

# Model using multiple methods - arima, expo smooth, theta, random walk, structural time series

#arima
coil.arima <- forecast(auto.arima(coilts.mod),h=11)

#exponential smoothing
coil.ets <- forecast(ets(coilts.mod),h=11)

#theta
coil.tht <- thetaf(coilts.mod, h=11)

#random walk
coil.rwf <- rwf(coilts.mod, h=11)

#structts
coil.struc <- forecast(StructTS(coilts.mod),h=11)


##accuracy 

arm.acc <- accuracy(coil.arima,coil.test)
ets.acc <- accuracy(coil.ets,coil.test)
tht.acc <- accuracy(coil.tht,coil.test)
rwf.acc <- accuracy(coil.rwf,coil.test)
str.acc <- accuracy(coil.struc,coil.test)

Usando o MAE nos dados de espera, eu escolheria o ARIMA para previsão de curto prazo (1 a 12 meses). a longo prazo, eu confiaria na previsão aleatória da caminhada. Observe que o ARIMA escolheu um modelo de passeio aleatório com desvio (0,1,0) + desvio, que tende a ser muito mais preciso do que o modelo de passeio aleatório puro nesse tipo de problema especificamente a curto prazo. Veja o gráfico abaixo. Isso se baseia na função de precisão, como mostrado no código acima.

insira a descrição da imagem aqui

Respostas específicas para suas perguntas específicas: Também uma pergunta que eu tinha era, antes de passar para o ARIMA ou para a rede neural, devo suavizar os dados? Se sim, usando o que?

  • Não, os métodos de previsão naturalmente suavizam seus dados para se ajustarem ao modelo.

Os dados mostram sazonalidade e tendência.

  • Os dados acima não mostram tendência ou sazonalidade. Se você determinar que os dados exibem sazonalidade e tendência, escolha um método apropriado.

Dicas práticas para melhorar a precisão:

Combine vários métodos de previsão: - Você pode tentar usar métodos de não extrapolação, como previsão por analogia , previsão de julgamento ou outras técnicas e combiná-los com seus métodos estatísticos para fornecer previsões precisas. Consulte este artigo para obter os benefícios da combinação. Tentei combinar os 5 métodos acima, mas as previsões não eram precisas como métodos individuais, um possível motivo é que a previsão individual é semelhante. Você colhe os benefícios da combinação de previsão ao combinar diversos métodos, como previsões estatísticas e de julgamento.

Detectar e entender discrepantes: - Os dados do mundo real são preenchidos com discrepantes. Identifique e trate apropriadamente os discrepantes em séries temporais. Recomende a leitura deste post . Ao olhar para os dados da bobina, a queda anterior a 2009 é um desvio?

Editar

Os dados parecem estar seguindo algum tipo de tendência macroeconômica. Meu palpite é que a tendência de queda observada antes de 2009 segue uma queda na economia observada entre 2008 - 2009 e começa a melhorar após 2009. Se esse for o caso, eu evitaria o uso de métodos de extrapolação e, em vez disso, confiaria na teoria sólida de como essas tendências econômicas se comportam como a mencionada por @GraemeWalsh.

Espero que isto ajude

previsor
fonte