k-fache Kreuzvalidierung für Random Forest

Wie erweitere ich R um eigene Funktionen oder Pakete? Welches Paket ist passend für meine Fragestellung?

Moderatoren: EDi, jogo

Mia89
Beiträge: 15
Registriert: Sa Mär 30, 2019 12:39 pm

k-fache Kreuzvalidierung für Random Forest

Beitrag von Mia89 »

Hallo,
ich würde gerne eine k-fache Kreuzvalidierung für ein Random Forest Model durchführen um die optimale Anzahl an Bäumen zu erhalten.
Die Theorie ist mir klar, zuerst k-folds bilden mit dem Trainingsdatensatz, dann Tuning Parameter festlegen.
Dann mein Model auf k-1 folds fitten und die Werte auf dem Validierungsset vorhersagen.
Allerdings weiß ich nicht, wie ich mein Model aufstellen soll, bzw. wie ich ein Model z.b. mit k=10 dann 10 mal hintereinander fitte, damit jedes Fold einmal Validierungsset ist.

Könnte mir jemand anhand eines R-Codes die einzelnen Schritte erklären?

Vielen Dank im Voraus
Benutzeravatar
EDi
Beiträge: 1599
Registriert: Sa Okt 08, 2016 3:39 pm

Re: k-fache Kreuzvalidierung für Random Forest

Beitrag von EDi »

Willst du alles mit der Hand machen oder dürfen es auch higher-level Funktionen sein?

Für zweiteres schau dir mal caret an.
rsample ist etwas mehr low level(https://www.google.com/amp/s/rdrr.io/a/ ... ld_cv.html), und man kann viele individuell damit anstellen.
Wennes Noch tiefer gehen soll, dann ist dir Frage vermutlich zu umfangreich und zu wage für dieses Forum.
Bitte immer ein reproduzierbares Minimalbeispiel angeben. Meinungen gehören mir und geben nicht die meines Brötchengebers wieder.

Dieser Beitrag ist lizensiert unter einer CC BY 4.0 Lizenz
Bild.
Mia89
Beiträge: 15
Registriert: Sa Mär 30, 2019 12:39 pm

Re: k-fache Kreuzvalidierung für Random Forest

Beitrag von Mia89 »

Eigentlich wollte ich alles per Hand erstellen. Also das Random Forest Model habe ich schon aufgestellt, komme bei der CV leider nicht weiter.
bigben
Beiträge: 2777
Registriert: Mi Okt 12, 2016 9:09 am

Re: k-fache Kreuzvalidierung für Random Forest

Beitrag von bigben »

Hier ein erster Ansatz für die Kreuzvalidierung "von Hand". Schau Dir das mal an und schreib, ob Du damit was anfangen kannst.

Code: Alles auswählen

pseudodaten <- data.frame(a = rnorm(98), b = runif(98))

pseudodaten$gruppe <- sample(gl(n=10, k=10, length=nrow(pseudodaten)))

for(leave_out in levels(pseudodaten$gruppe)){
  print(leave_out)
  training <- subset(pseudodaten, pseudodaten$gruppe != leave_out)
  test <- subset(pseudodaten, pseudodaten$gruppe == leave_out)
  print(nrow(training))
  print(coef(lm(a ~ b, training)))
}
Mit der Funktion gl kann man zehn verschiedene Gruppen erzeugen. Wenn Du die Funktion nicht kennst, dann lies gl nach. Der Aufruf von sample ist dazu da, die Zuordnung zu den Gruppen zufällig zu machen. Anschließend rufe ich eine for-Schleife auf, in der für jede der zehn Gruppen ein Trainings- und ein Testdatensatz via subset erstellt werden. Danach habe ich nur zwei print-Aufrufe um zu zeigen, dass was passiert. An deren Stelle musst Du Deine Random-Forest auf Basis des Training-Datensatzes erstellen und mit dem Test-Datensatz evaluieren. Kriegst Du das selbst hin?

LG,
Bernhard
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte
Mia89
Beiträge: 15
Registriert: Sa Mär 30, 2019 12:39 pm

Re: k-fache Kreuzvalidierung für Random Forest

Beitrag von Mia89 »

Super vielen Dank, ich versuche es gleich mal.
Kannst du mir vielleicht auch noch sagen wie ich die AUC als Evaluationsmaß einstelle?
Mia89
Beiträge: 15
Registriert: Sa Mär 30, 2019 12:39 pm

Re: k-fache Kreuzvalidierung für Random Forest

Beitrag von Mia89 »

Ich habe es jetzt mal versucht, allerdings funktioniert es nicht, wo mache ich denn einen Fehler?

Code: Alles auswählen

data.training$gruppe <- sample(gl(n=5, k=5, length=nrow(data.training)))

for(leave_out in levels(data.training$gruppe)){
  print(leave_out)
  training <- subset(data.training, data.training$gruppe != leave_out)
  test <- subset(data.training, data.training$gruppe == leave_out)
  
  print(nrow(training))
 
  #train RF
trainrf= randomForest(
    x = training
    , y = as.factor(training)
    , ntree = c(200, 400, 600)
    , mtry = c(2, 4, 6)
    , importance = TRUE
    , do.trace = 20)

predirf = predict(trainrf, newdata = test)

err.vect[leave_out] =roc.area(test, predirf)
print(paste("AUC for fold", leave_out, ":", err.vect[leave_out]))
}

print(paste("Average AUC:", mean(err.vect)))
bigben
Beiträge: 2777
Registriert: Mi Okt 12, 2016 9:09 am

Re: k-fache Kreuzvalidierung für Random Forest

Beitrag von bigben »

Hallo Mia!

"Es funktioniert nicht" ist nie eine gute Fehlerbeschreibung. Was genau funktinioniert nicht? Ich nehme an, Du erhälst eine Fehlermeldung. Welche denn genau?

In Deinem Code fehlt zunächst einmal ein Aufruf von

Code: Alles auswählen

library(randomForest)
Ohne das kann es nicht laufen.

Dann habe ich Deinen Datensatz nicht, kann das also bei mir nicht laufen lassen. Ins Auge sticht mir aber folgendes:

Code: Alles auswählen

trainrf= randomForest(
    x = training
    , y = as.factor(training)
    ...
Wenn training ein Dataframe ist, dann kann dieser nicht gleichzeitig x und y im Aufruf sein. Du müsstest randomForest schon irgendwie mitteilen, welche Spalten in diesem Dataframe als Prädiktoren und welche als Ergebnis, anders gesagt, was die unabhängigen und was die abhängige Variable ist. Wenn ich R wäre, würde ich an dieser Stelle wahrscheinlich eine Fehlermeldung ausgeben.

LG,
Bernhard
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte
Mia89
Beiträge: 15
Registriert: Sa Mär 30, 2019 12:39 pm

Re: k-fache Kreuzvalidierung für Random Forest

Beitrag von Mia89 »

Danke schonmal für den Tipp.
Also die Pakete habe ich alles schon geladen.

Das mit dem x und y vector ist ein guter Hinweis.

Wenn ich für y = as.factor(trainingset.mt.y) einsetze, erhalte ich dennoch die gleiche Fehlermeldung.

Ganz am Anfang habe ich meine Datensatz in verschiedene Matrix und Data.frame Versionen aufgeteilt, so dass mein normales Random Forest Model so aussieht :

Code: Alles auswählen

 library(randomForest)
 set.seed(1234)
    RF.mod = randomForest(
          x = trainingset.mt.X
        , y = as.factor(trainingset.mt.y)
        , ntree = 500
        , mtry = 3
        , importance = TRUE
        , do.trace = 10)

Code: Alles auswählen

Fehler: Must use a vector in `[`, not an object of class matrix.
Call `rlang::last_error()` to see a backtrace
> 
> print(paste("Average AUC:", mean(err.vect)))
Fehler in mean(err.vect) : Objekt 'err.vect' nicht gefunden
bigben
Beiträge: 2777
Registriert: Mi Okt 12, 2016 9:09 am

Re: k-fache Kreuzvalidierung für Random Forest

Beitrag von bigben »

Mia89 hat geschrieben: Mo Apr 01, 2019 1:09 pmDas mit dem x und y vector ist ein guter Hinweis.
Ja, da würde ich weiter nach Deinem Fehler suchen.
Wenn ich für y = as.factor(trainingset.mt.y) einsetze, erhalte ich dennoch die gleiche Fehlermeldung.
Keine Ahnung, was trainingsset.mt.y bedeuten soll, hast Du bislang hier noch nicht definiert.

Da ich die AUC-Funktionen in randomForest nicht kenne, habe ich mal ein numerisches Beispiel gebastelt, bei dem der RSME bestimmt wird. Vielleicht hilft das ja.

Code: Alles auswählen

library(randomForest)
k <- 10

x=rnorm(304); y=runif(304); z=ifelse(x>0, jitter(2*x+y^2), x-y)
beispieldaten <- data.frame(x=x, y=y, z=z)

beispieldaten$gruppe <- sample(gl(n=k, k=1, length=nrow(beispieldaten)))

rsme <- numeric(0)

for(leave_out in levels(beispieldaten$gruppe)){
  training <- subset(beispieldaten, beispieldaten$gruppe != leave_out)
  test <- subset(beispieldaten, beispieldaten$gruppe == leave_out)
  
  cat(paste0("\nDurchgang: ",leave_out," Trainingsdaten: ", nrow(training), "\n"))
  
  #train RF
  trainrf <- randomForest(z ~ x + y, data = training)
  
  predirf = predict(trainrf, newdata = test)

  rsme1 <- sqrt(mean((test$z-predirf)^2))
  rsme <- append(rsme, rsme1)
  cat(paste0("RSME = ", round(rsme1,3)))
}

print(paste("Average RSME:", mean(rsme)))

LG,
Bernhard
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte
Benutzeravatar
EDi
Beiträge: 1599
Registriert: Sa Okt 08, 2016 3:39 pm

Re: k-fache Kreuzvalidierung für Random Forest

Beitrag von EDi »

Code: Alles auswählen

Fehler: Must use a vector in `[`, not an object of class matrix.
Call `rlang::last_error()` to see a backtrace
> 
rlang?! Hätte ich jetzt nicht hier erwartet...

Da das randomForest keine Abhängigkeit hat und wesentlich älter als rlang ist, vermute ich das der Fehler woanders herrührt.
Vermutlich weil du tibble anstatt eine matrix übergibst. Aber ohne ein reproduzierbares Beispie ist das alles höchst spekulativ...

Generell würde ich NIE ein tibble an Funktionen übergeben die nicht aus dem tidyverse stammen (=alle Modellierungsfunktionen)...
Bitte immer ein reproduzierbares Minimalbeispiel angeben. Meinungen gehören mir und geben nicht die meines Brötchengebers wieder.

Dieser Beitrag ist lizensiert unter einer CC BY 4.0 Lizenz
Bild.
Antworten