キャレットと基本的なrandomForestパッケージを介したrandomForestからの異なる結果


14

私は少し混乱しています:キャレットを介してトレーニングされたモデルの結果は、元のパッケージのモデルとどう違うのですか?キャレットパッケージでRandomForestのFinalModelを使用して予測する前に前処理が必要かどうかを読みましたただし、ここでは前処理を使用しません。

キャレットパッケージを使用して、さまざまなmtry値を調整することにより、さまざまなランダムフォレストをトレーニングしました。

> cvCtrl = trainControl(method = "repeatedcv",number = 10, repeats = 3, classProbs = TRUE, summaryFunction = twoClassSummary)
> newGrid = expand.grid(mtry = c(2,4,8,15))
> classifierRandomForest = train(case_success ~ ., data = train_data, trControl = cvCtrl, method = "rf", metric="ROC", tuneGrid = newGrid)
> curClassifier = classifierRandomForest

mtry = 15がtraining_dataの最適なパラメーターであることがわかりました。

> curClassifier
 ...
Resampling results across tuning parameters:

mtry  ROC    Sens   Spec   ROC SD   Sens SD  Spec SD
 4    0.950  0.768  0.957  0.00413  0.0170   0.00285
 5    0.951  0.778  0.957  0.00364  0.0148   0.00306
 8    0.953  0.792  0.956  0.00395  0.0152   0.00389
10    0.954  0.797  0.955  0.00384  0.0146   0.00369
15    0.956  0.803  0.951  0.00369  0.0155   0.00472

ROC was used to select the optimal model using  the largest value.
The final value used for the model was mtry = 15. 

ROC曲線と混同マトリックスを使用してモデルを評価しました。

##ROC-Curve
predRoc = predict(curClassifier, test_data, type = "prob")
myroc = pROC::roc(test_data$case_success, as.vector(predRoc[,2]))
plot(myroc, print.thres = "best")

##adjust optimal cut-off threshold for class probabilities
threshold = coords(myroc,x="best",best.method = "closest.topleft")[[1]] #get optimal cutoff threshold
predCut = factor( ifelse(predRoc[, "Yes"] > threshold, "Yes", "No") )


##Confusion Matrix (Accuracy, Spec, Sens etc.)
curConfusionMatrix = confusionMatrix(predCut, test_data$case_success, positive = "Yes")

結果の混同マトリックスと精度:

Confusion Matrix and Statistics
      Reference
Prediction   No  Yes
   No  2757  693
   Yes  375 6684

           Accuracy : 0.8984
 ....

次に、基本的なrandomForestパッケージを使用して、同じパラメーターと同じtraining_dataでランダムロレストをトレーニングしました。

randomForestManual <- randomForest(case_success ~ ., data=train_data, mtry = 15, ntree=500,keep.forest=TRUE)
curClassifier = randomForestManual

再び、上記とまったく同じtest_dataの予測を作成し、上記と同じコードで混同マトリックスを評価しました。しかし今、私はさまざまな手段を得ました:

Confusion Matrix and Statistics

      Reference
Prediction   No  Yes
       No  2702  897
       Yes  430 6480

           Accuracy : 0.8737 
           ....

理由は何ですか?私は何が欠けていますか?


3
両方のモデルのランダムシードに同じ値を使用しましたか?
mmmmmmmmmm

私はそう思う。データセットをトレーニングデータとテストデータに分割するときにコードの初期にシードを設定し、キャレットモデルをトレーニングしてから、「元の」rfモデルをトレーニングしました。ですから、種は最初に設定された後も同じままでなければなりませんよね?
マルテ

「オリジナル」のrfモデルをトレーニングする前に、別のset.seedを直接挿入しようとしました。残念ながら、問題は解決しません。
マルテ

3
seedstrainControl
-topepo

回答:


4

この質問は、最初は少し些細で「プログラマティック」ではあるものの、現代の統計で非常に重要な2つの主要な問題に触れていると思います。

  1. 結果の再現性と
  2. 非決定的アルゴリズム。

結果が異なる理由は、2つの手順が異なるランダムシードを使用してトレーニングされるためです。ランダム林は(それはだ各分割で候補としてフルデータセットの変数からランダムなサブセットを使用してmtry引数に関し、ランダム部分空間法)だけでなく、バッグモデルの分散を減少させるために、元のデータセットを(ブートストラップ集計)。これらの2つの内部ランダムサンプリング手順は、アルゴリズムの異なる実行間で決定論的ではないと考えられました。サンプリングが行われるランダムな順序は、使用されるランダムなシードによって制御されます。同じシードが使用された場合、randomForestルーチンが呼び出される両方のケースでまったく同じ結果が得られます。両方とも内部的にcaret::trainランダムフォレストを手動でフィッティングする場合も外部的にも同様です。これを紹介するために、簡単なコードスニペットを添付します。ntreeトレーニングを高速に保つために非常に少ない数のツリー(引数:)を使用していることに注意してください。通常はもっと大きくする必要があります。

library(caret)

set.seed(321)
trainData <- twoClassSim(5000, linearVars = 3, noiseVars = 9)
testData  <- twoClassSim(5000, linearVars = 3, noiseVars = 9)

set.seed(432)
mySeeds <- sapply(simplify = FALSE, 1:26, function(u) sample(10^4, 3))
cvCtrl = trainControl(method = "repeatedcv", number = 5, repeats = 5, 
                      classProbs = TRUE, summaryFunction = twoClassSummary, 
                      seeds = mySeeds)

fitRFcaret = train(Class ~ ., data = trainData, trControl = cvCtrl, 
                   ntree = 33, method = "rf", metric="ROC")

set.seed( unlist(tail(mySeeds,1))[1])
fitRFmanual <- randomForest(Class ~ ., data=trainData, 
                            mtry = fitRFcaret$bestTune$mtry, ntree=33) 

この時点の両方でcaret.trainオブジェクトfitRFcaretならびに手動で定義されたrandomForestオブジェクトfitRFmanualと同じデータを使用して、それらの最終的なモデルをフィッティングするとき重要なの同じランダムシードを使用して訓練されています。そのため、これらのオブジェクト使用して予測しようとすると、データの前処理を行わないため、同じ正確な答えが得られます。

all.equal(current =  as.vector(predict(fitRFcaret, testData)), 
          target = as.vector(predict(fitRFmanual, testData)))
# TRUE

ただ、少しさらに、この後のポイントを明確にしますpredict(xx$finalModel, testData)と、predict(xx, testData)1セットの場合は異なるものになりますpreProcess使用してオプションtrain。一方、をfinalModel直接使用するpredict場合は、モデルの関数(predict.randomForestここ)を使用する代わりに、predict.train ;のです。事前処理は行われません。明らかに、前処理が行われない元の質問で概説したシナリオでは、、finalModel手動で適合したrandomForestオブジェクトまたはオブジェクトを使用した場合、結果は同じになりcaret.trainます。

all.equal(current =  as.vector(predict(fitRFcaret$finalModel, testData)), 
          target = as.vector(predict(fitRFmanual, testData)))
 # TRUE

all.equal(current =  as.vector(predict(fitRFcaret$finalModel, testData)),
          target = as.vector(predict(fitRFcaret, testData)))
# TRUE

私はあなたがいつもR、MATLAB、または使用される他のプログラムで使用されるランダムシード設定する。そうでなければ、結果の再現性をチェックすることはできません(これで終わりではないかもしれません)。また、モデリング手順のパフォーマンスに影響を与えるバグや外部要因を排除することはできません(そうです)。主要なMLアルゴリズム(例:勾配ブースティング、ランダムフォレスト、極端なニューラルネットワーク)の多くは、トレーニングフェーズ中に特定の内部リサンプリング手順を採用しています。トレーニングフェーズの前(または場合によってはその中)にランダムシード状態を設定することが重要です。


重要な部分は、引数「シード」を使用して「trainControl」で明示的に種子の引数を設定することでした
マルタ

はい、もちろん。私は、なぜこれが必要なのかという問題が完全に明らかにされたことを確認したかった。
usεr11852は回復モニック言う

train正確に同等になるように実行するにはどうすればよいrandomForestですか?試しましたmethod="none"が、シードを単一の値に設定する方法がわかりませんでした。ありがとう。
サイモンウッドワード

申し訳ありませんが、何かを持っているpreProcessかどうか、またはrandomForest最初からトレーニングされているかどうかは不明です。一般に、前処理ステップがないと仮定するmtry使用されるシードハイパーパラメーター(ここでは単に)の両方が同じであることを確認する必要があります。
usεr11852は回復モニック言う

0

からのcurClassifier予測はcurClassifier$finalModel linkからの予測と同じではありません。を再現finalModelし、predict.trainオブジェクトと比較しています。


1
あなたの言うことは事実ですが、残念ながら現在の設定では前処理がOPによって行われないため、少し誤解を招く可能性があります。どちらもpredict、OPが調査する場合に同じ予測を行う必要があります(実際に行います)。この点については、私の投稿でもう少し詳しく説明します。
usεr11852が復活モニック言う
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.