Je ne comprends pas quelle est la différence entre la fonction varImp
(package caret
) et la fonction importance
(package randomForest
) pour un modèle de forêt aléatoire:
J'ai calculé un modèle de classification simple RF et lors du calcul de l'importance variable, j'ai constaté que le "classement" des prédicteurs n'était pas le même pour les deux fonctions:
Voici mon code:
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
...
Je pensais qu'ils utilisaient le même "algorithme" mais je ne suis pas sûr pour le moment.
MODIFIER
Afin de reproduire le problème, l’ensemble de données ionosphere
(paquetage kknn) peut être utilisé:
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
...
Je pense qu'il me manque quelque chose ...
EDIT 2
J'ai compris que si vous faites la moyenne de chaque ligne des deux premières colonnes de importance(rfImp)
, vous obtenez les résultats de 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)
Je ne sais pas pourquoi cela se produit, mais il doit y avoir une explication à cela.
Si nous parcourons la méthode pour varImp:
Vérifiez l'objet:
> getFromNamespace('varImp','caret')
function (object, ...)
{
UseMethod("varImp")
}
Obtenez la méthode 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
}
Donc, ceci ne renvoie pas strictement randomForest :: importance,
Il commence par calculer cela, puis ne sélectionne que les valeurs qualitatives contenues dans l'ensemble de données.
Ensuite, il fait quelque chose d'intéressant, il vérifie s'il ne reste que deux colonnes:
if(dim(out)[2] == 2) {
tmp <- apply(out, 1, mean)
out[,1] <- out[,2] <- tmp
}
Selon la page de manuel varImp:
Forêt aléatoire: varImp.randomForest et varImp.RandomForest sont des enveloppes autour des fonctions d’importance de randomForest et forfaits de fête, respectivement.
Ce n'est clairement pas le cas.
Quant à pourquoi ...
Si nous n’avons que deux valeurs, l’importance de la variable en tant que prédicteur peut être représentée par une seule valeur.
Si la variable est un prédicteur de g
, elle doit également être un prédicteur de b
Cela a du sens, mais cela ne correspond pas à leur documentation sur ce que fait la fonction, donc je signalerais probablement cela comme un comportement inattendu. La fonction tente de vous aider lorsque vous vous attendez à faire le calcul relatif vous-même.
Cette réponse constitue un complément à la solution de @Shape. Je pense que importance
suit l’approche bien connue de Breiman pour calculer l’importance variable rapportée sous la forme MeanDecreaseAccuracy
, c’est-à-dire que pour l’échantillon en sortie de sac de chaque arbre, calculer la précision de l’arbre, puis permuter les variables les unes après les autres et mesurer la précision après permutation pour calculer la diminution de la précision sans cette variable.
Je n’ai pas trouvé beaucoup d’informations sur le calcul exact de la diminution de l’exactitude propre à la classe dans les premières colonnes, mais je suppose que c’est la classe prédite correctement k/la classe k totale prédite k .
Comme @Shape l'explique, varImp
ne rapporte pas la MeanDecreaseAccuracy
indiquée par importance
, mais calcule plutôt la moyenne des diminutions (mises à l'échelle) de la précision de la classe et la rapporte pour chacune des classes. (Pour plus de 2 classes, varImp
rapporte uniquement la diminution de précision de la classe.)
Cette approche n’est similaire que si la distribution de la classe est égale. La raison en est que ce n'est que dans le cas équilibré qu'une diminution de la précision d'une classe diminue également la précision de l'autre 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
Je pense que cela peut être interprété comme une insistance égale sur toutes les classes, alors que importance
rapporte les variables comme étant plus importantes si elles sont importantes pour la classe la plus courante. J'ai tendance à être d'accord avec Max Kuhn sur ce point, mais la différence devrait être expliquée quelque part dans la documentation.
Je n'ai pas vos données exactes, mais en utilisant des données factices (voir ci-dessous), je ne peux pas reproduire ce problème. Vérifiez peut-être que vous n'avez vraiment rien fait qui puisse affecter vos résultats. Quelle version de R et caret utilisez-vous?
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)
Mettre à jour:
En utilisant les données Ionosphere
, ceci est reproductible:
library(caret)
library(randomForest)
library(mlbench)
data(Ionosphere)
str(Ionosphere)
rfImp1 <- randomForest(Class ~ ., data = Ionosphere[,3:35], ntree = 2000, importance = TRUE)
... avec ces résultats:
> 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
Mon hypothèse serait que caret et randomForest utilisent simplement différentes méthodes pour agréger les résultats de différentes exécutions pour chaque variable - mais @topepo vous donnera probablement une réponse exacte de toute façon.
https://www.r-bloggers.com/variable-importance-plot-and-variable-selection/ Dans le lien indiqué, il a été démontré que lorsque vous ne spécifiez pas importance = TRUE dans votre modèle, vous obtenez la même diminution moyenne de la valeur de Gini avec les packages randomForest et Caret