After reading this blog post about Bayesian structural time series models, I wanted to look at implementing this in the context of a problem I'd previously used ARIMA for.
I have some data with some known (but noisy) seasonal components - there are definitely an annual, monthly and weekly components to this, and also some effects due to special days (such as federal or religious holidays).
I have used the bsts
package to implement this and as far as I can tell I haven't done anything wrong, although the components and prediction simply don't look as I'd expect. It isn't clear to me if my implementation is wrong, incomplete or has some other problem.
The full time series looks like this:
I can train the model on some subset of the data, and the model generally looks good in terms of the fit (plot is below). The code I am using to do this is here:
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)
The model looks reasonable:
But if I plot the prediction then firstly the trend is completely wrong, and secondly the uncertainty grows VERY quickly - to the point where I can't show the uncertainty band on the same plot as the predictions without making the y axis on a log-scale. The code for this part is here:
burn <- SuggestBurn(0.1, model)
pred <- predict(model, horizon = predict_length, burn = burn, quantiles = c(.025, .975))
The pure prediction looks like this:
And then when scaled back to the initial distribution (with the dotted line showing the transition from training to prediction, the problems are obvious:
I have tried adding more seasonal trends, removing seasonal trends, adding an AR term, changing the AddLocalLinearModel to AddGeneralizedLocalLinearTrend and several other things concerning tweaking the model, but nothing has resolved the issues and made the predictions more meaningful. In some cases the direction changes, so rather than dropping to 0 the prediction just continues to increase as a function of time. I definitely don't understand why the model is breaking down in this way. Any suggestions would be very welcome.