Estoy un poco confundido: ¿cómo pueden los resultados de un modelo entrenado a través de caret diferir del modelo en el paquete original? Yo leo si se necesita un procesamiento previo antes de la predicción usando FinalModel de RandomForest con el paquete caret? pero no uso ningún preprocesamiento aquí.
Entrené a diferentes bosques aleatorios usando el paquete de caret y sintonizando diferentes valores 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
Encontré que mtry = 15 es el mejor parámetro en 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.
Evalué el modelo con una curva ROC y una matriz de confusión:
##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")
La matriz de confusión resultante y la precisión:
Confusion Matrix and Statistics
Reference
Prediction No Yes
No 2757 693
Yes 375 6684
Accuracy : 0.8984
....
Ahora entrené un Rorest Random con los mismos parámetros y los mismos datos de entrenamiento usando el paquete básico randomForest:
randomForestManual <- randomForest(case_success ~ ., data=train_data, mtry = 15, ntree=500,keep.forest=TRUE)
curClassifier = randomForestManual
Nuevamente, creé predicciones para los mismos test_data de arriba y evalué la matriz de confusión con el mismo código que arriba. Pero ahora tengo diferentes medidas:
Confusion Matrix and Statistics
Reference
Prediction No Yes
No 2702 897
Yes 430 6480
Accuracy : 0.8737
....
¿Cuál es la razón? ¿Qué me estoy perdiendo?
seeds
argumento detrainControl
Respuestas:
Creo que la pregunta, aunque algo trivial y "programática" en primera lectura, toca dos cuestiones principales que son muy importantes en las estadísticas modernas:
La razón de los diferentes resultados es que los dos procedimientos se entrenan utilizando diferentes semillas aleatorias. Los bosques aleatorios usan un subconjunto aleatorio de las variables del conjunto de datos completo como candidatos en cada división (esa es la
mtry
argumento y se relaciona con el método de subespacio aleatorio ), así como bolsas el conjunto de datos original de (agregados de arranque) para disminuir la varianza del modelo. Estos dos procedimientos de muestreo aleatorio interno no son deterministas entre diferentes ejecuciones del algoritmo. El orden aleatorio en que se realiza el muestreo está controlado por las semillas aleatorias utilizadas. Si se usaran las mismas semillas, se obtendrían exactamente los mismos resultados en ambos casos donderandomForest
se llama la rutina; ambos internamente encaret::train
así como externamente cuando se ajusta un bosque aleatorio manualmente. Adjunto un fragmento de código simple para mostrar esto. Tenga en cuenta que uso un número muy pequeño de árboles (argumento:)ntree
para mantener el entrenamiento rápido, generalmente debería ser mucho más grande.En este punto, tanto el
caret.train
objetofitRFcaret
como elrandomForest
objeto definido manualmentefitRFmanual
han sido entrenados usando los mismos datos pero importantemente usando las mismas semillas aleatorias al ajustar su modelo final. Por lo tanto, cuando intentaremos predecir el uso de estos objetos y porque no procesamos previamente nuestros datos , obtendremos las mismas respuestas exactas.Solo para aclarar esto más adelante, apunte un poco más:
predict(xx$finalModel, testData)
ypredict(xx, testData)
será diferente si se configura lapreProcess
opción cuando se usatrain
. Por otro lado, cuando se usafinalModel
directamente, es equivalente usar elpredict
función del modelo ajustado (predict.randomForest
aquí) en lugar depredict.train
; no tiene lugar el preprocesamiento. Obviamente, en el escenario descrito en la pregunta original donde no se realiza el procesamiento previo, los resultados serán los mismos cuando se utiliza el objetofinalModel
ajustado manualmenterandomForest
o elcaret.train
objeto.Te sugiero encarecidamente que siempre establezca la semilla aleatoria utilizada por R, MATLAB o cualquier otro programa utilizado. De lo contrario, no puede verificar la reproducibilidad de los resultados (lo cual está bien, puede que no sea el fin del mundo) ni excluir un error o factor externo que afecte el desempeño de un procedimiento de modelado (que sí, apesta). Muchos de los principales algoritmos de ML (p. Ej., Aumento de gradiente, bosques aleatorios, redes neuronales extremas) emplean ciertos procedimientos internos de remuestreo durante sus fases de entrenamiento, estableciendo los estados de semilla aleatorios antes (o a veces incluso dentro) de su fase de entrenamiento puede ser importante.
fuente
train
para que sea exactamente equivalente arandomForest
? Intentémethod="none"
pero no estoy seguro de cómo establecer la semilla en el valor único. Gracias.preProcess
o cómorandomForest
está entrenado para empezar. En general, suponiendo que no tengamos pasos de preprocesamiento, debemos asegurarnos de que tanto la semilla como los hiperparámetros (aquí solomtry
) utilizados sean iguales.Las predicciones de
curClassifier
no son lo mismo que las predicciones delcurClassifier$finalModel
enlace . Has reproducidofinalModel
y lo estás comparando con elpredict.train
objeto.fuente
predict
deberían (y lo hacen en realidad) dar las mismas predicciones en el caso de que el OP explore. Aclaro un poco más este punto en mi publicación.