web-dev-qa-db-ja.com

ランダムフォレストのトレーニングをスピードアップするにはどうすればよいですか?

いくつかのランダムフォレスト(回帰用)をトレーニングして、それらを競合させ、どの機能選択とどのパラメーターが最良のモデルを与えるかを確認しようとしています。

しかし、トレーニングには非常に時間がかかるようで、何か間違っているのではないかと思っています。

私がトレーニングに使用しているデータセット(以下のtrainと呼ばれます)には、217k行と58列(そのうちの21のみがランダムフォレストで予測子として機能します。ブール値のものを除いて、これらはすべてnumericまたはintegerです。クラスはcharacterです。yの出力はnumericです)。

次のコードを4回実行し、_4_、_100_、_500_、_2000_から_nb_trees_の値を指定しました。

_library("randomForest")
nb_trees <- #this changes with each test, see above
ptm <- proc.time()
fit <- randomForest(y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 
    + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 
    + x20 + x21, 
    data = train, 
    ntree = nb_trees, 
    do.trace=TRUE)
proc.time() - ptm
_

それぞれがトレーニングにかかった時間は次のとおりです。

_nb_trees | time
4          4mn
100        1h 41mn
500        8h 40mn
2000       34h 26mn
_

私の会社のサーバーには12コアと125 GoのRAMがあるので、トレーニングを並列化してみようと思った この答え (ただし、doParallelパッケージを使用したのは、doSNOWで永久に実行されているようだったからです。理由はわかりません。また、doParallelも機能することを確認できませんでした(申し訳ありません)。

_library("randomForest")
library("foreach")
library("doParallel")
nb_trees <- #this changes with each test, see table below
nb_cores <- #this changes with each test, see table below
cl <- makeCluster(nb_cores)
registerDoParallel(cl)
ptm <- proc.time()
fit <- foreach(ntree = rep(nb_trees, nb_cores), .combine = combine, .packages = "randomForest") 
    %dopar% {
        randomForest(y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 
        + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 
        + x20 + x21,
        data = train, 
        ntree = ntree,
        do.trace=TRUE)}
proc.time() - ptm
stopCluster(cl)
_

実行すると、並列化されていないコードよりも時間がかかります:

_nb_trees | nb_cores | total number of trees              | time
1          4          4                                    2mn13s
10         10         100                                  52mn
9          12         108 (closest to 100 with 12 cores)   59mn
42         12         504 (closest to 500 with 12 cores)   I won't be running this one
167        12         2004 (closest to 2000 with 12 cores) I'll run it next week-end
_

でも、まだ時間がかかると思いますね。木を組み合わせて最終的なフォレストにするのに時間がかかることは承知しているので、12コアで12倍高速になるとは思っていませんでしたが、わずか2倍高速です...

  • これは正常ですか?
  • そうでない場合、実行時間を根本的に減らすために、データやコードでできることはありますか?
  • そうでない場合は、サーバーの担当者にもっと速くするように伝えますか?

ご回答ありがとうございます。

ノート :

  • このサーバーを使用しているのは私だけです
  • 次のテストでは、ランダムフォレストで使用されていない列を削除します
  • randomForest(predictors,decision)の代わりにrandomForest(decision~.,data=input)を呼び出すことで実行時間を改善できることにかなり遅れて気づきました。これからもそれを実行しますが、上記の質問はまだ残っていると思います。
11
François M.

私は、並列化や非常に長い時間コードを実行するなどのブルートフォーステクニックのファンですが、ブルートフォーステクニックを使用する必要がないようにアルゴリズムを改善するというより大きなファンです。

2000本の木を使用してランダムフォレストをトレーニングすることは法外に高価になり始めていましたが、より少ない本数の木を使用したトレーニングはより合理的な時間を要しました。まず第一に、あなたは言う481632...256512ツリーを使用して、モデルの堅牢性を知らせるメトリックを注意深く観察します。これらのメトリクスには、最適な定数モデル(データセットでフォレストがどの程度うまく機能するか、すべての入力の中央値を予測するモデルなど)、およびout-of-bagエラーが含まれます。さらに、上位の予測子とその重要性、およびツリーを追加するときにそこに収束が見られるかどうかを確認できます。

理想的には、モデルを構築するために何千ものツリーを使用する必要はないはずです。モデルが収束し始めたら、ツリーを追加しても必ずしもモデルが悪化するわけではありませんが、同時に新しい情報は追加されません。あまりにも多くの木を使用しないようにすることで、1週間から1日未満の計算を削減できる場合があります。これに加えて、数十のCPUコアを活用している場合は、何時間も何かを調べている可能性があります。

ランダムフォレストを実行するたびに変数の重要度を確認するには、次のように試してみます。

fit <- randomForest(...)
round(importance(fit), 2)

最初の5〜10の予測子がモデルに最も大きな影響を与えると私は理解しています。ツリーを増やしても、これらの上位予測子は実際には相対的な位置を変更せず、重要度の指標は同じであるように見える場合は、それほど多くのツリーを使用しないことを検討してください。

8
Tim Biegeleisen

randomForest()関数は、「式インターフェース」または「マトリックスインターフェース」のいずれかを使用してデータを受け入れることができます。マトリックスインターフェイスは、より優れたパフォーマンス値を提供することが知られています。

数式インターフェース:

rf.formula = randomForest(Species ~ ., data = iris)

マトリックスインターフェイス:

rf.matrix = randomForest(y = iris[, 5], x = iris[, 1:4])
5
user1808924