Après avoir lu ce billet de blog sur les modèles de séries chronologiques structurelles bayésiennes, j'ai voulu examiner la mise en œuvre de cela dans le contexte d'un problème pour lequel j'avais précédemment utilisé ARIMA.
J'ai quelques données avec certaines composantes saisonnières connues (mais bruyantes) - il y a certainement des composantes annuelles, mensuelles et hebdomadaires à cela, et aussi certains effets dus à des jours spéciaux (tels que les jours fériés fédéraux ou religieux).
J'ai utilisé le bsts
package pour l'implémenter et pour autant que je sache, je n'ai rien fait de mal, bien que les composants et la prédiction ne semblent tout simplement pas comme je m'y attendais. Il n'est pas clair pour moi si ma mise en œuvre est incorrecte, incomplète ou a un autre problème.
La série chronologique complète ressemble à ceci:
Je peux entraîner le modèle sur un sous-ensemble de données, et le modèle semble généralement bon en termes d'ajustement (le graphique est ci-dessous). Le code que j'utilise pour ce faire est ici:
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)
Le modèle semble raisonnable:
Mais si je trace la prédiction, premièrement, la tendance est complètement fausse, et deuxièmement, l'incertitude croît TRÈS rapidement - au point où je ne peux pas montrer la bande d'incertitude sur le même tracé que les prédictions sans faire l'axe des y sur un log- échelle. Le code de cette partie est ici:
burn <- SuggestBurn(0.1, model)
pred <- predict(model, horizon = predict_length, burn = burn, quantiles = c(.025, .975))
La prédiction pure ressemble à ceci:
Et puis une fois ramené à la distribution initiale (avec la ligne pointillée montrant la transition de l'entraînement à la prédiction, les problèmes sont évidents:
J'ai essayé d'ajouter plus de tendances saisonnières, de supprimer les tendances saisonnières, d'ajouter un terme AR, de changer AddLocalLinearModel en AddGeneralizedLocalLinearTrend et plusieurs autres choses concernant l'ajustement du modèle, mais rien n'a résolu les problèmes et rendu les prédictions plus significatives. Dans certains cas, la direction change, donc plutôt que de descendre à 0, la prédiction continue juste d'augmenter en fonction du temps. Je ne comprends vraiment pas pourquoi le modèle tombe en panne de cette façon. Toute suggestion serait la bienvenue.
Réponses:
Steve Scott ici. J'ai écrit le paquet bsts. J'ai quelques suggestions pour vous. Tout d'abord, vos composants saisonniers ne font pas ce que vous pensez qu'ils sont. Je pense que vous avez des données quotidiennes, car vous essayez d'ajouter un composant 7 saisons, qui devrait fonctionner correctement. Mais vous avez dit à votre composante saisonnière annuelle de se répéter tous les 12 jours. Obtenir une composante saisonnière mensuelle avec des données quotidiennes est un peu difficile à faire, mais vous pouvez faire une saison saisonnière de 52 semaines
AddSeasonal(..., nseasons = 52, season.duration = 7)
.L'
seasonal.duration
argument indique au modèle combien de points de temps chaque saison devrait durer. L'nseasons
argument lui indique combien de saisons sont dans un cycle. Le nombre total de points de temps dans un cycle estseason.duration * nseasons
.La deuxième suggestion est que vous voudrez peut-être penser à un modèle de tendance différent. Le
LocalLinearTrend
modèle est très flexible, mais cette flexibilité peut apparaître comme une variation indésirable des prévisions à long terme. Il existe d'autres modèles de tendance qui contiennent un peu plus de structure.GeneralizedLocalLinearTrend
(désolé pour le nom non descriptif) suppose que la composante "pente" de la tendance est un processus AR1 au lieu d'une marche aléatoire. C'est mon option par défaut si je veux faire des prévisions dans le futur. La plupart de vos variations de séries chronologiques semblent provenir de la saisonnalité, vous pouvez donc essayerAddLocalLevel
ou mêmeAddAr
au lieu deAddLocalLinearTrend
.Enfin, en général, si vous obtenez des prévisions étranges et que vous souhaitez déterminer quelle partie du modèle est à blâmer, essayez
plot(model, "components")
de voir le modèle décomposé en pièces individuelles que vous avez demandées.la source
Je pense que vous pouvez également modifier la gravure par défaut. Comme j'ai utilisé bsts, j'ai créé une grille de valeurs de gravure et de niter avec MAPE comme statistique sur la période de blocage. Essayez également d'utiliser AddStudentLocalLinearTrend à la place si vos données présentent d'énormes variations afin que le modèle puisse s'attendre à de telles variations.
la source