ผลลัพธ์ที่แตกต่างจาก RandomForest ผ่าน caret และแพ็คเกจ RandomForest พื้นฐาน


14

ฉันสับสนเล็กน้อย: ผลลัพธ์ของโมเดลที่ได้รับการฝึกอบรมผ่านคาเร็ตจะแตกต่างจากโมเดลในแพ็คเกจดั้งเดิมอย่างไร ฉันอ่านว่าจำเป็นต้องมีการประมวลผลล่วงหน้าก่อนการทำนายด้วย FinalModel ของ RandomForest พร้อมชุดคาเร็ตหรือไม่? แต่ฉันไม่ได้ใช้ preprocessing ใด ๆ ที่นี่

ฉันฝึกป่าสุ่มที่แตกต่างกันโดยใช้ชุดคาเร็ตและปรับแต่งค่า 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 Curve และเมทริกซ์ความสับสน:

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

ตอนนี้ฉันฝึก Rorest แบบสุ่มด้วยพารามิเตอร์เดียวกันและ training_data เดียวกันโดยใช้แพ็คเกจ randomForest พื้นฐาน:

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 ต้นฉบับ "ดั้งเดิม" ดังนั้นเมล็ดควรจะคงเดิมเมื่อเริ่มต้นใช่ไหม?
Malte

ฉันพยายามแทรก set.seed อื่นโดยตรงก่อนฝึกรุ่น rf "ดั้งเดิม" ไม่ได้แก้ปัญหาโชคไม่ดี
Malte

3
คุณควรทดสอบสิ่งนี้โดยใช้seedsอาร์กิวเมนต์ของtrainControl
topepo

คำตอบ:


4

ฉันคิดว่าคำถามในขณะที่ค่อนข้างเล็กน้อยและ "เขียนโปรแกรม" ในตอนแรกอ่านสัมผัสกับสองประเด็นหลักที่สำคัญมากในสถิติสมัยใหม่:

  1. การทำซ้ำของผลลัพธ์และ
  2. อัลกอริทึมที่ไม่ได้กำหนดไว้

เหตุผลสำหรับผลลัพธ์ที่แตกต่างคือว่าทั้งสองขั้นตอนได้รับการฝึกอบรมโดยใช้เมล็ดแบบสุ่มที่แตกต่างกัน ป่าสุ่มใช้ชุดย่อยแบบสุ่มจากตัวแปรของชุดข้อมูลแบบเต็มในฐานะผู้สมัครในแต่ละการแยก (นั่นคือmtryอาร์กิวเมนต์และเกี่ยวข้องกับวิธีการ subspace แบบสุ่ม ) เช่นเดียวกับถุง (ชุดรวม bootstrap) ชุดข้อมูลดั้งเดิมเพื่อลดความแปรปรวนของแบบจำลอง ความคิดการสุ่มตัวอย่างแบบสุ่มภายในทั้งสองนี้ไม่ได้กำหนดไว้ระหว่างการวิ่งของอัลกอริทึมที่แตกต่างกัน ลำดับแบบสุ่มที่การสุ่มตัวอย่างเสร็จสิ้นจะถูกควบคุมโดยเมล็ดแบบสุ่มที่ใช้ หากใช้เมล็ดพันธุ์เดียวกันเมล็ดหนึ่งจะได้ผลลัพธ์ที่เหมือนกันแน่นอนในทั้งสองกรณีที่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)จะแตกต่างกันหากชุดตัวเลือกเมื่อใช้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" โดยใช้อาร์กิวเมนต์ "เมล็ด"
Malte

ใช่แน่นอน ฉันต้องการตรวจสอบให้แน่ใจว่าปัญหาที่ว่าทำไมจึงจำเป็นต้องมีการชี้แจงอย่างเต็มที่
usεr11852พูดว่า Reinstate Monic

ฉันจะเรียกวิธีtrainเพื่อที่จะเทียบเท่าตรงกับrandomForest? ฉันพยายามmethod="none"แต่ไม่แน่ใจว่าจะตั้งค่าเมล็ดเป็นค่าเดียวได้อย่างไร ขอบคุณ
Simon Woodward

ขออภัย แต่ก็ไม่มีความชัดเจนหากคุณมีpreProcessวิธีการใด ๆหรือวิธีการrandomForestฝึกอบรมที่จะเริ่มต้นด้วย โดยทั่วไปสมมติว่าเราไม่มีขั้นตอนการประมวลผลล่วงหน้าที่เราต้องการเพื่อให้แน่ใจว่าทั้งเมล็ดและพารามิเตอร์ (ที่นี่เพียงmtry) ใช้เหมือนกัน
usεr11852พูดว่า Reinstate Monic

0

การคาดการณ์จากการcurClassifierไม่ได้เช่นเดียวกับการคาดการณ์จากการเชื่อมโยงcurClassifier$finalModel คุณทำซ้ำfinalModelและเปรียบเทียบกับpredict.trainวัตถุ


1
ในขณะที่สิ่งที่คุณพูดเป็นความจริง แต่น่าเสียดายที่ความเข้าใจผิดเล็กน้อยในการตั้งค่าปัจจุบันเนื่องจาก OP ไม่ได้ทำการประมวลผลล่วงหน้า ทั้งสองpredictควร (และทำจริง) ให้การคาดการณ์เดียวกันในกรณีที่ OP สำรวจ ฉันชี้แจงประเด็นนี้อีกเล็กน้อยในโพสต์ของฉัน
usεr11852พูดว่า Reinstate Monic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.