2016-06-17 2 views
8

Я не понимаю, что разница между varImp функцией (caret пакетом) и importance функцией (randomForest пакетом) для модели Random Forest:Разница между varImp (каретки) и значением (RandomForest) для случайных лес

I вычислена простая радиочастотная модель классификации и при вычислении переменного значения, я обнаружил, что «рейтинг» предсказатели не было одинаковым для обоего функций:

Вот мой код:

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

Я думал, что они использовали один и тот же «алгоритм», но теперь я не уверен.

EDIT

Для того, чтобы воспроизвести проблему, ionosphere набор данных (kknn пакет) может быть использован:

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

Я думаю, что я что-то не хватает ...

EDIT 2

Я понял, что если вы сделать среднее каждую строку первых двух столбцов importance(rfImp), вы получите результаты 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) 

Я не знаю, почему это происходит, но там должен быть объяснением для этого.

+0

Воспроизводимый пример необходим людям, чтобы точно ответить на вопрос. – topepo

+0

Извините. Я обнаружил, что та же проблема возникает при использовании набора данных «ионосфера». Я собираюсь отредактировать вопрос –

+0

@topepo, как вы думаете? Я надеюсь, что вы сможете помочь с объяснением различий. –

ответ

7

Если пройти через метод для varImp:

Проверить объект:

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

Получить 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 
        } 

Так что это не строго возвращающегося RandomForest :: важность ,

Он начинается с вычисления этого, но затем выбирает только категориальный val которые находятся в наборе данных.

Тогда это что-то интересное, он проверяет, если у нас есть только две колонки:

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

По словам мужчины странице varImp:

Random Forest: varImp.randomForest и varImp .RandomForest - это обертки вокруг функций важности из пакетов randomForest и , соответственно.

Это явно не тот случай.


Как почему ...

Если у нас есть только два значения, то значение переменной как предсказатель может быть представлена ​​в виде одного значения.

Если переменная является предиктором g, то оно также должно быть предсказателем b

Это имеет смысл, но это не соответствует их документации о том, что эта функция делает, поэтому я бы скорее сообщите об этом как о неожиданном поведении. Функция пытается помочь, когда вы ожидаете сделать относительный расчет самостоятельно.

+0

Быстрое добавление к «Как к почему ..». 'randomForest :: значение()' агрегирует оценки значимости класса, используя взвешенное среднее, прежде чем оно перескакивает их, используя их «стандартную ошибку» и сообщает об этом как «meanDecreaseAccuracy». 'varImp()' принимает (по умолчанию) масштабированные оценки по классам и усредняет их без взвешивания. Для неравного распределения классов первое кажется более близким к важности для общей точности, второе - предвзятым в пользу редких классов. Есть ли теоретическое отношение к этому? – joha

+0

@joha Есть ли у вас пример смещения в терминах редких классов? (Я не знаю, откуда это происходит отсюда: существуют другие способы сочетания двух значений в одном, почему среднее?). Кроме того, мой смелый комментарий, очевидно, справедлив в случае с двумя объектами, но я не уверен, что он не должен влиять на большее количество классов. Это подразумевает дополнительную информацию и 1 меньшую степень свободы при каждом количестве занятий. – Shape

+0

Я добавил ответ, чтобы объяснить, что я имею в виду, может быть, вы могли бы проверить, имеет ли это смысл. Одна поправка к предыдущему комментарию: RandomForest :: значение() _ не содержит агрегировать оценки значимости класса, используя средневзвешенное значение. – joha

2

У меня нет ваших точных данных, но с использованием фиктивных данных (см. Ниже) Я не могу воспроизвести это поведение. Возможно, дважды проверьте, что вы действительно ничего не делали, что могло повлиять на ваши результаты. Какую версию R и карету вы используете?

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) 

Update:

Используя данные Ionosphere это воспроизводимая:

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

... с этими результатами:

> 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 

Мое предположение было бы, что каретка и randomForest просто используют разные способы agg приносящие результаты из разных прогонов для каждой переменной, но @topepo, скорее всего, даст вам точный ответ в любом случае.

+1

Привет @geekoverdose! Я использовал набор данных «iris», и важность для обеих функций важна, как вы сказали. Я попытался использовать другой набор данных, чтобы воспроизвести проблему, и я обнаружил, что если я использую набор данных «ионосфера», обе функции приносят разные значения, как я упоминаю в своем вопросе. 'rfImp1 <- randomForest (класс ~., Data = ionosphere [, 3: 35], ntree = 2000, значение = TRUE)' Моя версия R - 3.2.5, а версия «caret» - 6.0.68 –

3

Этот ответ предназначен как дополнение к решению от @Shape. Я думаю, что importance следует известному подходу Бреймана, чтобы рассчитать переменную значимость, указанную как MeanDecreaseAccuracy, т. Е. Для образца вне мешка каждого дерева вычислить точность дерева, а затем переставить переменные один за другим и измерить точность после перестановки для вычисления уменьшения точности без этой переменной.
Я не смог найти много информации о том, как точно вычисляется снижение точности класса в первых столбцах, но я предполагаю, что это правильно предсказанный класс k/общий прогнозируемый класс k.

Как объясняет @Shape, varImp не сообщает MeanDecreaseAccuracy сообщает importance, но вместо этого вычисляет среднее значение (масштабируемым) класс конкретного уменьшается в точности и доклады для каждого из классов. (Для более чем 2 классов varImp сообщает только о снижении точности для класса).
Этот подход аналогичен только в том случае, если распределение классов равно. Причина в том, что только в сбалансированном случае уменьшение точности одного класса равномерно снижает точность в другом классе.

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 

Я считаю, что это может быть истолковано как кареткой положить одинаковый вес по всем классам, в то время как importance отчеты переменные как более важно, если они имеют важное значение для более общего класса. Я склонен согласиться с Максом Куном по этому поводу, но эту разницу следует объяснить где-то в документации.