R: Cosa vedo nei grafici di dipendenza parziale di gbm e RandomForest?


14

In realtà, pensavo di aver capito cosa si può mostrare con un diagramma di dipendenza parziale, ma usando un esempio ipotetico molto semplice, sono rimasto piuttosto perplesso. Nel seguente pezzo di codice a generare tre variabili indipendenti ( un , b , c ) e una variabile dipendente ( y ) con c mostra una stretta relazione lineare con y , mentre un e b sono correlati con y . Faccio un'analisi di regressione con un albero di regressione potenziato usando il pacchetto R gbm:

a <- runif(100, 1, 100)
b <- runif(100, 1, 100)
c <- 1:100 + rnorm(100, mean = 0, sd = 5)
y <- 1:100 + rnorm(100, mean = 0, sd = 5)
par(mfrow = c(2,2))
plot(y ~ a); plot(y ~ b); plot(y ~ c)
Data <- data.frame(matrix(c(y, a, b, c), ncol = 4))
names(Data) <- c("y", "a", "b", "c")
library(gbm)
gbm.gaus <- gbm(y ~ a + b + c, data = Data, distribution = "gaussian")
par(mfrow = c(2,2))
plot(gbm.gaus, i.var = 1)
plot(gbm.gaus, i.var = 2)
plot(gbm.gaus, i.var = 3)

Non sorprendentemente, per le variabili a e b piazzole dipendenza parziali cedere linee orizzontali intorno alla media di un . Quello che puzzle è la trama per la variabile c . Ottengo linee orizzontali per gli intervalli c <40 e c > 60 e l'asse y è limitato ai valori vicini alla media di y . Poiché un e b sono completamente estranei alla y (e quindi non variabile importanza nel modello è 0), mi aspettavo che cmostrerebbe una dipendenza parziale lungo tutto il suo raggio anziché quella forma sigmoidea per un intervallo molto limitato dei suoi valori. Ho cercato di trovare informazioni in Friedman (2001) "Approssimazione di funzioni avide: una macchina per aumentare il gradiente" e in Hastie et al. (2011) "Elementi di apprendimento statistico", ma le mie capacità matematiche sono troppo basse per comprendere tutte le equazioni e le formule in essi contenute. Quindi la mia domanda: cosa determina la forma del diagramma di dipendenza parziale per la variabile c ? (Spiega in parole comprensibili a un non matematico!)

AGGIUNTO il 17 aprile 2014:

In attesa di una risposta, ho usato gli stessi dati di esempio per un'analisi con R-package randomForest. Le trame dipendenza parziali di foresta casuale assomigliano molto più di quanto mi aspettassi dalle trame GBM: la dipendenza parziale di variabili esplicative a e b variano casualmente e strettamente circa 50, mentre esplicative variabile c dipendenza spettacoli parziale su tutta la gamma (e su quasi intera gamma di y ). Quali potrebbero essere le ragioni di queste diverse forme dei diagrammi di dipendenza parziale in gbme randomForest?

grafici parziali di gbm e randomForest

Ecco il codice modificato che confronta i grafici:

a <- runif(100, 1, 100)
b <- runif(100, 1, 100)
c <- 1:100 + rnorm(100, mean = 0, sd = 5)
y <- 1:100 + rnorm(100, mean = 0, sd = 5)
par(mfrow = c(2,2))
plot(y ~ a); plot(y ~ b); plot(y ~ c)
Data <- data.frame(matrix(c(y, a, b, c), ncol = 4))
names(Data) <- c("y", "a", "b", "c")

library(gbm)
gbm.gaus <- gbm(y ~ a + b + c, data = Data, distribution = "gaussian")

library(randomForest)
rf.model <- randomForest(y ~ a + b + c, data = Data)

x11(height = 8, width = 5)
par(mfrow = c(3,2))
par(oma = c(1,1,4,1))
plot(gbm.gaus, i.var = 1)
partialPlot(rf.model, Data[,2:4], x.var = "a")
plot(gbm.gaus, i.var = 2)
partialPlot(rf.model, Data[,2:4], x.var = "b")
plot(gbm.gaus, i.var = 3)
partialPlot(rf.model, Data[,2:4], x.var = "c")
title(main = "Boosted regression tree", outer = TRUE, adj = 0.15)
title(main = "Random forest", outer = TRUE, adj = 0.85)

1
Potresti voler sintonizzare effettivamente gli iperparametri con un tocco. Non sono sicuro di quale sia il numero predefinito di alberi in gbm, ma potrebbe essere così piccolo da non avere il tempo di imparare una curvatura sana.
Shea Parkes,

@Shea Parkes - Hai ragione. Il numero predefinito di alberi è 100 che non era abbastanza per generare un buon modello. Con 2000 alberi, i diagrammi di dipendenza parziale di gbm e foresta casuale sono quasi identici.
user7417

Risposte:


7

Ho trascorso un po 'di tempo a scrivere il mio "parziale. Function-plotter" prima di rendermi conto che era già raggruppato nella libreria R randomForest.

[EDIT ... ma poi ho trascorso un anno a creare il pacchetto CRAN forestFloor , che secondo me è significativamente migliore dei classici diagrammi di dipendenza parziale]

Il diagramma Partial.function è ottimo in casi come questo esempio di simulazione che mostri qui, in cui la variabile esplicativa non interagisce con altre variabili. Se ogni variabile che spiega contribuisce in modo addizionale al target-Y con una funzione sconosciuta, questo metodo è ottimo per mostrare quella funzione nascosta stimata. Vedo spesso un tale appiattimento nei confini delle funzioni parziali.

Alcuni motivi: randomForsest ha un argomento chiamato 'nodesize = 5', il che significa che nessun albero suddivide un gruppo di 5 membri o meno. Pertanto ogni albero non può distinguere con ulteriore precisione. Il livello di insacco / bootstrap di insiemi smussa votando le numerose funzioni a gradini dei singoli alberi, ma solo nel mezzo dell'area dati. In prossimità dei bordi dei dati rappresentati dallo spazio, l '"ampiezza" della funzione parziale cadrà. Impostare nodesize = 3 e / o ottenere più osservazioni rispetto al rumore può ridurre questo effetto di flatting del bordo ... Quando il rapporto segnale-rumore scende in generale nella foresta casuale, la scala delle previsioni si condensa. Pertanto le previsioni non sono assolutamente accurate, ma sono solo linearmente correlate al target. Puoi vedere i valori aeb come esempi di rapporto segnale-rumore estremamente basso, e quindi queste funzioni parziali sono molto piatte. È una bella caratteristica della foresta casuale che già dalla gamma di previsioni del set di allenamento puoi indovinare quanto bene il modello stia funzionando. OOB.predictions è fantastico anche ..

l'appiattimento del grafico parziale in regioni senza dati è ragionevole: poiché la foresta casuale e il CART sono modelli basati sui dati, mi piace personalmente il concetto che questi modelli non estrapolano. Quindi la previsione di c = 500 o c = 1100 è esattamente la stessa di c = 100 o nella maggior parte dei casi anche c = 98.

Ecco un esempio di codice con l'appiattimento del bordo ridotto:

Non ho provato il pacchetto gbm ...

ecco un codice illustrativo basato sul tuo esempio ...

#more observations are created...
a <- runif(5000, 1, 100)
b <- runif(5000, 1, 100)
c <- (1:5000)/50 + rnorm(100, mean = 0, sd = 0.1)
y <- (1:5000)/50 + rnorm(100, mean = 0, sd = 0.1)
par(mfrow = c(1,3))
plot(y ~ a); plot(y ~ b); plot(y ~ c)
Data <- data.frame(matrix(c(y, a, b, c), ncol = 4))
names(Data) <- c("y", "a", "b", "c")
library(randomForest)
#smaller nodesize "not as important" when there number of observartion is increased
#more tress can smooth flattening so boundery regions have best possible signal to             noise, data specific how many needed

plot.partial = function() {
partialPlot(rf.model, Data[,2:4], x.var = "a",xlim=c(1,100),ylim=c(1,100))
partialPlot(rf.model, Data[,2:4], x.var = "b",xlim=c(1,100),ylim=c(1,100))
partialPlot(rf.model, Data[,2:4], x.var = "c",xlim=c(1,100),ylim=c(1,100))
}

#worst case! : with 100 samples from Data and nodesize=30
rf.model <- randomForest(y ~ a + b + c, data = Data[sample(5000,100),],nodesize=30)
plot.partial()

#reasonble settings for least partial flattening by few observations: 100 samples and nodesize=3 and ntrees=2000
#more tress can smooth flattening so boundery regions have best possiblefidelity
rf.model <- randomForest(y ~ a + b + c, data = Data[sample(5000,100),],nodesize=5,ntress=2000)
plot.partial()

#more observations is great!
rf.model <- randomForest(y ~ a + b + c,
 data = Data[sample(5000,5000),],
 nodesize=5,ntress=2000)
plot.partial()

4

Come menzionato nei commenti sopra, il modello gbm sarebbe migliore con alcuni parametri di regolazione. Un modo semplice per individuare i problemi nel modello e la necessità di tali parametri è generare alcuni grafici diagnostici. Ad esempio, per il modello gbm sopra con i parametri predefiniti (e usando il pacchetto plotmo per creare i grafici) abbiamo

gbm.gaus <- gbm(y~., data = Data, dist = "gaussian")
library(plotmo)   # for the plotres function
plotres(gbm.gaus) # plot the error per ntrees and the residuals

che dà

tracciare

Nel diagramma a sinistra vediamo che la curva di errore non ha toccato il fondo. E nella trama di destra i residui non sono ciò che vorremmo.

Se ricostruiamo il modello con un numero maggiore di alberi

gbm.gaus1 <- gbm(y~., data = Data, dist = "gaussian",
                 n.trees=5000, interact=3)
plotres(gbm.gaus1)

noi abbiamo

tracciare

Vediamo la curva di errore dal basso con un gran numero di alberi e la trama dei residui è più sana. Possiamo anche tracciare i grafici di dipendenza parziale per il nuovo modello gbm e il modello di foresta casuale

library(plotmo)
plotmo(gbm.gaus1, pmethod="partdep", all1=TRUE, all2=TRUE)
plotmo(rf.model,  pmethod="partdep", all1=TRUE, all2=TRUE)

che dà

tracciare

I grafici gbm e modelli casuali di foreste sono ora simili, come previsto.


3

È necessario aggiornare il interaction.depthparametro quando si crea il modello potenziato. Il valore predefinito è 1 e ciò causerà la gbmdivisione di tutti gli alberi che l' algoritmo costruisce una sola volta ciascuno. Ciò significherebbe che ogni albero si sta semplicemente dividendo su variabile ce, a seconda del campione di osservazioni che utilizza, si dividerà da qualche parte tra 40 e 60.

Ecco i grafici parziali con interaction.depth = 3

inserisci qui la descrizione dell'immagine


buon punto, lo è
Soren Havelund Welling,
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.