Procedura e metodi di analisi della multiproprietà utilizzando R


13

Sto lavorando a un piccolo progetto in cui stiamo cercando di prevedere i prezzi delle materie prime (petrolio, alluminio, stagno, ecc.) Per i prossimi 6 mesi. Ho 12 di tali variabili da prevedere e ho dati da aprile 2008 a maggio 2013.

Come devo fare per la previsione? Ho fatto quanto segue:

  • Dati importati come set di dati di Timeseries
  • La stagionalità di tutte le variabili tende a variare con Trend, quindi vado al modello moltiplicativo.
  • Ho preso il registro della variabile da convertire in modello additivo
  • Per ogni variabile decomposta i dati usando STL

Sto programmando di utilizzare il livellamento esponenziale di Holt Winters, ARIMA e la rete neurale per le previsioni. Ho diviso i dati come training e testing (80, 20). Pianificazione di scegliere il modello con meno MAE, MPE, MAPE e MASE.

Lo sto facendo bene?

Anche una domanda che avevo era, prima di passare ad ARIMA o alla rete neurale, dovevo lisciare i dati? Se si, usando cosa? I dati mostrano sia stagionalità che tendenza.

MODIFICARE:

Allegare la trama e i dati della multiproprietà inserisci qui la descrizione dell'immagine

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: Una domanda, puoi dirmi se i miei dati hanno stagionalità o tendenza? E anche per favore dammi alcuni consigli su come identificarli. inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine


2
Se stai cercando di provare a prevedere gruppi di merci, come vari tipi di metallo (acciaio A, acciaio B, acciaio C, ecc.), Potrebbe valere la pena testare l'esistenza di cointegrazione. Ad esempio, qualcosa del genere: i prezzi dell'acciaio si muovono insieme? . Ciò può fornire previsioni migliori a 6 mesi (a medio / lungo termine) rispetto ai metodi univariati, ma questo è, in effetti, un gioco difficile che stai cercando di giocare. ;-)
Graeme Walsh,

1
Come sottolinea @GraemeWalsh, l'estrapolazione tendenziale univariata potrebbe non essere ideale per questo tipo di dati. Ci sono metodi ben consolidati in letteratura per la previsione del petrolio, i prezzi dell'acciaio che potrebbero valere la pena esplorare.
meteorologo

1
Puoi pubblicare nuove modifiche come domanda separata? Dato che hai già accettato una risposta, le nuove domande potrebbero non ricevere l'attenzione di cui hanno bisogno. Dall'osservazione dei dati posso dire che nessuno di essi ha tendenze o modelli stagionali. Come notato nel mio post qui sotto, sembra che la tendenza al ribasso prima del 2009 sia un fenomeno macroeconomico come la recessione?
meteorologo

@ previsioni, @ GraemeWalsh: grazie. Sto programmando di utilizzare il metodo di cointegrazione usando i test ADF.
Niranjan Sonachalam,

1
Hai fornito un contesto nella tua nuova domanda e ora ha senso Mosre. Quindi il calo prima del 2009 è stato in effetti un fenomeno macroeconomico. In tal caso, utilizzare il metodo di camminata casuale con drift o (arima (0,1,0) + drift
previsioni

Risposte:


21

È necessario utilizzare il pacchetto di previsione , che supporta tutti questi modelli (e altro) e semplifica l'adattamento:

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)

Vorrei sconsigliare di uniformare i dati prima di adattare il modello. Il tuo modello cercherà intrinsecamente di lisciare i dati, quindi il pre-smoothing complica semplicemente le cose.

inserisci qui la descrizione dell'immagine

Modifica in base a nuovi dati:

In realtà sembra che Arima sia uno dei peggiori modelli che potresti scegliere per questo set di allenamento e test.

Ho salvato i tuoi dati in una chiamata di file coil.csv, li ho caricati in R e li ho divisi in un set di addestramento e 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))

Quindi inserirò un sacco di modelli di serie storiche: arima, livellamento esponenziale, rete neurale, pipistrelli, pipistrelli, decomposizione stagionale e serie temporali strutturali:

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)
  )

Quindi ho fatto alcune previsioni e confrontato con il set di test. Ho incluso una previsione ingenua che prevede sempre una linea piatta e orizzontale:

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')
}

inserisci qui la descrizione dell'immagine

Come puoi vedere, il modello Arima sbaglia la tendenza, ma mi piace un po 'l'aspetto del "Modello strutturale di base"

Infine, ho misurato l'accuratezza di ciascun modello sul set di 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

Le metriche utilizzate sono descritte in Hyndman, RJ e Athanasopoulos, G. (2014) "Previsioni: principi e pratica" , che sono anche gli autori del pacchetto di previsioni. Consiglio vivamente di leggere il loro testo: è disponibile gratuitamente online. La serie temporale strutturale è il modello migliore per diverse metriche, tra cui MASE, che è la metrica che tendo a preferire per la selezione del modello.

Un'ultima domanda è: il modello strutturale è stato fortunato in questo set di test? Un modo per valutare questo è guardare gli errori impostati nella formazione. Gli errori del set di addestramento sono meno affidabili degli errori del set di test (perché possono essere troppo adatti), ma in questo caso il modello strutturale risulta ancora in primo piano:

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

(Si noti che la rete neurale si sovrappone, con prestazioni eccellenti sul set di allenamento e scarsamente sul set di test)

Infine, sarebbe una buona idea convalidare in modo incrociato tutti questi modelli, magari allenandosi su 2008-2009 / test sul 2010, training su 2008-2010 / test sul 2011, training su 2008-2011 / test sul 2012, training nel periodo 2008-2012 / test nel 2013 e errori medi in tutti questi periodi di tempo. Se desideri seguire questa strada, ho un pacchetto parzialmente completo per la validazione incrociata di modelli di serie temporali su github che ti piacerebbe provare e darmi feedback / richieste di pull su:

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

Modifica 2: vediamo se ricordo come usare il mio pacchetto!

Prima di tutto, installa e carica il pacchetto da github (vedi sopra). Quindi convalidare in modo incrociato alcuni modelli (utilizzando il set di dati completo):

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)

(Si noti che ho ridotto la flessibilità del modello di rete neurale, per cercare di evitare che si adatti eccessivamente)

Una volta che abbiamo adattato i modelli, possiamo confrontarli con MAPE (cv.ts non supporta ancora 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

Ahia. Sembrerebbe che le nostre previsioni strutturali siano state fortunate. A lungo termine, la previsione ingenua fornisce le migliori previsioni, calcolate in media in un orizzonte di 12 mesi (il modello arima è ancora uno dei modelli peggiori). Confrontiamo i modelli in ciascuno dei 12 orizzonti di previsione e vediamo se qualcuno di loro ha mai battuto il modello ingenuo:

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")
    )

modello di confronto

In modo evidente, il modello di livellamento esponenziale sceglie sempre il modello ingenuo (la linea arancione e la linea blu si sovrappongono al 100%). In altre parole, l'ingenua previsione dei "prezzi delle bobine del mese prossimo sarà la stessa dei prezzi delle bobine di questo mese" è più accurata (in quasi tutti gli orizzonti delle previsioni) rispetto a 7 modelli di serie temporali estremamente sofisticati. A meno che tu non abbia alcune informazioni segrete che il mercato delle bobine non conosce già, battere l'ingenua previsione dei prezzi delle bobine sarà estremamente difficile .

Non è mai la risposta che qualcuno vuole sentire, ma se la precisione delle previsioni è il tuo obiettivo, dovresti usare il modello più accurato. Usa il modello ingenuo.


È interessante osservare le differenze tra questi modelli. NNAR in particolare sembra diverso. Dato che si tratta di un set di dati famoso (e storicamente vecchio, credo), è noto quale sia giusto e se un tipo di modello superi? (Nb, so relativamente poco di TS.)
gung - Ripristina Monica

@gung Il modo migliore per farlo sarebbe quello di dividere un set di controllo e testare il modello. Si noti che il modello che effettua le migliori previsioni a breve termine potrebbe non essere il modello che effettua le migliori previsioni a lungo termine ....
Zach

Grazie mille, ma non sto ottenendo buone previsioni per il set di dati di cui sopra (penso che mi manchi qualche passaggio importante qui). Potete per favore fatemi sapere se mi manca qualcosa
Niranjan Sonachalam

@Niranjan Puoi dirci / mostrare come si conclude che non si ottengono buone previsioni?
previsioni del

@forecaster: controlla qui pbrd.co/1DRPRsq . Sono nuovo alle previsioni. Fammi sapere se hai bisogno di informazioni specifiche. Ho provato con il modello Arima.
Niranjan Sonachalam,

12

L'approccio che hai adottato è ragionevole. Se non conoscete le previsioni, consiglierei i seguenti libri:

  1. Metodi e applicazioni di previsione di Makridakis, Wheelright e Hyndman
  2. Previsioni: principi e pratiche di Hyndman e Athanasopoulos.

Il primo libro è un classico che consiglio vivamente. Il secondo libro è un libro open source a cui è possibile fare riferimento per i metodi di previsione e come viene applicato utilizzando la previsione delR pacchetto software open source . Entrambi i libri forniscono una buona conoscenza dei metodi che ho usato. Se sei seriamente intenzionato a fare previsioni, allora consiglierei Principi di previsione di Armstrong, che è una raccolta di enormi quantità di ricerche nelle previsioni che un professionista potrebbe trovare molto utile.

Venendo al tuo esempio specifico sulla bobina, mi ricorda un concetto di previsione che la maggior parte dei libri di testo spesso ignora. Alcune serie come le tue serie semplicemente non possono essere previste perché sono meno pattern in quanto non mostrano trend o schemi stagionali o qualsiasi variazione sistematica. In tal caso, classificherei una serie come meno prevedibile. Prima di avventurarmi in metodi di estrapolazione, vorrei esaminare i dati e porre la domanda, è la mia serie prevista? In questo esempio specifico, una semplice estrapolazione come la previsione di camminata casuale che utilizza l'ultimo valore della previsione è risultata più accurata .

Anche un ulteriore commento sulla rete neurale: notoriamente le reti neurali falliscono nelle competizioni empiriche . Vorrei provare i metodi statistici tradizionali per le serie storiche prima di tentare di utilizzare le reti neurali per le attività di previsione delle serie storiche.

Ho provato a modellare i tuoi dati R's forecast package , spero che i commenti siano autoesplicativi.

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)

Usando MAE sui dati di controllo, sceglierei ARIMA per le previsioni a breve termine (1-12 mesi). a lungo termine, farei affidamento su previsioni casuali di camminata. Si noti che ARIMA ha scelto un modello di camminata casuale con deriva (0,1,0) + deriva che tende ad essere molto più accurato rispetto al modello di camminata casuale pura in questo tipo di problemi specificamente a breve termine. Vedi la tabella sotto. Questo si basa sulla funzione di precisione come mostrato nel codice sopra.

inserisci qui la descrizione dell'immagine

Risposte specifiche alle vostre domande specifiche: anche una domanda che avevo era, prima di passare ad ARIMA o alla rete neurale dovrei lisciare i dati? Se si, usando cosa?

  • No, i metodi di previsione naturalmente levigano i dati per adattarli al modello.

I dati mostrano sia stagionalità che tendenza.

  • I dati sopra riportati non mostrano tendenza o stagionalità. Se si determina che i dati mostrano stagionalità e tendenza, quindi scegliere un metodo appropriato.

Suggerimenti pratici per migliorare la precisione:

Combina una varietà di metodi di previsione: - Potresti provare a utilizzare metodi di non estrapolazione come previsioni per analogia , previsioni giudiziarie o altre tecniche e combinarle con i tuoi metodi statistici per fornire previsioni accurate. Vedi questo articolo per i vantaggi della combinazione. Ho provato a combinare i 5 metodi precedenti, ma la previsione non era accurata come metodi individuali, una possibile ragione è che le previsioni individuali sono simili. Ottieni i vantaggi della combinazione delle previsioni quando combini diversi metodi come previsioni statistiche e di giudizio.

Rileva e capisci i valori anomali: - I dati del mondo reale sono pieni di valori anomali. Identificare e trattare adeguatamente i valori anomali nelle serie temporali. Consiglia a leggere questo post . Guardando i dati della bobina, il calo prima del 2009 è un valore anomalo ??

modificare

I dati sembrano seguire alcuni tipi di tendenze macroeconomiche. La mia ipotesi è che la tendenza al ribasso osservata prima del 2009 segua il crollo dell'economia tra il 2008 e il 2009 e inizi a riprendersi dopo il 2009. In tal caso, eviterei tutti insieme di utilizzare metodi di estrapolazione e fare affidamento invece su una solida teoria su come queste tendenze economiche si comportano come quella a cui fa riferimento @GraemeWalsh.

Spero che sia di aiuto

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.