Le previsioni di un modello Foresta casuale hanno un intervallo di previsione?


52

Se eseguo un randomForestmodello, posso quindi fare previsioni basate sul modello. C'è un modo per ottenere un intervallo di previsione di ciascuna delle previsioni in modo tale che io sappia quanto "sicuro" sia il modello della sua risposta. Se ciò è possibile, è semplicemente basato sulla variabilità della variabile dipendente per l'intero modello o avrà intervalli più ampi e più stretti a seconda del particolare albero decisionale che è stato seguito per una previsione particolare?


3
AFAIK, tutte le librerie RF hanno una sorta di scorefunzione per valutare le prestazioni. Poiché l'output si basa sul voto a maggioranza degli alberi nella foresta, in caso di classificazione ti darà la probabilità che questo risultato sia vero, in base alla distribuzione dei voti. Non sono sicuro della regressione però .... Quale libreria usi?
sashkello,

Risposte:


40

Questa è in parte una risposta a @Sashikanth Dareddy (poiché non si adatta a un commento) e in parte una risposta al post originale.

Ricorda che cos'è un intervallo di predizione, è un intervallo o un insieme di valori in cui prevediamo che mentiranno osservazioni future. Generalmente l'intervallo di predizione ha 2 pezzi principali che ne determinano la larghezza, un pezzo che rappresenta l'incertezza sulla media prevista (o altro parametro) questa è la parte dell'intervallo di confidenza, e un pezzo che rappresenta la variabilità delle singole osservazioni attorno a quella media. L'intervallo di confidenza è fiabesco grazie al Teorema del limite centrale e, nel caso di una foresta casuale, aiuta anche il bootstrap. Ma l'intervallo di previsione dipende completamente dalle ipotesi su come i dati sono distribuiti, date le variabili predittive, CLT e bootstrap non hanno alcun effetto su quella parte.

L'intervallo di previsione dovrebbe essere più ampio laddove anche l'intervallo di confidenza corrispondente sarebbe più ampio. Altre cose che potrebbero influenzare la larghezza dell'intervallo di previsione sono ipotesi sulla varianza uguale o no, questo deve venire dalla conoscenza del ricercatore, non dal modello di foresta casuale.

Un intervallo di predizione non ha senso per un risultato categorico (potresti fare un set di predizione piuttosto che un intervallo, ma il più delle volte probabilmente non sarebbe molto informativo).

Possiamo vedere alcuni dei problemi relativi agli intervalli di previsione simulando i dati in cui conosciamo la verità esatta. Considera i seguenti dati:

set.seed(1)

x1 <- rep(0:1, each=500)
x2 <- rep(0:1, each=250, length=1000)

y <- 10 + 5*x1 + 10*x2 - 3*x1*x2 + rnorm(1000)

Questi dati particolari seguono i presupposti per una regressione lineare ed è abbastanza semplice per un adattamento casuale della foresta. Sappiamo dal modello "vero" che quando entrambi i predittori sono 0 che la media è 10, sappiamo anche che i singoli punti seguono una distribuzione normale con deviazione standard di 1. Ciò significa che l'intervallo di previsione del 95% basato sulla conoscenza perfetta per questi punti vanno da 8 a 12 (ben 8,04 a 11,96, ma l'arrotondamento lo rende più semplice). Qualsiasi intervallo di previsione stimato dovrebbe essere più ampio di questo (non avere informazioni perfette aggiunge larghezza per compensare) e includere questo intervallo.

Diamo un'occhiata agli intervalli dalla regressione:

fit1 <- lm(y ~ x1 * x2)

newdat <- expand.grid(x1=0:1, x2=0:1)

(pred.lm.ci <- predict(fit1, newdat, interval='confidence'))
#        fit       lwr      upr
# 1 10.02217  9.893664 10.15067
# 2 14.90927 14.780765 15.03778
# 3 20.02312 19.894613 20.15162
# 4 21.99885 21.870343 22.12735

(pred.lm.pi <- predict(fit1, newdat, interval='prediction'))
#        fit      lwr      upr
# 1 10.02217  7.98626 12.05808
# 2 14.90927 12.87336 16.94518
# 3 20.02312 17.98721 22.05903
# 4 21.99885 19.96294 24.03476

Possiamo vedere che c'è una certa incertezza nelle medie stimate (intervallo di confidenza) e che ci dà un intervallo di predizione che è più ampio (ma include) l'intervallo da 8 a 12.

Ora diamo un'occhiata all'intervallo basato sulle singole previsioni dei singoli alberi (dovremmo aspettarci che siano più ampie poiché la foresta casuale non beneficia delle ipotesi (che sappiamo essere vere per questi dati) che la regressione lineare fa):

library(randomForest)
fit2 <- randomForest(y ~ x1 + x2, ntree=1001)

pred.rf <- predict(fit2, newdat, predict.all=TRUE)

pred.rf.int <- apply(pred.rf$individual, 1, function(x) {
  c(mean(x) + c(-1, 1) * sd(x), 
  quantile(x, c(0.025, 0.975)))
})

t(pred.rf.int)
#                           2.5%    97.5%
# 1  9.785533 13.88629  9.920507 15.28662
# 2 13.017484 17.22297 12.330821 18.65796
# 3 16.764298 21.40525 14.749296 21.09071
# 4 19.494116 22.33632 18.245580 22.09904

Gli intervalli sono più ampi degli intervalli di previsione della regressione, ma non coprono l'intero intervallo. Includono i valori reali e pertanto possono essere legittimi come intervalli di confidenza, ma prevedono solo dove si trova la media (valore previsto), nessun elemento aggiunto per la distribuzione intorno a tale media. Per il primo caso in cui x1 e x2 sono entrambi 0 gli intervalli non scendono al di sotto di 9,7, questo è molto diverso dal vero intervallo di predizione che scende a 8. Se generiamo nuovi punti dati, allora ci saranno diversi punti (molto di più del 5%) che si trovano negli intervalli di regressione e true, ma non rientrano negli intervalli di foresta casuali.

Per generare un intervallo di previsione dovrai fare alcune forti ipotesi sulla distribuzione dei singoli punti attorno ai mezzi previsti, quindi potresti prendere le previsioni dai singoli alberi (il pezzo dell'intervallo di confidenza avviato) e quindi generare un valore casuale dall'assunto distribuzione con quel centro. I quantili per quei pezzi generati possono formare l'intervallo di predizione (ma lo testerei ancora, potrebbe essere necessario ripetere il processo più volte e combinare).

Ecco un esempio di ciò aggiungendo deviazioni normali (poiché sappiamo che i dati originali hanno utilizzato una normale) alle previsioni con la deviazione standard basata sul MSE stimato dall'albero:

pred.rf.int2 <- sapply(1:4, function(i) {
  tmp <- pred.rf$individual[i, ] + rnorm(1001, 0, sqrt(fit2$mse))
  quantile(tmp, c(0.025, 0.975))
})
t(pred.rf.int2)
#           2.5%    97.5%
# [1,]  7.351609 17.31065
# [2,] 10.386273 20.23700
# [3,] 13.004428 23.55154
# [4,] 16.344504 24.35970

Questi intervalli contengono quelli basati su una conoscenza perfetta, quindi sembra ragionevole. Tuttavia, dipenderanno molto dalle ipotesi formulate (le ipotesi sono valide qui perché abbiamo usato la conoscenza di come i dati sono stati simulati, potrebbero non essere validi in casi di dati reali). Continuerei a ripetere più volte le simulazioni per dati che assomigliano più ai tuoi dati reali (ma simulati in modo da conoscere la verità) più volte prima di affidarmi completamente a questo metodo.


11

Mi rendo conto che questo è un vecchio post, ma ho eseguito alcune simulazioni su questo e ho pensato di condividere i miei risultati.

[μ+σ,μσ][μ+1.96σ,μ1.96σ]

Apportando questa modifica al codice @GregSnow, otteniamo i seguenti risultati

set.seed(1)
x1 <- rep( 0:1, each=500 )
x2 <- rep( 0:1, each=250, length=1000 )
y <- 10 + 5*x1 + 10*x2 - 3*x1*x2 + rnorm(1000)

library(randomForest)
fit2 <- randomForest(y~x1+x2)
pred.rf <- predict(fit2, newdat, predict.all=TRUE)
pred.rf.int <- t(apply( pred.rf$individual, 1, function(x){ 
  c( mean(x) + c(-1.96,1.96)*sd(x), quantile(x, c(0.025,0.975)) )}))

pred.rf.int
                          2.5%    97.5%
1  7.826896 16.05521  9.915482 15.31431
2 11.010662 19.35793 12.298995 18.64296
3 14.296697 23.61657 14.749248 21.11239
4 18.000229 23.73539 18.237448 22.10331

Ora, confrontandoli con gli intervalli generati aggiungendo la deviazione normale alle previsioni con la deviazione standard come MSE come @GregSnow ha suggerito di ottenere,

pred.rf.int2 <- sapply(1:4, function(i) {
   tmp <- pred.rf$individual[i,] + rnorm(1000, 0, sqrt(fit2$mse))
   quantile(tmp, c(0.025, 0.975))
   })
t(pred.rf.int2)
          2.5%    97.5%
[1,]  7.486895 17.21144
[2,] 10.551811 20.50633
[3,] 12.959318 23.46027
[4,] 16.444967 24.57601

L'intervallo di entrambi questi approcci ora sembra molto vicino. Tracciare l'intervallo di previsione per i tre approcci rispetto alla distribuzione degli errori in questo caso appare come di seguito

inserisci qui la descrizione dell'immagine

  • Linee nere = intervalli di predizione dalla regressione lineare,
  • Linee rosse = intervalli casuali della foresta calcolati su pronostici individuali,
  • Linee blu = intervalli casuali della foresta calcolati aggiungendo una deviazione normale alle previsioni

Ora, eseguiamo nuovamente la simulazione, ma questa volta aumentando la varianza del termine di errore. Se i nostri calcoli dell'intervallo di previsione sono buoni, dovremmo finire con intervalli più ampi rispetto a quanto sopra.

set.seed(1)
x1 <- rep( 0:1, each=500 )
x2 <- rep( 0:1, each=250, length=1000 )
y <- 10 + 5*x1 + 10*x2 - 3*x1*x2 + rnorm(1000,mean=0,sd=5)

fit1 <- lm(y~x1+x2)
newdat <- expand.grid(x1=0:1,x2=0:1)
predict(fit1,newdata=newdat,interval = "prediction")
      fit       lwr      upr
1 10.75006  0.503170 20.99695
2 13.90714  3.660248 24.15403
3 19.47638  9.229490 29.72327
4 22.63346 12.386568 32.88035

set.seed(1)
fit2 <- randomForest(y~x1+x2,localImp=T)
pred.rf.int <- t(apply( pred.rf$individual, 1, function(x){ 
  c( mean(x) + c(-1.96,1.96)*sd(x), quantile(x, c(0.025,0.975)) )}))
pred.rf.int
                          2.5%    97.5%
1  7.889934 15.53642  9.564565 15.47893
2 10.616744 18.78837 11.965325 18.51922
3 15.024598 23.67563 14.724964 21.43195
4 17.967246 23.88760 17.858866 22.54337

pred.rf.int2 <- sapply(1:4, function(i) {
   tmp <- pred.rf$individual[i,] + rnorm(1000, 0, sqrt(fit2$mse))
   quantile(tmp, c(0.025, 0.975))
   })
t(pred.rf.int2)
         2.5%    97.5%
[1,] 1.291450 22.89231
[2,] 4.193414 25.93963
[3,] 7.428309 30.07291
[4,] 9.938158 31.63777

inserisci qui la descrizione dell'immagine

Ora, questo chiarisce che il calcolo degli intervalli di previsione con il secondo approccio è molto più accurato e sta producendo risultati abbastanza vicini all'intervallo di previsione dalla regressione lineare.

μiMSEiN(μi,RMSEi)N(μi/n,RMSEi/n)

mean.rf <- pred.rf$aggregate
sd.rf <- mean(sqrt(fit2$mse))
pred.rf.int3 <- cbind(mean.rf - 1.96*sd.rf, mean.rf + 1.96*sd.rf)
pred.rf.int3
1  1.332711 22.09364
2  4.322090 25.08302
3  8.969650 29.73058
4 10.546957 31.30789

Queste coincidono molto bene con gli intervalli del modello lineare e anche con l'approccio suggerito da @GregSnow. Ma si noti che l'assunto sottostante in tutti i metodi che abbiamo discusso è che gli errori seguono una distribuzione normale.


10

Se usi R puoi facilmente produrre intervalli di previsione per le previsioni di una regressione di foreste casuali: basta usare il pacchetto quantregForest(disponibile presso CRAN ) e leggere l' articolo di N. Meinshausen su come inferire i quantili condizionali con le foreste di regressione quantile e come può essere utilizzato per costruire intervalli di previsione. Molto informativo anche se non lavori con R!



2
Questa sembra la risposta appropriata e non richiede ipotesi distributive relative all'intervallo predittivo. C'è un tutorial su come farlo in Python qui: blog.datadive.net/prediction-intervals-for-random-forests
colin

6

Questo è facile da risolvere con randomForest.

Prima lasciami occuparmi dell'attività di regressione (supponendo che la tua foresta abbia 1000 alberi). Nella predictfunzione, hai la possibilità di restituire risultati da singoli alberi. Ciò significa che riceverai un output di 1000 colonne. Possiamo prendere la media delle 1000 colonne per ogni riga: questa è la normale uscita RF prodotta in qualsiasi modo. Ora per ottenere l'intervallo di previsione diciamo +/- 2 std. le deviazioni tutto ciò che devi fare è, per ogni riga, dai 1000 valori calcolati +/- 2 std. deviazioni e rendi questi i tuoi limiti superiore e inferiore sulla tua previsione.

In secondo luogo, nel caso della classificazione, ricordare che ciascun albero produce 1 o 0 (per impostazione predefinita) e la somma su tutti i 1000 alberi divisi per 1000 dà la probabilità di classe (nel caso della classificazione binaria). Per impostare un intervallo di previsione sulla probabilità, è necessario modificare il valore min. opzione nodesize (vedi la documentazione randomForest per il nome esatto di quell'opzione) una volta impostato un valore >> 1, i singoli alberi genereranno numeri compresi tra 1 e 0. Ora, da qui in poi puoi ripetere lo stesso processo descritto sopra per l'attività di regressione.

Spero che abbia un senso.


Non l'ho provato ma sembra avere senso. Grazie per aver risposto alla mia vecchia domanda.
Decano MacGregor,

1
Penso che questo metodo darebbe qualcosa di più simile a un intervallo di confidenza di un intervallo di predizione. I risultati dovrebbero essere confrontati con un modello lineare in cui la teoria degli intervalli di previsione è ben consolidata. Meglio su alcuni dati simulati in cui la verità è nota e tutte le ipotesi valgono.
Greg Snow,

1
@GregSnow: Quello che otterrai da ciò che ho descritto sopra è sicuramente l'intervallo di previsione. Si noti che gli intervalli di predizione sono generalmente molto più ampi degli intervalli di confidenza poiché gli intervalli di confidenza specificano realmente dove si trova la statistica media di una quanitiy in quanto la predizione riguarda una sola osservazione, quindi una maggiore incertezza e quindi intervalli più ampi. Le 1000 previsioni che ricevi da 1000 alberi possono essere pensate come un campione avviato e non è necessario applicare ipotesi di normalità qui. Anche la semplice analisi del decile darà buoni risultati.

5
@SashikanthDareddy, Quello che otterrai da ciò che descrivi non è sicuramente un intervallo di predizione. Un intervallo di previsione è determinato da qualcosa di più del semplice essere più ampio. Sì, i singoli alberi formano un bootstrap, ma il bootstrap stima i parametri, non i singoli valori. L'intervallo di predizione dipende molto dalla distribuzione dei singoli punti. Il fatto che il tuo metodo dia un intervallo per le proporzioni con un risultato categorico invece delle categorie lo dimostra. Vedi il mio esempio nella risposta aggiunta.
Greg Snow,

0

Ho provato alcune opzioni (tutto questo WIP):

  1. In realtà ho reso la variabile dipendente un problema di classificazione con i risultati come intervalli, anziché un singolo valore. I risultati ottenuti sono stati scarsi, rispetto all'utilizzo di un valore semplice. Ho rinunciato a questo approccio.

  2. L'ho quindi convertito in più problemi di classificazione, ognuno dei quali era un limite inferiore per l'intervallo (il risultato del modello era se avrebbe attraversato il limite inferiore o meno) e quindi ho eseguito tutti i modelli (~ 20), quindi combinato il risultato per ottenere una risposta finale come intervallo. Funziona meglio di 1 sopra ma non è buono come ne ho bisogno. Sto ancora lavorando per migliorare questo approccio.

Ho usato le stime OOB e di esclusione per decidere quanto sono buoni / cattivi i miei modelli.


0

Il problema di costruire intervalli di previsione per previsioni casuali di foreste è stato affrontato nel seguente documento:

Zhang, Haozhe, Joshua Zimmerman, Dan Nettleton e Daniel J. Nordman. "Intervalli di previsione della foresta casuale". The American Statistician, 2019.

Il pacchetto R "rfinterval" è la sua implementazione disponibile presso CRAN.

Installazione

Per installare il pacchetto R rfinterval :

#install.packages("devtools")
#devtools::install_github(repo="haozhestat/rfinterval")
install.packages("rfinterval")
library(rfinterval)
?rfinterval

uso

Avvio veloce:

train_data <- sim_data(n = 1000, p = 10)
test_data <- sim_data(n = 1000, p = 10)

output <- rfinterval(y~., train_data = train_data, test_data = test_data,
                     method = c("oob", "split-conformal", "quantreg"),
                     symmetry = TRUE,alpha = 0.1)

### print the marginal coverage of OOB prediction interval
mean(output$oob_interval$lo < test_data$y & output$oob_interval$up > test_data$y)

### print the marginal coverage of Split-conformal prediction interval
mean(output$sc_interval$lo < test_data$y & output$sc_interval$up > test_data$y)

### print the marginal coverage of Quantile regression forest prediction interval
mean(output$quantreg_interval$lo < test_data$y & output$quantreg_interval$up > test_data$y)

Esempio di dati:

oob_interval <- rfinterval(pm2.5 ~ .,
                            train_data = BeijingPM25[1:1000, ],
                            test_data = BeijingPM25[1001:2000, ],
                            method = "oob",
                            symmetry = TRUE,
                            alpha = 0.1)
str(oob_interval)

1
Benvenuto nel sito, @ xiaolongmao.Potresti voler fare il nostro tour . Non inviare risposte identiche a più thread. Prova a personalizzare le tue risposte alla domanda specifica su ogni thread. Se hai un caso in cui credi davvero che una risposta identica risponda completamente alla domanda, ciò implica che la domanda è un duplicato. Quando raggiungi la reputazione di 50, puoi pubblicare un commento all'OP. Nel frattempo, puoi contrassegnare la Q per la chiusura come duplicato.
gung - Ripristina Monica
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.