Les prédictions du modèle BSTS (en R) échouent complètement


15

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

Données complètes

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:

Tracé du modèle

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:

prédiction pure

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:

distribution complète

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.


2
Pourquoi ne postez-vous pas vos données et je vais essayer d'aider ... Je ne serai pas en mesure de vous expliquer pourquoi le modèle tombe en panne car je n'utilise pas cette approche car elle a trop d'hypothèses intégrées. précise le nombre de valeurs retenues, la date de début et le pays d'origine.
IrishStat

Merci beaucoup pour votre commentaire. J'ai téléchargé les données brutes ici au cas où vous auriez le temps d'y jeter un œil. Les données vont du début de 2013 à la fin de cette année. J'ai également tenté de faire des prévisions avec un modèle ARIMA, mais les prévisions à partir de cela ne correspondaient pas non plus aux données sur les retenues. Les données de maintien représentent essentiellement une fraction de 2015 ou 2016, selon la quantité de données d'entraînement que je voulais utiliser.
anthr

J'ai un problème de téléchargement .. veuillez envoyer un fichier csv à mon adresse e-mail
IrishStat

Réponses:


26

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.durationargument indique au modèle combien de points de temps chaque saison devrait durer. L' nseasonsargument lui indique combien de saisons sont dans un cycle. Le nombre total de points de temps dans un cycle est season.duration * nseasons.

La deuxième suggestion est que vous voudrez peut-être penser à un modèle de tendance différent. Le LocalLinearTrendmodè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 essayer AddLocalLevelou même AddArau lieu de AddLocalLinearTrend.

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.


FYI: J'ai des problèmes très similaires avec mes données, qui sont également quotidiennes. J'ai mis en œuvre toutes vos suggestions répertoriées ici et aucune ne semble vous aider.
ZakJ

1
@Steve Scott Désolé de vous déranger Steve, je veux vous demander ceci: si j'essaie de modéliser plusieurs séries chronologiques et que je suis dans un cadre de modèle mixte hiérarchique, puis-je modéliser cela à l'aide de votre package? Au fait: merci beaucoup pour votre colis!
Tommaso Guerrini

4

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.


1
A été utile dans mon cas quand j'avais peu de points de données (20)
SCallan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.