Risultati diversi da randomForest via caret e dal pacchetto randomForest di base


14

Sono un po 'confuso: in che modo i risultati di un modello addestrato tramite il cursore possono differire dal modello nella confezione originale? Ho letto Se è necessaria la preelaborazione prima della previsione utilizzando FinalModel di RandomForest con pacchetto di inserimento? ma non uso alcuna preelaborazione qui.

Ho addestrato diverse foreste casuali utilizzando il pacchetto di inserimento e sintonizzazione per valori di mtry diversi.

> 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

Ho trovato mtry = 15 come il miglior parametro su 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. 

Ho valutato il modello con una curva ROC e una matrice di confusione:

##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 matrice di confusione e la precisione risultanti:

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

           Accuracy : 0.8984
 ....

Ora ho allenato un Random Rorest con gli stessi parametri e gli stessi training_data usando il pacchetto randomForest di base:

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

Ancora una volta ho creato previsioni per lo stesso test_data di cui sopra e valutato la matrice di confusione con lo stesso codice di cui sopra. Ma ora ho ottenuto diverse misure:

Confusion Matrix and Statistics

      Reference
Prediction   No  Yes
       No  2702  897
       Yes  430 6480

           Accuracy : 0.8737 
           ....

Qual è il motivo? Cosa mi sto perdendo?


3
Hai usato lo stesso valore per il seme casuale per entrambi i modelli?
mmmmmmmmmm

Credo di si. Ho impostato il seed precedentemente nel codice quando ho diviso il set di dati in training e test data, quindi ho addestrato il modello del cursore, quindi ho addestrato il modello rf "originale". Quindi il seme dovrebbe rimanere lo stesso una volta fissato all'inizio, no?
Malte,

Ho provato a inserire un altro set.seed direttamente prima di allenare il modello rf "originale". Purtroppo non risolve il problema.
Malte,

3
Dovresti testarlo usando l' seedsargomento ditrainControl
topepo

Risposte:


4

Penso che la domanda, sebbene alquanto banale e "programmatica" a prima lettura, tocchi due questioni principali che sono molto importanti nelle moderne statistiche:

  1. riproducibilità dei risultati e
  2. algoritmi non deterministici.

Il motivo dei diversi risultati è che le due procedure vengono addestrate utilizzando diversi semi casuali. Foreste casuali utilizza un sottoinsieme casuale dalle variabili del intero set di dati come candidati per ogni divisione (che è l' mtryargomento e si riferisce al metodo sottospazio casuale ) così come sacchetti (aggregati bootstrap) di dati originale per diminuire la varianza del modello. Queste due procedure interne di campionamento casuale non sono deterministiche tra differenti esecuzioni dell'algoritmo. L'ordine casuale in cui viene eseguito il campionamento è controllato dai semi casuali utilizzati. Se si usassero gli stessi semi, si otterrebbero gli stessi esatti risultati in entrambi i casi in cui randomForestviene chiamata la routine; entrambi internamentecaret::traincosì come esternamente quando si adatta manualmente una foresta casuale. Allego un semplice frammento di codice per mostrare questo caso. Si prega di notare che uso un numero molto piccolo di alberi (argomento:) ntreeper mantenere l'allenamento veloce, dovrebbe essere generalmente molto più grande.

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) 

A questo punto sia l' caret.trainoggetto fitRFcaretche l' randomForestoggetto definito manualmente fitRFmanualsono stati addestrati usando gli stessi dati ma, soprattutto, usando gli stessi semi casuali quando si adatta il loro modello finale. Pertanto, quando proveremo a prevedere l'utilizzo di questi oggetti e poiché non eseguiamo la preelaborazione dei nostri dati , otterremo le stesse risposte esatte.

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

Giusto per chiarire questo punto un po 'più avanti: predict(xx$finalModel, testData)e predict(xx, testData)sarà diverso se si imposta l' preProcessopzione durante l'utilizzo train. D'altra parte, quando si usa finalModeldirettamente è equivalente usando la predictfunzione del modello montato ( predict.randomForestqui) invece di predict.train; non ha luogo alcun processo preliminare. Ovviamente nello scenario delineato nella domanda originale in cui non viene eseguita alcuna pre-elaborazione, i risultati saranno gli stessi quando si utilizza l'oggetto finalModel, l' randomForestoggetto montato manualmente o l' caret.trainoggetto.

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

Consiglio vivamente di impostare sempre il seme casuale utilizzato da R, MATLAB o qualsiasi altro programma utilizzato. Altrimenti, non è possibile verificare la riproducibilità dei risultati (che OK, potrebbe non essere la fine del mondo) né escludere un bug o un fattore esterno che influisce sull'esecuzione di una procedura di modellazione (che sì, fa schifo). Molti dei principali algoritmi ML (ad es. Aumento del gradiente, foreste casuali, reti neurali estreme) utilizzano determinate procedure di ricampionamento interno durante le fasi di addestramento, stabilire gli stati di seme casuali prima (o talvolta anche all'interno) della fase di addestramento può essere importante.


La parte importante era impostare esplicitamente l'argomento seed in "trainControl" usando l'argomento "seeds"
Malte

Sì, naturalmente. Volevo assicurarmi che il problema sul perché fosse necessario fosse chiarito completamente.
usεr11852 dice Reinstate Monic il

Come posso eseguire in trainmodo che sia esattamente equivalente a randomForest? Ho provato method="none"ma non sono sicuro di come impostare il seme sul singolo valore. Grazie.
Simon Woodward,

Ci scusiamo ma non è chiaro se si dispone di uno preProcesso come randomForestè addestrato per iniziare. In generale, supponendo che non ci siano fasi di pre-elaborazione, dobbiamo assicurarci che sia il seme che gli iperparametri (qui solo mtry) usati siano gli stessi.
usεr11852 dice Reinstate Monic

0

Le previsioni da curClassifiernon corrispondono alle previsioni dal curClassifier$finalModel collegamento . Hai riprodotto finalModele lo stai confrontando con l' predict.trainoggetto.


1
Sebbene ciò che dici sia vero, sfortunatamente è un po 'fuorviante nell'impostazione attuale poiché nessun OP viene eseguito dall'elaborazione preliminare. Entrambi predictdovrebbero (e effettivamente) dare le stesse previsioni nel caso esplorato dall'OP. Chiarisco questo punto un po 'di più nel mio post.
Usεr11852 dice Reinstate Monic il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.