2016-06-17 46 views
8

nie rozumiem, co jest różnica między varImp funkcji (caret pakietu) i importance funkcji (randomForest pakietu) dla modelu Losowe lasu:Różnica między varImp (daszek) i wagi (lasy losowe) dla Losowe Las

I obliczane prostego modelu klasyfikacyjnego RF i przy obliczaniu zmiennej znaczenie, okazało się, że „ranking” przewidywaczy nie była taka sama dla obu funkcji:

Oto mój kod:

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

Myślałem, że użyli tego samego "algorytmu", ale nie jestem teraz pewien.

EDIT

W celu odtworzenia problemu, ionosphere zbiór danych (pakiet kknn) można stosować:

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

Myślę, że jestem brakuje czegoś ...

EDIT 2

Odkryłem, że jeśli ty zrobić średnią z każdego rzędu pierwszych dwóch kolumnach importance(rfImp), otrzymasz wyniki 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) 

Nie wiem, dlaczego tak się dzieje, ale nie musi być wyjaśnieniem tego.

+0

Potrzebny jest powtarzalny przykład, aby ludzie mogli dokładnie odpowiedzieć na pytanie. – topepo

+0

Przepraszamy. Odkryłem, że ten sam problem występuje podczas korzystania z zestawu danych 'ionosphere'. Zamierzam edytować pytanie –

+0

@topepo, jaka jest Twoja opinia? Mam nadzieję, że pomożesz w wyjaśnieniu różnic. –

Odpowiedz

7

Jeśli idziemy przez sposobie varImp:

Sprawdź przedmiot:

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

Get Method 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 
        } 

Więc to nie jest ściśle powracającego lasy losowe :: znaczenie ,

Zaczyna się od obliczenia, ale następnie wybiera tylko kategoryczny val które są w zbiorze danych.

Wtedy to ma coś ciekawego, sprawdza jeśli mamy tylko dwie kolumny:

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

Według strony man varImp:

Losowe lasu: varImp.randomForest i varImp .RandomForest to owijki wokół ważnych funkcji z pakietów imprezowych randomForest i .

Oczywiście tak nie jest.


Jako dlaczego ...

Jeśli mamy tylko dwie wartości, znaczenie zmiennej jako czynnik prognostyczny może być reprezentowana jako jedną wartość.

Jeśli zmienna jest predyktorem g, to musi to być predyktorem b

To nie ma sensu, ale to nie pasuje do ich dokumentacji, co robi funkcja, więc chciałbym prawdopodobnie zgłosić to jako nieoczekiwane zachowanie. Funkcja próbuje pomóc, gdy sam podejmiesz się wykonania obliczeń względnych.

+0

Szybki dodatek do "Co do ...". 'randomForest :: importance()' agreguje oceny ważności specyficzne dla klasy za pomocą ważonej średniej przed ich przeskalowaniem przy użyciu "błędu standardowego" i zgłasza ją jako "meanDecreaseAccuracy". 'varImp()' przyjmuje (domyślnie) skalowane wyniki specyficzne dla klasy i uśrednia je bez ważenia. W przypadku nierównego podziału na klasy pierwszy wydaje się bliższy znaczeniu dla ogólnej dokładności, drugi jest stronniczy na rzecz rzadkich klas. Czy istnieje jakieś teoretyczne podejście do tego? – joha

+0

@joha Czy masz przykład stronniczości w kategoriach rzadkich klas? (Nie jestem pewien, skąd pochodzi ten środek, istnieją inne sposoby na połączenie dwóch wartości w jedną, dlaczego średnia?). Ponadto, mój pogrubiony komentarz jest oczywiście prawdziwy w przypadku 2 obiektów, ale nie jestem pewien, czy nie powinien on mieć wpływu również na więcej klas. Oznacza to dodatkową informację i 1 mniejszy stopień swobody na każdej liczbie klas. – Shape

+0

Dodałem odpowiedź, aby wyjaśnić, co mam na myśli, może mógłbyś sprawdzić, czy ma to sens. Jedna korekta do poprzedniego komentarza: randomforest :: importance() _nie powoduje, że wyniki ważenia specyficzne dla klasy są oparte na średniej ważonej. – joha

2

Nie mam dokładnych danych, ale używając danych fikcyjnych (patrz poniżej) nie mogę odtworzyć tego zachowania. Może sprawdź jeszcze raz, czy naprawdę nie zrobiłeś nic, co mogłoby wpłynąć na twoje wyniki. Którą wersję R i caret używasz?

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) 

Aktualizacja:

Wykorzystując dane Ionosphere ten jest powtarzalny:

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

... z tymi wynikami:

> 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 

Moje przypuszczenie byłoby, że karetka i randomForest po prostu używają różnych sposobów ag reguła wyników z różnych przebiegów dla każdej zmiennej - ale @topepo najprawdopodobniej da ci teraz dokładną odpowiedź.

+1

Hi @geekoverdose! Użyłem zestawu danych "tęczówki" i znaczenie jest takie samo dla obu funkcji, jak powiedziałeś. Próbowałem z innym zbiorem danych, aby odtworzyć problem i odkryłem, że jeśli używam zbioru danych 'ionosphere', obie funkcje dają różne wyniki ważności, jak wspomnę w moim pytaniu. 'rfImp1 <- randomForest (klasa ~., Data = jonosfera [, 3: 35], ntree = 2000, znaczenie = PRAWDA)' Moja wersja R to 3.2.5, a wersja 'caret' to 6.0.68 –

3

Ta odpowiedź jest przeznaczona jako dodatek do rozwiązania autorstwa @Shape. Myślę, że importance jest zgodne ze znanym podejściem Breimana do obliczenia zmiennej ważności, o której donosi się jako MeanDecreaseAccuracy, tzn. Dla próbki poza każdym workiem obliczyć dokładność drzewa, a następnie przesłać zmienne jeden po drugim i zmierzyć dokładność po permutacji, aby obliczyć spadek dokładności bez tej zmiennej.
Nie byłem w stanie znaleźć wielu informacji o tym, jak dokładnie obliczana jest dokładność specyficzna dla klasy w pierwszych kolumnach, ale zakładam, że jest to poprawnie przewidziana klasa k/przewidywana klasa k.

Jak wyjaśnia @Shape, varImp nie zgłasza raportowany MeanDecreaseAccuracy przez importance, lecz oblicza średnią z (skalowane) Klasa specyficzne spadku dokładności i raportów to dla każdej z klas. (Dla więcej niż 2 klas, varImp zgłasza tylko specyficzny dla klasy spadek dokładności.)
To podejście jest podobne tylko wtedy, gdy rozkład klas jest równy. Powodem jest to, że tylko w przypadku zrównoważonym spadek dokładności jednej klasy zmniejsza jednocześnie dokładność w drugiej klasie.

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 

Wierzę, że to może być interpretowane jako karetki oddanie równą wagę na wszystkich zajęciach, natomiast importance raporty zmienne jak ważniejsze, jeżeli są one istotne dla bardziej wspólnej klasie. Zgadzam się na to z Maxem Kuhnem, ale różnicę należy wyjaśnić gdzieś w dokumentacji.