Procédure et méthodes d'analyse de la série temporelle utilisant R

13

Je travaille sur un petit projet où nous essayons de prévoir les prix des matières premières (pétrole, aluminium, étain, etc.) pour les 6 prochains mois. J'ai 12 variables de ce type à prévoir et j'ai des données d'avril 2008 à mai 2013.

Comment dois-je procéder pour la prédiction? J'ai fait ce qui suit:

  • Données importées en tant que jeu de données Timeseries
  • La saisonnalité de toutes les variables a tendance à varier avec la tendance, je vais donc utiliser un modèle multiplicatif.
  • J'ai pris le log de la variable à convertir en modèle additif
  • Pour chaque variable décomposé les données en utilisant STL

Je prévois d'utiliser le lissage exponentiel Holt Winters, ARIMA et le réseau neuronal pour prévoir. J'ai divisé les données en formation et tests (80, 20). Prévoir de choisir le modèle avec moins de MAE, MPE, MAPE et MASE.

Suis-je en train de bien faire?

Une autre question que j'avais était, avant de passer à ARIMA ou au réseau neuronal, dois-je lisser les données? Si oui, en utilisant quoi? Les données montrent à la fois la saisonnalité et la tendance.

ÉDITER:

Joindre le graphique et les données de la série temporelle entrez la description de l'image ici

Year  <- c(2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2009, 2009, 
           2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2010, 
           2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 
           2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 
           2011, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 
           2012, 2012, 2013, 2013)
Month <- c(4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 
           12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 
           8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2) 
Coil  <- c(44000, 44500, 42000, 45000, 42500, 41000, 39000, 35000, 34000, 
           29700, 29700, 29000, 30000, 30000, 31000, 31000, 33500, 33500, 
           33000, 31500, 34000, 35000, 35000, 36000, 38500, 38500, 35500, 
           33500, 34500, 36000, 35500, 34500, 35500, 38500, 44500, 40700, 
           40500, 39100, 39100, 39100, 38600, 39500, 39500, 38500, 39500, 
           40000, 40000, 40500, 41000, 41000, 41000, 40500, 40000, 39300, 
           39300, 39300, 39300, 39300, 39800)
coil <- data.frame(Year = Year, Month = Month, Coil = Coil)

EDIT 2: Une question, pouvez-vous s'il vous plaît me dire si mes données ont une saisonnalité ou une tendance? Et donnez-moi aussi quelques conseils pour les identifier. entrez la description de l'image ici entrez la description de l'image ici

Niranjan Sonachalam
la source
2
Si vous cherchez à prévoir des groupes de produits, tels que divers types de métaux (acier A, acier B, acier C, etc.), il peut être utile de tester l'existence de la cointégration. Par exemple, quelque chose comme ceci: les prix de l'acier évoluent-ils ensemble? . Cela peut fournir de meilleures prévisions à 6 mois (moyen / long terme) que les méthodes univariées, mais c'est en effet un jeu difficile que vous essayez de jouer. ;-)
Graeme Walsh
1
Comme le souligne @GraemeWalsh, l'extrapolation de tendance univariée pourrait ne pas être idéale pour ce type de données. Il existe des méthodes bien établies dans la littérature pour prévoir les prix du pétrole et de l'acier qui méritent d'être explorées.
prévisionniste
1
Pouvez-vous publier de nouvelles modifications en tant que question distincte? Puisque vous avez déjà accepté une réponse, les nouvelles questions risquent de ne pas attirer l'attention dont elles ont besoin. En observant les données, je peux dire qu'aucun d'entre eux n'a de tendances ou de modèles saisonniers. Comme indiqué dans mon article ci-dessous, la tendance à la baisse avant 2009 semble être un phénomène macroéconomique comme la récession?
prévisionniste
@ prévisionniste, @ GraemeWalsh: Merci. Je prévois d'utiliser la méthode de cointégration à l'aide de tests ADF.
Niranjan Sonachalam
1
Vous avez fourni un contexte dans votre nouvelle question et cela a plus de sens maintenant. La baisse avant 2009 est en effet due à certains phénomènes macroéconomiques. Dans ce cas, veuillez utiliser la méthode de marche aléatoire avec dérive ou (arima (0,1,0) + dérive
prévisionniste

Réponses:

21

Vous devez utiliser le package de prévision , qui prend en charge tous ces modèles (et plus) et facilite leur ajustement:

library(forecast)
x <- AirPassengers
mod_arima <- auto.arima(x, ic='aicc', stepwise=FALSE)
mod_exponential <- ets(x, ic='aicc', restrict=FALSE)
mod_neural <- nnetar(x, p=12, size=25)
mod_tbats <- tbats(x, ic='aicc', seasonal.periods=12)
par(mfrow=c(4, 1))
plot(forecast(mod_arima, 12), include=36)
plot(forecast(mod_exponential, 12), include=36)
plot(forecast(mod_neural, 12), include=36)
plot(forecast(mod_tbats, 12), include=36)

Je déconseille de lisser les données avant d'adapter votre modèle. Votre modèle va par nature essayer de lisser les données, donc le pré-lissage ne fait que compliquer les choses.

entrez la description de l'image ici

Modifier en fonction des nouvelles données:

Il semble que l'arima soit l'un des pires modèles que vous puissiez choisir pour cet ensemble d'entraînement et de test.

J'ai enregistré vos données dans un appel de fichier coil.csv, les ai chargées dans R et les ai divisées en un ensemble de formation et de test:

library(forecast)
dat <- read.csv('~/coil.csv')
x <- ts(dat$Coil, start=c(dat$Year[1], dat$Month[1]), frequency=12)
test_x <- window(x, start=c(2012, 3))
x <- window(x, end=c(2012, 2))

Ensuite, j'adapte un tas de modèles de séries chronologiques: arima, lissage exponentiel, réseau neuronal, tbats, chauves-souris, décomposition saisonnière et séries chronologiques structurelles:

models <- list(
  mod_arima = auto.arima(x, ic='aicc', stepwise=FALSE),
  mod_exp = ets(x, ic='aicc', restrict=FALSE),
  mod_neural = nnetar(x, p=12, size=25),
  mod_tbats = tbats(x, ic='aicc', seasonal.periods=12),
  mod_bats = bats(x, ic='aicc', seasonal.periods=12),
  mod_stl = stlm(x, s.window=12, ic='aicc', robust=TRUE, method='ets'),
  mod_sts = StructTS(x)
  )

Ensuite, j'ai fait quelques prévisions et comparé à l'ensemble de test. J'ai inclus une prévision naïve qui prédit toujours une ligne horizontale plate:

forecasts <- lapply(models, forecast, 12)
forecasts$naive <- naive(x, 12)
par(mfrow=c(4, 2))
for(f in forecasts){
  plot(f)
  lines(test_x, col='red')
}

entrez la description de l'image ici

Comme vous pouvez le voir, le modèle arima se trompe de tendance, mais j'aime un peu le look du "Basic Structural Model"

Enfin, j'ai mesuré la précision de chaque modèle sur l'ensemble de test:

acc <- lapply(forecasts, function(f){
  accuracy(f, test_x)[2,,drop=FALSE]
})
acc <- Reduce(rbind, acc)
row.names(acc) <- names(forecasts)
acc <- acc[order(acc[,'MASE']),]
round(acc, 2)
                ME    RMSE     MAE   MPE MAPE MASE ACF1 Theil's U
mod_sts     283.15  609.04  514.46  0.69 1.27 0.10 0.77      1.65
mod_bats     65.36  706.93  638.31  0.13 1.59 0.12 0.85      1.96
mod_tbats    65.22  706.92  638.32  0.13 1.59 0.12 0.85      1.96
mod_exp      25.00  706.52  641.67  0.03 1.60 0.12 0.85      1.96
naive        25.00  706.52  641.67  0.03 1.60 0.12 0.85      1.96
mod_neural   81.14  853.86  754.61  0.18 1.89 0.14 0.14      2.39
mod_arima   766.51  904.06  766.51  1.90 1.90 0.14 0.73      2.48
mod_stl    -208.74 1166.84 1005.81 -0.52 2.50 0.19 0.32      3.02

Les métriques utilisées sont décrites dans Hyndman, RJ et Athanasopoulos, G. (2014) «Forecasting: Principles and Practice» , qui se trouvent également être les auteurs de l'ensemble de prévisions. Je vous recommande fortement de lire leur texte: il est disponible gratuitement en ligne. La série chronologique structurelle est le meilleur modèle selon plusieurs métriques, y compris MASE, qui est la métrique que j'ai tendance à préférer pour la sélection du modèle.

Une dernière question est: le modèle structurel a-t-il eu de la chance sur cet ensemble de test? Une façon d'évaluer cela consiste à examiner les erreurs des ensembles de formation. Les erreurs de l'ensemble de formation sont moins fiables que les erreurs de l'ensemble de test (car elles peuvent être trop ajustées), mais dans ce cas, le modèle structurel vient toujours en tête:

acc <- lapply(forecasts, function(f){
  accuracy(f, test_x)[1,,drop=FALSE]
})
acc <- Reduce(rbind, acc)
row.names(acc) <- names(forecasts)
acc <- acc[order(acc[,'MASE']),]
round(acc, 2)
                ME    RMSE     MAE   MPE MAPE MASE  ACF1 Theil's U
mod_sts      -0.03    0.99    0.71  0.00 0.00 0.00  0.08        NA
mod_neural    3.00 1145.91  839.15 -0.09 2.25 0.16  0.00        NA
mod_exp     -82.74 1915.75 1359.87 -0.33 3.68 0.25  0.06        NA
naive       -86.96 1936.38 1386.96 -0.34 3.75 0.26  0.06        NA
mod_arima  -180.32 1889.56 1393.94 -0.74 3.79 0.26  0.09        NA
mod_stl     -38.12 2158.25 1471.63 -0.22 4.00 0.28 -0.09        NA
mod_bats     57.07 2184.16 1525.28  0.00 4.07 0.29 -0.03        NA
mod_tbats    62.30 2203.54 1531.48  0.01 4.08 0.29 -0.03        NA

(Notez que le réseau de neurones est trop performant, performant sur l'ensemble d'entraînement et médiocrement sur l'ensemble de test)

Enfin, ce serait une bonne idée de contre-valider tous ces modèles, peut-être par une formation sur 2008-2009 / tests sur 2010, formation sur 2008-2010 / tests sur 2011, formation sur 2008-2011 / tests sur 2012, formation sur 2008-2012 / tests sur 2013 et moyenne des erreurs sur toutes ces périodes. Si vous souhaitez emprunter cette voie, j'ai un package partiellement complet pour les modèles de séries chronologiques à validation croisée sur github que j'aimerais que vous essayiez et que vous me fassiez part de vos commentaires / demandes de traction sur:

devtools::install_github('zachmayer/cv.ts')
library(cv.ts)

Edit 2: Voyons si je me souviens comment utiliser mon propre package!

Tout d'abord, installez et chargez le paquet depuis github (voir ci-dessus). Validez ensuite certains modèles (en utilisant l'ensemble de données complet):

library(cv.ts)
x <- ts(dat$Coil, start=c(dat$Year[1], dat$Month[1]), frequency=12)
ctrl <- tseriesControl(stepSize=1, maxHorizon=12, minObs=36, fixedWindow=TRUE)
models <- list()

models$arima = cv.ts(
  x, auto.arimaForecast, tsControl=ctrl,
  ic='aicc', stepwise=FALSE)

models$exp = cv.ts(
  x, etsForecast, tsControl=ctrl,
  ic='aicc', restrict=FALSE)

models$neural = cv.ts(
  x, nnetarForecast, tsControl=ctrl,
  nn_p=6, size=5)

models$tbats = cv.ts(
  x, tbatsForecast, tsControl=ctrl,
  seasonal.periods=12)

models$bats = cv.ts(
  x, batsForecast, tsControl=ctrl,
  seasonal.periods=12)

models$stl = cv.ts(
  x, stl.Forecast, tsControl=ctrl,
  s.window=12, ic='aicc', robust=TRUE, method='ets')

models$sts = cv.ts(x, stsForecast, tsControl=ctrl)

models$naive = cv.ts(x, naiveForecast, tsControl=ctrl)

models$theta = cv.ts(x, thetaForecast, tsControl=ctrl)

(Notez que j'ai réduit la flexibilité du modèle de réseau neuronal, pour essayer de l'empêcher de sur-adapter)

Une fois que nous avons ajusté les modèles, nous pouvons les comparer par MAPE (cv.ts ne prend pas encore en charge MASE):

res_overall <- lapply(models, function(x) x$results[13,-1])
res_overall <- Reduce(rbind, res_overall)
row.names(res_overall) <- names(models)
res_overall <- res_overall[order(res_overall[,'MAPE']),]
round(res_overall, 2)
                 ME    RMSE     MAE   MPE MAPE
naive     91.40 1126.83  961.18  0.19 2.40
ets       91.56 1127.09  961.35  0.19 2.40
stl     -114.59 1661.73 1332.73 -0.29 3.36
neural     5.26 1979.83 1521.83  0.00 3.83
bats     294.01 2087.99 1725.14  0.70 4.32
sts     -698.90 3680.71 1901.78 -1.81 4.77
arima  -1687.27 2750.49 2199.53 -4.23 5.53
tbats   -476.67 2761.44 2428.34 -1.23 6.10

Aie. Il semblerait que notre prévision structurelle ait eu de la chance. À long terme, la prévision naïve fait les meilleures prévisions, moyennées sur un horizon de 12 mois (le modèle arima est toujours l'un des pires modèles). Comparons les modèles à chacun des 12 horizons de prévision et voyons si l'un d'eux a déjà battu le modèle naïf:

library(reshape2)
library(ggplot2)
res <- lapply(models, function(x) x$results$MAPE[1:12])
res <- data.frame(do.call(cbind, res))
res$horizon <- 1:nrow(res)
res <- melt(res, id.var='horizon', variable.name='model', value.name='MAPE')
res$model <- factor(res$model, levels=row.names(res_overall))
ggplot(res, aes(x=horizon, y=MAPE, col=model)) +
  geom_line(size=2) + theme_bw() +
  theme(legend.position="top") +
  scale_color_manual(values=c(
    "#1f78b4", "#ff7f00", "#33a02c", "#6a3d9a",
    "#e31a1c", "#b15928", "#a6cee3", "#fdbf6f",
    "#b2df8a")
    )

modèle comparer

Fait révélateur, le modèle de lissage exponentiel sélectionne toujours le modèle naïf (la ligne orange et la ligne bleue se chevauchent à 100%). En d'autres termes, la prévision naïve des "prix des bobines du mois prochain sera la même que les prix des bobines de ce mois-ci" est plus précise (à presque tous les horizons de prévision) que 7 modèles de séries chronologiques extrêmement sophistiqués. Sauf si vous avez des informations secrètes que le marché des bobines ne connaît pas déjà, battre les prévisions de prix naïves des bobines sera extrêmement difficile .

Ce n'est jamais la réponse que quiconque veut entendre, mais si la précision des prévisions est votre objectif, vous devez utiliser le modèle le plus précis. Utilisez le modèle naïf.

Zach
la source
Il est intéressant de regarder les différences entre ces modèles. NNAR en particulier est différent. Étant donné qu'il s'agit d'un ensemble de données célèbre (et historiquement ancien, je crois), est-il connu qui a raison et si un type de modèle surpasse? (Nb, je connais relativement peu de TS.)
gung - Réintègre Monica
@gung La meilleure façon de procéder serait de séparer un ensemble d'exclusion et de tester le modèle. Notez que le modèle qui fait les meilleures prévisions à court terme n'est peut-être pas le modèle qui fait les meilleures prévisions à long terme ....
Zach
Merci beaucoup, mais je n'obtiens pas de bonnes prévisions pour l'ensemble de données ci-dessus (je pense que je manque une étape importante ici). Pouvez-vous s'il vous plaît laissez-moi savoir si je manque quelque chose
Niranjan Sonachalam
@Niranjan Pouvez-vous nous dire / montrer comment vous concluez que vous n'obtenez pas de bonnes prévisions?
prévisionniste
@forecaster: Veuillez vérifier ici pbrd.co/1DRPRsq . Je suis nouveau dans les prévisions. Faites-moi savoir si vous avez besoin d'informations spécifiques. J'ai essayé avec le modèle Arima.
Niranjan Sonachalam
12

L'approche que vous avez adoptée est raisonnable. Si vous êtes nouveau dans la prévision, alors je recommanderais les livres suivants:

  1. Méthodes et applications de prévision par Makridakis, Wheelright et Hyndman
  2. Prévision: principes et pratique par Hyndman et Athanasopoulos.

Le premier livre est un classique que je recommande fortement. Le deuxième livre est un livre open source auquel vous pouvez vous référer pour les méthodes de prévision et comment il est appliqué à l'aide de prévisions deR progiciels open source . Les deux livres fournissent un bon contexte sur les méthodes que j'ai utilisées. Si vous êtes sérieux au sujet de la prévision, alors je recommanderais les principes de prévision d'Armstrong, qui constituent une énorme quantité de recherches en prévision qu'un pratiquant pourrait trouver très utile.

En venant à votre exemple spécifique sur la bobine, cela me rappelle un concept de prévisibilité que la plupart des manuels ignorent souvent. Certaines séries telles que la vôtre ne peuvent tout simplement pas être prévues car elles sont moins structurées car elles ne présentent pas de tendances ou de tendances saisonnières ou toute variation systématique. Dans ce cas, je classerais une série comme moins prévisible. Avant de s'aventurer dans les méthodes d'extrapolation, je regardais les données et poser la question, est ma série prévisible? Dans cet exemple spécifique, une simple extrapolation, comme marche aléatoire prévision qui utilise la dernière valeur de la prévision a été jugée plus précise .

Un autre commentaire sur le réseau de neurones: les réseaux de neurones sont connus pour échouer dans les compétitions empiriques . J'essaierais les méthodes statistiques traditionnelles pour les séries chronologiques avant d'essayer d'utiliser des réseaux de neurones pour des tâches de prévision de séries chronologiques.

J'ai essayé de modéliser vos données R's forecast package, j'espère que les commentaires sont explicites.

coil <- c(44000, 44500, 42000, 45000, 42500, 41000, 39000, 35000, 34000, 
          29700, 29700, 29000, 30000, 30000, 31000, 31000, 33500, 33500, 
          33000, 31500, 34000, 35000, 35000, 36000, 38500, 38500, 35500, 
          33500, 34500, 36000, 35500, 34500, 35500, 38500, 44500, 40700, 
          40500, 39100, 39100, 39100, 38600, 39500, 39500, 38500, 39500, 
          40000, 40000, 40500, 41000, 41000, 41000, 40500, 40000, 39300, 
          39300, 39300, 39300, 39300, 39800)


coilts <- ts(coil,start=c(2008,4),frequency=12)

library("forecast")

# Data for modeling
coilts.mod <- window(coilts,end = c(2012,3))

#Data for testing
coil.test <- window(coilts,start=c(2012,4))

# Model using multiple methods - arima, expo smooth, theta, random walk, structural time series

#arima
coil.arima <- forecast(auto.arima(coilts.mod),h=11)

#exponential smoothing
coil.ets <- forecast(ets(coilts.mod),h=11)

#theta
coil.tht <- thetaf(coilts.mod, h=11)

#random walk
coil.rwf <- rwf(coilts.mod, h=11)

#structts
coil.struc <- forecast(StructTS(coilts.mod),h=11)


##accuracy 

arm.acc <- accuracy(coil.arima,coil.test)
ets.acc <- accuracy(coil.ets,coil.test)
tht.acc <- accuracy(coil.tht,coil.test)
rwf.acc <- accuracy(coil.rwf,coil.test)
str.acc <- accuracy(coil.struc,coil.test)

En utilisant MAE sur les données de rétention, je choisirais ARIMA pour les prévisions à court terme (1 à 12 mois). à long terme, je compterais sur des prévisions de marche aléatoires. Veuillez noter qu'ARIMA a choisi un modèle de marche aléatoire avec dérive (0,1,0) + dérive qui a tendance à être beaucoup plus précis que le modèle de marche aléatoire pur dans ce type de problèmes spécifiquement à court terme. Voir le tableau ci-dessous. Ceci est basé sur la fonction de précision comme indiqué dans le code ci-dessus.

entrez la description de l'image ici

Réponses spécifiques à vos questions spécifiques: Une autre question que j'avais était, avant de passer à ARIMA ou au réseau neuronal, dois-je lisser les données? Si oui, en utilisant quoi?

  • Non, les méthodes de prévision lissent naturellement vos données pour les adapter au modèle.

Les données montrent à la fois la saisonnalité et la tendance.

  • Les données ci-dessus ne montrent ni tendance ni saisonnalité. Si vous déterminez que les données présentent une saisonnalité et une tendance, choisissez une méthode appropriée.

Conseils pratiques pour améliorer la précision:

Combinez diverses méthodes de prévision: - Vous pouvez essayer d'utiliser des méthodes de non extrapolation telles que la prévision par analogie , la prévision par jugement ou d'autres techniques et les combiner avec vos méthodes statistiques pour fournir des prévisions précises. Voir cet article pour les avantages de la combinaison. J'ai essayé de combiner les 5 méthodes ci-dessus, mais les prévisions n'étaient pas précises en tant que méthodes individuelles, une des raisons possibles est que les prévisions individuelles sont similaires. Vous récoltez les avantages de la combinaison des prévisions lorsque vous combinez diverses méthodes telles que les prévisions statistiques et de jugement.

Détectez et comprenez les valeurs aberrantes: - Les données du monde réel sont remplies de valeurs aberrantes. Identifier et traiter de manière appropriée les valeurs aberrantes dans les séries chronologiques. Recommander la lecture de ce post . En regardant vos données de bobine, la baisse avant 2009 est-elle une valeur aberrante ??

Éditer

Les données semblent suivre un certain type de tendances macroéconomiques. Je suppose que la tendance à la baisse observée avant 2009 fait suite à l'effondrement de l'économie observé entre 2008 et 2009 et commence à reprendre après 2009. Si tel est le cas, j'éviterais tous ensemble d'utiliser des méthodes d'extrapolation et de me fier à une théorie solide sur la façon dont ces tendances économiques se comportent comme celle référencée par @GraemeWalsh.

J'espère que cela t'aides

prévisionniste
la source