Различные результаты от randomForest через каретку и базового пакета randomForest


14

Я немного растерялся: чем могут отличаться результаты обученной модели с помощью каретки от модели в оригинальной упаковке? Я прочитал , нужна ли предварительная обработка перед прогнозированием с использованием FinalModel из RandomForest с пакетом Caret? но я не использую никакой предварительной обработки здесь.

Я тренировал разные случайные леса, используя набор карет и настраивая их для разных значений 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
 ....

Теперь я обучил Random 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
Вы использовали одно и то же значение для случайного начального числа для обеих моделей?
мммммммммм

Я думаю так. Я установил начальное значение в коде ранее при разделении набора данных на обучающие и тестовые данные, затем обучил модель каретки, затем обучил «оригинальную» RF-модель. Таким образом, семя должно оставаться прежним, как только оно появилось в начале, не так ли?
Мальте

Я попытался вставить еще один set.seed непосредственно перед тренировкой «оригинальной» модели. К сожалению, не решает проблему.
Мальте

3
Вы должны проверить это, используя seedsаргументtrainControl
topepo

Ответы:


4

Я думаю, что этот вопрос, хотя и несколько тривиальный и «программный», на первый взгляд, затрагивает две основные проблемы, которые очень важны в современной статистике:

  1. Воспроизводимость результатов и
  2. недетерминированные алгоритмы.

Причина для разных результатов состоит в том, что две процедуры обучаются с использованием разных случайных семян. В случайных лесах используется случайное подмножество из переменных полного набора данных в качестве кандидатов при каждом разбиении (это mtryаргумент и относится к методу случайного подпространства ), а также пакеты (начальные загрузки) исходного набора данных для уменьшения дисперсии модели. Эти две процедуры внутренней случайной выборки считаются недетерминированными между различными прогонами алгоритма. Случайный порядок, в котором производится выборка, контролируется используемыми случайными семенами. Если бы использовались одни и те же семена, можно было бы получить одинаковые результаты в обоих случаях, когда 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 (например, усиление градиента, случайные леса, экстремальные нейронные сети) действительно используют определенные процедуры внутренней передискретизации во время своих этапов обучения, поэтому установка случайных начальных состояний перед (или иногда даже внутри) их этапом обучения может быть важной.


Важная часть заключалась в том, чтобы явно установить аргумент seed в «trainControl», используя аргумент «
Malte

Да, конечно. Я хотел убедиться, что вопрос о том, зачем это нужно, был полностью прояснен.
usεr11852 говорит восстановить Monic

Как мне запустить, trainчтобы это точно эквивалентно randomForest? Я пытался, method="none"но не уверен, как установить начальное значение для одного значения. Благодарю.
Саймон Вудворд

Извините, но неясно, есть ли у вас что-либо preProcessили как вас randomForestобучают с самого начала. В общем, предполагая, что у нас нет шагов предварительной обработки, мы должны убедиться, что оба семени и используемые гиперпараметры (здесь только что mtry) одинаковы.
usεr11852 говорит восстановить Monic

0

Прогнозы от curClassifierне совпадают с прогнозами по curClassifier$finalModel ссылке . Вы воспроизвели finalModelи сравниваете его с predict.trainобъектом.


1
Хотя то, что вы говорите, правда, это, к сожалению, немного вводит в заблуждение в текущей настройке, так как OP не выполняет предварительной обработки. Оба predictдолжны (и действительно делают) давать одинаковые прогнозы в случае, когда исследуется OP. Я разъясняю этот момент немного больше в своем посте.
usεr11852 говорит восстановить Monic
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.