2016-06-17 27 views
8

Non capisco che è la differenza tra varImp funzione (caret pacchetto) e importance funzione (randomForest pacchetto) per un modello Foresta a caso:Differenza tra varImp (accento circonflesso) e l'importanza (foresta casuale) per la foresta a caso

I calcolato un semplice modello di classificazione RF e quando si calcola variabile importante, ho trovato che la "classifica" dei predittori non era lo stesso per entrambe le funzioni:

Ecco il mio codice:

rfImp <- randomForest(Origin ~ ., data = TAll_CS, 
         ntree = 2000, 
         importance = TRUE) 

importance(rfImp) 

           BREAST  LUNG MeanDecreaseAccuracy MeanDecreaseGini 
Energy_GLCM_R1SC4NG3  -1.44116806 2.8918537   1.0929302  0.3712622 
Contrast_GLCM_R1SC4NG3  -2.61146974 1.5848150   -0.4455327  0.2446930 
Entropy_GLCM_R1SC4NG3  -3.42017102 3.8839464   0.9779201  0.4170445 
... 

varImp(rfImp) 
           BREAST  LUNG 
Energy_GLCM_R1SC4NG3   0.72534283 0.72534283 
Contrast_GLCM_R1SC4NG3  -0.51332737 -0.51332737 
Entropy_GLCM_R1SC4NG3  0.23188771 0.23188771 
... 

Pensavo che usassero lo stesso "algoritmo" ma non ne sono sicuro ora.

EDIT

Per riprodurre il problema, il ionosphere set di dati (pacchetto kknn) può essere utilizzato:

library(kknn) 
data(ionosphere) 
rfImp <- randomForest(class ~ ., data = ionosphere[,3:35], 
         ntree = 2000, 
         importance = TRUE) 
importance(rfImp) 
      b  g MeanDecreaseAccuracy MeanDecreaseGini 
V3 21.3106205 42.23040    42.16524  15.770711 
V4 10.9819574 28.55418    29.28955   6.431929 
V5 30.8473944 44.99180    46.64411  22.868543 
V6 11.1880372 33.01009    33.18346   6.999027 
V7 13.3511887 32.22212    32.66688  14.100210 
V8 11.8883317 32.41844    33.03005   7.243705 
V9 -0.5020035 19.69505    19.54399   2.501567 
V10 -2.9051578 22.24136    20.91442   2.953552 
V11 -3.9585608 14.68528    14.11102   1.217768 
V12 0.8254453 21.17199    20.75337   3.298964 
... 

varImp(rfImp) 
      b   g 
V3 31.770511 31.770511 
V4 19.768070 19.768070 
V5 37.919596 37.919596 
V6 22.099063 22.099063 
V7 22.786656 22.786656 
V8 22.153388 22.153388 
V9 9.596522 9.596522 
V10 9.668101 9.668101 
V11 5.363359 5.363359 
V12 10.998718 10.998718 
... 

penso che mi manca qualcosa ...

EDIT 2

Ho capito che se si fare la media di ogni riga dei primi due colonne di importance(rfImp), si ottengono i risultati di varImp(rfImp):

impRF <- importance(rfImp)[,1:2] 
apply(impRF, 1, function(x) mean(x)) 
     V3  V4  V5  V6  V7  V8  V9 
31.770511 19.768070 37.919596 22.099063 22.786656 22.153388 9.596522 
     V10  V11  V12 
9.668101 5.363359 10.998718  ... 

# Same result as in both columns of varImp(rfImp) 

Non so perché questo sta accadendo, ma ci deve essere una spiegazione per questo.

+0

Un esempio riproducibile è necessario affinché le persone rispondano esattamente alla domanda. – topepo

+0

Siamo spiacenti. Ho trovato che lo stesso problema si verifica quando si utilizza il set di dati 'ionosphere'. Ho intenzione di modificare la domanda –

+0

@topepo, qual è la tua opinione? Spero che tu possa aiutare a spiegare le differenze .. –

risposta

7

Se camminiamo attraverso il metodo per varImp:

Controllare l'oggetto:

> getFromNamespace('varImp','caret') 
function (object, ...) 
{ 
    UseMethod("varImp") 
} 

Prendi il Metodo S3:

> getS3method('varImp','randomForest') 
function (object, ...) 
{ 
    code <- varImpDependencies("rf") 
    code$varImp(object, ...) 
} 
<environment: namespace:caret> 


code <- caret:::varImpDependencies('rf') 

> code$varImp 
function(object, ...){ 
        varImp <- randomForest::importance(object, ...) 
        if(object$type == "regression") 
         varImp <- data.frame(Overall = varImp[,"%IncMSE"]) 
        else { 
         retainNames <- levels(object$y) 
         if(all(retainNames %in% colnames(varImp))) { 
         varImp <- varImp[, retainNames] 
         } else { 
         varImp <- data.frame(Overall = varImp[,1]) 
         } 
        } 

        out <- as.data.frame(varImp) 
        if(dim(out)[2] == 2) { 
         tmp <- apply(out, 1, mean) 
         out[,1] <- out[,2] <- tmp 
        } 
        out 
        } 

Quindi questo non è strettamente tornando foresta casuale :: importanza ,

Inizia calcolando quello, ma poi seleziona solo la val categoriale quelli che si trovano nel set di dati.

poi lo fa qualcosa di interessante, controlla se abbiamo solo due colonne:

if(dim(out)[2] == 2) { 
    tmp <- apply(out, 1, mean) 
    out[,1] <- out[,2] <- tmp 
} 

Secondo la pagina man varImp:

a caso Foresta: varImp.randomForest e varImp .RandomForest sono i wrapper attorno alle funzioni di importanza dei pacchetti di partito randomForest e , rispettivamente.

Questo chiaramente non è il caso.


Sul perché ...

Se abbiamo solo due valori, l'importanza della variabile come predittore può essere rappresentato come un valore.

Se la variabile è un predittore di g, allora deve anche essere un predittore di b

ha senso, ma questo non va bene per la loro documentazione su ciò che fa la funzione, quindi vorrei probabilmente segnalarlo come comportamento inaspettato. La funzione sta tentando di aiutare quando ci si aspetta di fare il calcolo relativo da soli.

+0

Aggiunta rapida al "Per quanto riguarda il motivo ...". 'randomForest :: importance()' aggrega i punteggi di importanza specifica della classe usando una media ponderata prima di ridimensionarli usando il loro "errore standard" e riportandolo come "meanDecreaseAccuracy". 'varImp()' prende (di default) i punteggi specifici della classe in scala e li calcola in media senza peso. Per una distribuzione di classi non equa, la prima sembra più vicina all'importanza per l'accuratezza generale, la seconda è distorta a favore delle classi rare. C'è qualche trattamento teorico di questo? – joha

+0

@joha Avete un esempio di pregiudizio in termini di classi rare? (Non sono sicuro da dove viene la media, ci sono altri modi per combinare i due valori in uno, perché il significato?). Inoltre, il mio commento audace è ovviamente vero in un caso di 2 oggetti, ma non sono sicuro che non dovrebbe avere un impatto con più classi pure. Implica un'ulteriore informazione e 1 meno grado di libertà in ogni numero di classi. – Shape

+0

Ho aggiunto una risposta per spiegare cosa intendo, forse potresti controllare se ha senso. Una correzione al commento precedente: The randomForest :: importance() non esegue l'aggregazione dei punteggi di importanza specifica della classe utilizzando una media ponderata. – joha

2

Non ho i dati esatti, ma utilizzando dati fittizi (vedi sotto) Non riesco a riprodurre questo comportamento. Forse ricontrolla che non hai fatto nient'altro che possa influenzare i tuoi risultati. Quale versione di R e caret usi?

library(caret) 
library(randomForest) 

# classification - same result 
rfImp1 <- randomForest(Species ~ ., data = iris[,1:5], 
        ntree = 2000, 
        importance = TRUE) 
importance(rfImp1) 
varImp(rfImp1) 

# regression - same result 
rfImp2 <- randomForest(Sepal.Length ~ ., data = iris[,1:4], 
        ntree = 2000, 
        importance = TRUE) 
importance(rfImp2) 
varImp(rfImp2) 

Aggiornamento:

Utilizzando i dati Ionosphere questo è riproducibile:

library(caret) 
library(randomForest) 
library(mlbench) 
data(Ionosphere) 
str(Ionosphere) 
rfImp1 <- randomForest(Class ~ ., data = Ionosphere[,3:35], ntree = 2000, importance = TRUE) 

... con questi risultati:

> head(importance(rfImp1)) 

     bad  good MeanDecreaseAccuracy MeanDecreaseGini 
V3 20.545836 41.43872    41.26313  15.308791 
V4 10.615291 29.31543    29.58395   6.226591 
V5 29.508581 44.86784    46.79365  21.757928 
V6 9.231544 31.77881    31.48614   7.201694 
V7 12.461476 34.39334    34.92728  14.802564 
V8 12.944721 32.49392    33.35699   6.971502 

> head(varImp(rfImp1)) 

     bad  good 
V3 30.99228 30.99228 
V4 19.96536 19.96536 
V5 37.18821 37.18821 
V6 20.50518 20.50518 
V7 23.42741 23.42741 
V8 22.71932 22.71932 

La mia ipotesi è che accento circonflesso e randomForest usa solo diversi modi di agg Regolando i risultati di diverse esecuzioni per ogni variabile, ma @topepo molto probabilmente ti darà una risposta esatta in ogni caso.

+1

Ciao @geekoverdose! Ho usato il set di dati 'iris' e l'importanza è la stessa per entrambe le funzioni, come hai detto tu. Ho provato con altri set di dati per riprodurre il problema e ho scoperto che se uso il set di dati 'ionosphere', entrambe le funzioni danno risultati di importanza diversa, come accennavo nella mia domanda. 'rfImp1 <- randomForest (classe ~., Data = ionosphere [, 3: 35], ntree = 2000, importanza = TRUE)' La mia versione R è 3.2.5 e la versione 'caret' è 6.0.68 –

3

Questa risposta è intesa come aggiunta alla soluzione da parte di @Shape. Penso che importance segua il noto approccio di Breiman per calcolare l'importanza variabile riportata come MeanDecreaseAccuracy, cioè per l'esemplare out-of-bag di ogni albero calcolare l'accuratezza dell'albero, quindi permutare le variabili una dopo l'altra e misurare la precisione dopo la permutazione per calcolare la diminuzione della precisione senza quella variabile.
Non sono stato in grado di trovare molte informazioni su come viene calcolato esattamente il decremento della precisione specifico della classe nelle prime colonne, ma presumo che sia classe prevista k/classe totale prevista k.

Come spiega @Shape, varImp non riporta le MeanDecreaseAccuracy riportato da importance, ma invece calcola la media delle diminuzioni specifiche della classe (scala) di accuratezza e dei rapporti per ciascuna delle classi. (Per più di 2 classi, varImp segnala solo la diminuzione della precisione specifica della classe.)
Questo approccio è simile solo se la distribuzione della classe è uguale. Il motivo è che solo in un caso equilibrato una diminuzione dell'accuratezza di una classe riduce ugualmente la precisione nell'altra classe.

library(caret) 
library(randomForest) 
library(mlbench) 

### Balanced sample size ### 
data(Ionosphere) 
rfImp1 <- randomForest(Class ~ ., data = Ionosphere[,3:35], ntree = 1000, importance = TRUE) 

# How importance() calculates the overall decerase in accuracy for the variable 
Imp1 <- importance(rfImp1, scale = FALSE) 
summary(Ionosphere$Class)/nrow(Ionosphere) 
classRatio1 <- summary(Ionosphere$Class)/nrow(Ionosphere) 
#  bad  good 
#0.3589744 0.6410256 

# Caret calculates a simple mean 
varImp(rfImp1, scale = FALSE)["V3",] # 0.04542253 
Imp1["V3", "bad"] * 0.5 + Imp1["V3", "good"] * 0.5 # 0.04542253 
# importance is closer to the weighted average of class importances 
Imp1["V3", ] # 0.05262225 
Imp1["V3", "bad"] * classRatio1[1] + Imp1["V3", "good"] * classRatio1[2] # 0.05274091 

### Equal sample size ### 
Ionosphere2 <- Ionosphere[c(which(Ionosphere$Class == "good"), sample(which(Ionosphere$Class == "bad"), 225, replace = TRUE)),] 
summary(Ionosphere2$Class)/nrow(Ionosphere2) 
classRatio2 <- summary(Ionosphere2$Class)/nrow(Ionosphere2) 
# bad good 
# 0.5 0.5 

rfImp2 <- randomForest(Class ~ ., data = Ionosphere2[,3:35], ntree = 1000, importance = TRUE) 
Imp2 <- importance(rfImp2, scale = FALSE) 

# Caret calculates a simple mean 
varImp(rfImp2, scale = FALSE)["V3",] # 0.06126641 
Imp2["V3", "bad"] * 0.5 + Imp2["V3", "good"] * 0.5 # 0.06126641 
# As does the average adjusted for the balanced class ratio 
Imp2["V3", "bad"] * classRatio2[1] + Imp2["V3", "good"] * classRatio2[2] # 0.06126641 
# There is now not much difference between the measure for balanced classes 
Imp2["V3",] # 0.06106229 

Credo che questo può essere interpretato come segno di omissione di mettere lo stesso peso su tutte le classi, mentre importance rapporti variabili come più importante se sono importanti per la classe più comune. Sono tendenzialmente d'accordo con Max Kuhn su questo, ma la differenza dovrebbe essere spiegata da qualche parte nella documentazione.

Problemi correlati