Hasil yang berbeda dari randomForest via caret dan paket randomForest dasar

14

Saya agak bingung: Bagaimana hasil dari Model yang terlatih melalui caret berbeda dari model dalam paket aslinya? Saya membaca apakah preprocessing diperlukan sebelum prediksi menggunakan FinalModel dari RandomForest dengan paket caret? tapi saya tidak menggunakan preprocessing di sini.

Saya melatih berbagai Random Forests dengan menggunakan paket caret dan tuning untuk nilai mtry yang berbeda.

> 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

Saya menemukan mtry = 15 sebagai parameter terbaik di 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. 

Saya menilai model dengan Kurva ROC dan matriks kebingungan:

##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")

Matriks dan Akurasi yang dihasilkan:

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

           Accuracy : 0.8984
 ....

Sekarang saya melatih Rorest Acak dengan parameter yang sama dan training_data yang sama menggunakan paket randomForest dasar:

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

Sekali lagi saya membuat prediksi untuk test_data yang sama seperti di atas dan menilai matriks kebingungan dengan kode yang sama seperti di atas. Tapi sekarang saya mendapat langkah berbeda:

Confusion Matrix and Statistics

      Reference
Prediction   No  Yes
       No  2702  897
       Yes  430 6480

           Accuracy : 0.8737 
           ....

Apa alasannya? Apa yang saya lewatkan?

Malte
sumber
3
Apakah Anda menggunakan nilai yang sama untuk seed acak untuk kedua model?
mmmmmmmmmm
Aku pikir begitu. Saya mengatur seed sebelumnya dalam kode ketika memisahkan set data untuk melatih dan menguji data, kemudian melatih model caret, kemudian melatih model rf "asli". Jadi, benihnya harus tetap sama setelah ditetapkan di awal, bukan?
Malte
Saya mencoba untuk memasukkan set.seed lain secara langsung sebelum melatih model "asli". Sayangnya, tidak menyelesaikan masalah.
Malte
3
Anda harus menguji ini menggunakan seedsargumentrainControl
topepo

Jawaban:

4

Saya pikir pertanyaan sementara agak sepele dan "terprogram" pada awalnya dibaca menyentuh dua masalah utama yang sangat penting dalam Statistik modern:

  1. reproduktifitas hasil dan
  2. algoritma non-deterministik.

Alasan untuk hasil yang berbeda adalah bahwa kedua prosedur dilatih menggunakan benih acak yang berbeda. Hutan acak menggunakan subset acak dari variabel dataset lengkap sebagai kandidat di setiap pemisahan (itulah mtryargumennya dan berhubungan dengan metode subruang acak ) serta tas (bootstrap agregat) dataset asli untuk mengurangi varian model. Kedua prosedur pengambilan sampel acak internal ini dianggap tidak deterministik antara berbagai proses algoritma. Urutan acak yang dilakukan pengambilan sampel dikendalikan oleh benih acak yang digunakan. Jika benih yang sama digunakan, orang akan mendapatkan hasil yang sama persis dalam kedua kasus di mana rutinitas dipanggil; keduanya secara internal di serta secara eksternal saat memasang hutan acak secara manual. Saya melampirkan cuplikan kode sederhana untuk menunjukkan hal ini Harap dicatat bahwa saya menggunakan jumlah pohon yang sangat kecil (argumen:) untuk menjaga pelatihan cepat, itu harus umumnya jauh lebih besar.randomForestcaret::trainntree

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) 

Pada titik ini baik caret.trainobjek fitRFcaretmaupun randomForestobjek yang ditentukan secara manual fitRFmanualtelah dilatih menggunakan data yang sama tetapi yang penting menggunakan benih acak yang sama saat memasang model akhir mereka. Karena itu ketika kami akan mencoba untuk memprediksi menggunakan objek-objek ini dan karena kami tidak melakukan preprocessing data kami, kami akan mendapatkan jawaban yang persis sama.

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

Hanya untuk memperjelas hal ini nanti sedikit lebih jauh: predict(xx$finalModel, testData)dan predict(xx, testData)akan berbeda jika seseorang menetapkan preProcessopsi saat menggunakan train. Di sisi lain, ketika menggunakan finalModellangsung itu setara dengan menggunakan predictfungsi dari model yang dipasang (di predict.randomForestsini) bukannya predict.train; tidak ada pra-proses berlangsung. Jelas dalam skenario yang diuraikan dalam pertanyaan asli di mana tidak ada pra-pemrosesan dilakukan hasilnya akan sama ketika menggunakan finalModel, randomForestobjek yang dipasang secara manual atau caret.trainobjek.

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

Saya sangat menyarankan agar Anda selalu mengatur seed acak yang digunakan oleh R, MATLAB atau program lain yang digunakan. Kalau tidak, Anda tidak dapat memeriksa reproduksibilitas hasil (yang OK, itu mungkin bukan akhir dari dunia) atau mengecualikan bug atau faktor eksternal yang mempengaruhi kinerja prosedur pemodelan (yang ya, itu agak menyebalkan). Banyak algoritma ML terkemuka (mis. Meningkatkan gradien, hutan acak, jaringan saraf ekstrem) menggunakan prosedur resampling internal tertentu selama fase pelatihan mereka, pengaturan keadaan benih acak sebelum (atau kadang-kadang bahkan di dalam) fase pelatihan mereka bisa menjadi penting.

usεr11852 kata Reinstate Monic
sumber
Bagian yang penting adalah mengatur argumen seed secara eksplisit di "trainControl" menggunakan argumen "seed"
Malte
Ya tentu saja. Saya ingin memastikan bahwa masalah mengapa ini diperlukan, sepenuhnya diklarifikasi.
usεr11852 mengatakan Reinstate Monic
Bagaimana cara saya menjalankannya trainsehingga persis sama dengan randomForest? Saya mencoba method="none"tetapi tidak yakin bagaimana mengatur seed ke nilai tunggal. Terima kasih.
Simon Woodward
Permintaan maaf tetapi tidak jelas apakah Anda memiliki preProcessatau bagaimana randomForestdilatih untuk memulai. Secara umum, dengan asumsi kita tidak memiliki langkah-langkah pra-pemrosesan, kita perlu memastikan bahwa baik seed dan hyperparameters (di sini saja mtry) yang digunakan adalah sama.
usεr11852 mengatakan Reinstate Monic
0

Prediksi dari curClassifiertidak sama dengan prediksi dari curClassifier$finalModel tautan . Anda telah mereproduksi finalModeldan membandingkannya dengan predict.trainobjek.

Tomaz
sumber
1
Meskipun apa yang Anda katakan itu benar, sayangnya agak menyesatkan dalam pengaturan saat ini karena tidak ada pra-pemrosesan yang dilakukan oleh OP. Keduanya predictharus (dan benar-benar melakukan) memberikan prediksi yang sama dalam kasus OP mengeksplorasi. Saya mengklarifikasi poin ini sedikit lebih banyak di posting saya.
usεr11852 mengatakan Reinstate Monic