web-dev-qa-db-ja.com

ランダムフォレストのvarImp(キャレット)と重要度(randomForest)の違い

ランダムフォレストモデルのvarImp関数(caretパッケージ)とimportance関数(randomForestパッケージ)の違いはわかりません。

単純なRF分類モデルを計算し、変数の重要度を計算すると、予測子の「ランキング」が両方の関数で同じではないことがわかりました。

これが私のコードです:

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

彼らは同じ「アルゴリズム」を使っていると思いましたが、今はわかりません。

[〜#〜]編集[〜#〜]

問題を再現するために、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
...
_

何かが足りないと思います...

編集2

importance(rfImp)の最初の2列の各行の平均を計算すると、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)
_

なぜこれが起こっているのかはわかりませんが、説明が必要です。

13
Rafa OR

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 :: importanceを返しません。

最初にそれを計算しますが、その後、データセットにあるカテゴリ値のみを選択します。

次に、興味深いことを行い、2つの列しかないかどうかを確認します。

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

VarImp manページによると:

ランダムフォレスト:varImp.randomForestとvarImp.RandomForestは、それぞれrandomForestパッケージとpartyパッケージの重要度関数のラッパーです。

これは明らかにそうではありません。


理由について...

値が2つしかない場合、予測子としての変数の重要性は1つの値として表すことができます。

変数がgの予測子である場合、bの予測子でもある必要があります

それは理にかなっていますが、これは関数が何をするかについての彼らのドキュメンテーションに適合しないので、私はおそらくこれを予期しない動作として報告するでしょう。この関数は、相対計算を自分で行うことを期待しているときに支援しようとしています。

16
Shape

この回答は、@ Shapeによるソリューションへの追加を意味しています。 importanceはBreimanのよく知られたアプローチに従ってMeanDecreaseAccuracyとして報告される変数の重要度を計算すると思います。つまり、各ツリーのout-of-bagサンプルについて、ツリーの精度を計算します。次に、変数を順番に並べ替え、置換後に精度を測定して、その変数なしでの精度の低下を計算します。
最初の列のクラス固有の精度低下がどのように正確に計算されるかについて多くの情報を見つけることができませんでしたが、それは正しく予測されたクラスk /合計予測クラスkであると仮定します。

@Shapeが説明しているように、varImpMeanDecreaseAccuracyによって報告されたimportanceを報告せず、代わりに精度の(スケーリングされた)クラス固有の減少の平均を計算し、各クラス。 (3つ以上のクラスの場合、varImpは、クラス固有の精度の低下のみを報告します。)
このアプローチは、クラス分布が等しい場合にのみ同様です。その理由は、バランスの取れた場合にのみ、1つのクラスの精度が低下すると、他のクラスの精度も同様に低下するためです。

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は、より一般的なクラスにとって重要である場合、変数をより重要であると報告します。私はこれについてMax Kuhnに同意する傾向がありますが、違いはドキュメントのどこかに説明されています。

4
joha

正確なデータはありませんが、ダミーデータ(下記参照)を使用すると、この動作を再現できません。結果に影響を与える可能性のある他のことを本当に何もしていないことを再確認してください。 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)

更新:

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は、変数ごとに異なる実行からの結果を集計するさまざまな方法を使用しているだけですが、@ topepoはおそらくとにかく正確な答えを与えるでしょう。

2
geekoverdose

https://www.r-bloggers.com/variable-importance-plot-and-variable-selection/ 指定されたリンクでは、重要度を指定しない場合= TRUEであることが示されていますモデルでは、randomForestおよびCaretパッケージを使用して、同じ平均減少Gini値を取得します