2

私は現在、R の randomForest パッケージを使用しています。分類ステップを高速化するために、フォレストを並行して実行することに興味がありました。そのために、「foreach」ビネットに示されているのと同様の方法でパッケージ「foreach」を使用しました。これは、ツリーの総数を使用したいコアの数で分割し、それらをパッケージ「randomForest」の関数「combine」と組み合わせることで構成されます。

require(randomForest)
require(foreach)
require(doParallel)
registerDoParallel(cores=CPUS)
rf  <- foreach::foreach(ntree=rep(ceiling(NTREE/CPUS), CPUS), .combine=randomForest::combine, .packages='randomForest') %dopar% {
    randomForest::randomForest(x=t(Y), y=A, ntree=ntree, importance=TRUE, ...)
    }

「並列」フォレストの結果と、1 つのコアで生成されたフォレストを比較しました。テスト セットの予測能力は似ているように見えますが、「重要度」の値は大幅に減少しており、これは変数選択の次のステップに影響します。

imp <- importance(rf,type=1)

どうしてこうなったのか、正しいのか間違いなのか教えていただきたいです。どうもありがとう!

4

1 に答える 1

1

randomForest::combine は、変数の重要度の再計算をサポートしていません。randomForest パッケージでは、randomForest::randomForest 関数が終了する直前にのみ重要度が計算されます。次の 2 つのオプションがあります。

  • 組み合わせたフォレストとトレーニング セットを入力として受け取る、独自の変数重要度関数を記述します。これはおよそ 50 行のコードです。

  • 各 randomForest オブジェクトが出力リストの要素である「lapply」のような並列計算を使用します。次に、すべてのフォレストで変数の重要度を集計し、単純に平均を計算します。代わりに foreach ループの外側で do.call(rf.list,combine) を使用してください。この方法は、変数の重要度の合計の概算ですが、非常に優れた方法です。

Windows がサポートするコード例:

library(randomForest)
library(doParallel)
CPUS=6; NTREE=5000
cl = makeCluster(CPUS)
registerDoParallel(cl)
data(iris)
rf.list = foreach(ntree = rep(NTREE/CPUS,CPUS),
                  .combine=c,
                  .packages="randomForest") %dopar% {
                    list(randomForest(Species~.,data=iris,importance=TRUE, ntree=ntree))  
                  }
stopCluster(cl)
big.rf = do.call(combine,rf.list)
big.rf$importance = rf.list[[1]]$importance
for(i in 2:CPUS) big.rf$importance = big.rf$importance + rf.list[[i]]$importance
big.rf$importance  = big.rf$importance / CPUS
varImpPlot(big.rf)

#test number of trees in one forest and combined forest, big.rf
print(big.rf)  #5000 trees
rf.list[[1]]$ntree 

#training single forest
rf.single = randomForest(Species~.,data=iris,ntree=5000,importance=T)
varImpPlot(big.rf)
varImpPlot(rf.single)
#print unscaled variable importance, no large deviations
print(big.rf$importance)

# setosa  versicolor  virginica MeanDecreaseAccuracy MeanDecreaseGini
# Sepal.Length 0.033184860 0.023506673 0.04043017           0.03241500         9.679552
# Sepal.Width  0.008247786 0.002135783 0.00817186           0.00613059         2.358298
# Petal.Length 0.335508637 0.304525644 0.29786704           0.30933142        43.160074
# Petal.Width  0.330610910 0.307016328 0.27129746           0.30023245        44.043737

print(rf.single$importance)

# setosa   versicolor  virginica MeanDecreaseAccuracy MeanDecreaseGini
# Sepal.Length 0.031771614 0.0236603417 0.03782824          0.031049531         9.516198
# Sepal.Width  0.008436457 0.0009236979 0.00880401          0.006048261         2.327478
# Petal.Length 0.341879367 0.3090482654 0.29766905          0.312507316        43.786481
# Petal.Width  0.322015885 0.3045458852 0.26885097          0.296227150        43.623370

#but when plotting using varImppLot, scale=TRUE by default
#either simply turn of scaling to get comparable results
varImpPlot(big.rf,scale=F)
varImpPlot(rf.single,scale=F)

#... or correct scaling to the number of trees
big.rf$importanceSD = CPUS^-.5 * big.rf$importanceSD 


#and now there are no large differences for scaled variable importance either
varImpPlot(big.rf,scale=T)
varImpPlot(rf.single,scale=T)
于 2015-10-02T12:59:14.197 に答える