As previsões do modelo BSTS (em R) estão falhando completamente

15

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 bstspacote 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:

Dados completos

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:

Modelo

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:

previsão pura

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:

distribuição completa

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.

anthr
fonte
2
Por que você não publica seus dados e tentarei ajudar ... Não poderei responder por que o modelo está sendo quebrado, pois não uso essa abordagem, pois possui muitas suposições embutidas. preciso quanto a quantos valores foram retidos, a data de início e o país de origem.
precisa saber é o seguinte
Muito obrigado pelo seu comentário. Fiz o upload dos dados brutos aqui , caso você tenha tempo para dar uma olhada. Os dados variam desde o início de 2013 até o final deste ano. Também tentei fazer a previsão com um modelo ARIMA, mas as previsões não correspondiam aos dados de espera. Os dados de espera são basicamente apenas uma fração de 2015 ou 2016, dependendo da quantidade de dados de treinamento que eu queria usar.
anthr
Estou tendo um problema de baixá-lo .. por favor, envie um arquivo CSV para o meu endereço de e-mail
IrishStat

Respostas:

26

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.durationargumento diz ao modelo quantos pontos de tempo cada temporada deve durar. O nseasonsargumento 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 LocalLinearTrendmodelo é 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, tente AddLocalLevelou mesmo em AddArvez de AddLocalLinearTrend.

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.

Steve Scott
fonte
FYI: Estou tendo problemas muito parecidos com meus dados, que também são diários. Implementamos todas as suas sugestões listadas aqui e nenhuma parece ajudar.
ZakJ
11
@ Steve Scott Desculpe por incomodá-lo Steve, quero lhe perguntar o seguinte: se estou tentando modelar várias séries temporais e estou em uma estrutura de modelo Hierárquico Misto, posso modelar isso usando seu pacote? A propósito: muito obrigado pelo seu pacote!
Tommaso Guerrini 27/03
4

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

Elderkm2012
fonte
11
Foi útil no meu caso quando eu tinha poucos pontos de dados (20)
Scallan