Różne wyniki z randomForest za pomocą karetki i podstawowego pakietu randomForest

14

Jestem trochę zdezorientowany: w jaki sposób wyniki wyszkolonego Modelu za pomocą karetki mogą różnić się od modelu w oryginalnym opakowaniu? Czytałem, czy wstępne przetwarzanie jest potrzebne przed prognozowaniem przy użyciu FinalModel z RandomForest z pakietem Caret? ale nie używam tutaj żadnego przetwarzania wstępnego.

Trenowałem różne Losowe Lasy, używając pakietu Caret i dostosowując je do różnych wartości 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

Odkryłem, że mtry = 15 jest najlepszym parametrem w danych treningowych:

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

Oceniłem model za pomocą krzywej ROC i macierzy zamieszania:

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

Wynikowa macierz nieporozumień i dokładność:

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

           Accuracy : 0.8984
 ....

Teraz trenowałem Random Rorest z tymi samymi parametrami i tymi samymi danymi_ treningowymi przy użyciu podstawowego pakietu randomForest:

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

Ponownie stworzyłem prognozy dla tych samych danych test_danych jak powyżej i oceniłem macierz pomyłek przy użyciu tego samego kodu jak powyżej. Ale teraz mam inne środki:

Confusion Matrix and Statistics

      Reference
Prediction   No  Yes
       No  2702  897
       Yes  430 6480

           Accuracy : 0.8737 
           ....

Jaki jest powód? czego mi brakuje?

Malta
źródło
3
Czy użyłeś tej samej wartości dla losowego materiału siewnego dla obu modeli?
mmmmmmmmmm
Chyba tak. Ustawiłem ziarno wcześniej w kodzie podczas dzielenia zestawu danych na dane treningowe i testowe, następnie wyszkoliłem model daszka, a następnie wyszkoliłem „oryginalny” model rf. Więc ziarno powinno pozostać takie samo, gdy zostanie ustawione na początku, prawda?
Malte
Próbowałem wstawić kolejny set.seed bezpośrednio przed treningiem „oryginalnego” modelu RF. Niestety nie rozwiązuje problemu.
Malte
3
Powinieneś to sprawdzić za pomocą seedsargumentutrainControl
topepo

Odpowiedzi:

4

Wydaje mi się, że pytanie, choć nieco trywialne i „programistyczne” na pierwszy rzut oka, dotyczy dwóch głównych kwestii, które są bardzo ważne we współczesnej statystyce:

  1. odtwarzalność wyników i
  2. algorytmy niedeterministyczne.

Powodem różnych wyników jest to, że dwie procedury są trenowane przy użyciu różnych losowych nasion. Losowe lasy używają losowego podzbioru ze zmiennych pełnego zestawu danych jako kandydatów przy każdym podziale (to mtryargument i dotyczy metody losowej podprzestrzeni ), a także zewnętrznie przy ręcznym dopasowywaniu losowego lasu. Załączam prosty fragment kodu, aby to pokazać. Pamiętaj, że używam bardzo małej liczby drzew (argument:), aby szybko trenować, powinna być ogólnie znacznie większa. worków (agregatów ładowania początkowego) oryginalny zestaw danych w celu zmniejszenia wariancji modelu. Te dwie wewnętrzne procedury losowego próbkowania nie są deterministyczne między różnymi przebiegami algorytmu. Losowa kolejność pobierania próbek jest kontrolowana przez użyte losowe nasiona. Gdyby zastosowano te same nasiona, uzyskano by dokładnie takie same wyniki w obu przypadkach, w których randomForestwywoływana jest procedura; oba wewnętrznie wcaret::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) 

W tym momencie zarówno caret.trainobiekt, fitRFcaretjak i ręcznie zdefiniowany randomForestobiekt fitRFmanualzostały przeszkolone przy użyciu tych samych danych, ale co ważne przy użyciu tych samych losowych nasion podczas dopasowywania ich ostatecznego modelu. W związku z tym, gdy spróbujemy przewidzieć użycie tych obiektów, a ponieważ nie przetwarzamy wstępnie naszych danych , otrzymamy te same dokładne odpowiedzi.

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

Aby wyjaśnić ten punkt później, nieco dalej: predict(xx$finalModel, testData)i predict(xx, testData)będzie inaczej, jeśli ustawisz preProcessopcję podczas używania train. Z drugiej strony, gdy używasz finalModelbezpośrednio, jest to równoważne z użyciem predictfunkcji z zamontowanego modelu ( predict.randomForesttutaj) zamiast predict.train; nie ma wstępnego przetwarzania. Oczywiście w scenariuszu przedstawionym w pierwotnym pytaniu, w którym nie wykonuje się wstępnego przetwarzania, wyniki będą takie same przy użyciu finalModelręcznie dopasowanego randomForestobiektu lub caret.trainobiektu.

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

Zdecydowanie sugeruję, abyś zawsze ustawiał losowe ziarno używane przez R, MATLAB lub jakikolwiek inny używany program. W przeciwnym razie nie można sprawdzić odtwarzalności wyników (co OK, może to nie być koniec świata), ani wykluczyć błędu lub czynnika zewnętrznego wpływającego na wydajność procedury modelowania (co jest do bani). Wiele wiodących algorytmów ML (np. Zwiększanie gradientu, losowe lasy, ekstremalne sieci neuronowe) stosuje pewne wewnętrzne procedury ponownego próbkowania podczas faz treningu, ustalanie losowych stanów nasion przed (a czasem nawet wewnątrz) fazą szkolenia może być ważne.

usεr11852 mówi Reinstate Monic
źródło
Ważną częścią było jawne ustawienie argumentu nasion w „trainControl” za pomocą argumentu „nasiona”
Malte
Tak oczywiście. Chciałem się upewnić, że kwestia, dlaczego jest to potrzebne, została w pełni wyjaśniona.
usεr11852 mówi Przywróć Monic
Jak uruchomić, trainaby dokładnie odpowiadał randomForest? Próbowałem, method="none"ale nie jestem pewien, jak ustawić ziarno na pojedynczą wartość. Dzięki.
Simon Woodward,
Przepraszam, ale nie jest jasne, czy je masz, preProcesslub jak randomForestzacząć szkolenie. Ogólnie rzecz biorąc, zakładając, że nie mamy kroków wstępnego przetwarzania, musimy upewnić się, że zarówno ziarno, jak imtry użyte hiperparametry (tutaj właśnie ) są takie same.
usεr11852 mówi: Przywróć Monic
0

Prognozy z curClassifiernie są takie same jak prognozy z curClassifier$finalModel linku . Reprodukujesz finalModeli porównujesz go z predict.trainobiektem.

tomaz
źródło
1
Chociaż to, co mówisz, jest prawdą, jest to niestety nieco mylące w obecnym ustawieniu, ponieważ OP nie wykonuje wstępnego przetwarzania. Oba predictpowinny (i faktycznie) dają takie same prognozy w przypadku, gdy OP bada. Tę kwestię wyjaśnię nieco bardziej w moim poście.
usεr11852 mówi Przywróć Monic