Depois de ler esta postagem no blog sobre modelos estruturais de séries temporais bayesianas, eu queria analisar isso no contexto de um problema para o qual eu havia usado o ARIMA anteriormente.
Eu tenho alguns dados com alguns componentes sazonais conhecidos (mas barulhentos) - existem definitivamente componentes anuais, mensais e semanais para isso e também alguns efeitos devido a dias especiais (como feriados federais ou religiosos).
Eu usei o bsts
pacote para implementar isso e, até onde sei, não fiz nada de errado, embora os componentes e a previsão simplesmente não pareçam como eu esperaria. Não está claro para mim se minha implementação está errada, incompleta ou tem algum outro problema.
A série completa fica assim:
Eu posso treinar o modelo em alguns subconjuntos de dados, e o modelo geralmente parece bom em termos de ajuste (o gráfico está abaixo). O código que estou usando para fazer isso está aqui:
library(bsts)
predict_length = 90
training_cut_date <- '2015-05-01'
test_cut_date <- as.Date(training_cut_date) + predict_length
df = read.csv('input.tsv', sep ='\t')
df$date <- as.Date(as.character(df$date),format="%Y-%m-%d")
df_train = df[df$date < training_cut_date,]
yts <- xts(log10(df_train$count), order.by=df_train$date)
ss <- AddLocalLinearTrend(list(), yts)
ss <- AddSeasonal(ss, yts, nseasons = 7)
ss <- AddSeasonal(ss, yts, nseasons = 12)
ss <- AddNamedHolidays(ss, named.holidays = NamedHolidays(), yts)
model <- bsts(yts, state.specification = ss, niter = 500, seed=2016)
O modelo parece razoável:
Mas se eu traçar a previsão, em primeiro lugar, a tendência estará completamente errada e, em segundo lugar, a incerteza aumentará MUITO rapidamente - a ponto de não poder mostrar a banda de incerteza no mesmo gráfico que as previsões sem fazer o eixo y em um log- escala. O código para esta parte está aqui:
burn <- SuggestBurn(0.1, model)
pred <- predict(model, horizon = predict_length, burn = burn, quantiles = c(.025, .975))
A previsão pura é assim:
E então, quando redimensionados para a distribuição inicial (com a linha pontilhada mostrando a transição do treinamento para a previsão, os problemas são óbvios:
Tentei adicionar mais tendências sazonais, remover tendências sazonais, adicionar um termo de AR, alterar o AddLocalLinearModel para AddGeneralizedLocalLinearTrend e várias outras coisas relacionadas ao ajuste do modelo, mas nada resolveu os problemas e tornou as previsões mais significativas. Em alguns casos, a direção muda; portanto, em vez de cair para 0, a previsão continua a aumentar em função do tempo. Definitivamente, não entendo por que o modelo está se deteriorando dessa maneira. Qualquer sugestão seria muito bem-vinda.
Respostas:
Steve Scott aqui. Eu escrevi o pacote bsts. Eu tenho algumas sugestões para você. Primeiro, seus componentes sazonais não estão fazendo o que você pensa. Eu acho que você tem dados diários, porque está tentando adicionar um componente de 7 temporadas, que deve estar funcionando corretamente. Mas você disse ao seu componente sazonal anual para repetir a cada 12 dias. É difícil obter um componente sazonal mensal com dados diários, mas você pode fazer uma sazonal de 52 semanas
AddSeasonal(..., nseasons = 52, season.duration = 7)
.O
seasonal.duration
argumento diz ao modelo quantos pontos de tempo cada temporada deve durar. Onseasons
argumento diz quantas estações existem em um ciclo. O número total de pontos no tempo em um ciclo éseason.duration * nseasons
.A segunda sugestão é que você pode pensar em um modelo diferente de tendência. O
LocalLinearTrend
modelo é muito flexível, mas essa flexibilidade pode aparecer como variação indesejada nas previsões de longo prazo. Existem alguns outros modelos de tendência que contêm um pouco mais de estrutura.GeneralizedLocalLinearTrend
(desculpe pelo nome não descritivo) assume que o componente "slope" da tendência é um processo AR1 em vez de uma caminhada aleatória. É a minha opção padrão se eu quiser fazer uma previsão para o futuro. A maior parte da variação das séries temporais parece advir da sazonalidade; portanto, tenteAddLocalLevel
ou mesmo emAddAr
vez deAddLocalLinearTrend
.Por fim, em geral, se você está recebendo previsões estranhas e deseja descobrir qual parte do modelo é responsável, tente
plot(model, "components")
ver o modelo decomposto nas partes individuais solicitadas.fonte
Eu acho que você também pode alterar a gravação padrão. Como usei o bsts, criei uma grade de valores de queima e nitro com o MAPE como minha estatística no período de espera. Tente também usar AddStudentLocalLinearTrend se seus dados tiverem uma variação enorme para que o modelo espere essa variação
fonte