2013-02-05 9 views
7

Weiß jemand, wie gbm in R behandelt fehlende Werte? Ich kann anscheinend keine Erklärung mit Google finden.R gbm Umgang mit fehlenden Werten

+0

Welches Detail genau suchen Sie? Die Hilfeseite für '? Gbm' zeigt, dass es mit fehlenden Werten umgehen kann. Möchten Sie etwas anderes oder zusätzliches wissen? –

+3

@BryanHanson: Ich weiß, dass es mit ihnen umgehen kann, ich suche nur nach einer Erklärung, wie es gemacht wird. – screechOwl

Antwort

11

Um zu erklären, was gbm mit fehlenden Prädiktoren macht, lassen Sie uns zunächst einen einzelnen Baum eines gbm-Objekts visualisieren.

Angenommen, Sie haben ein gbm-Objekt mygbm. Mit pretty.gbm.tree(mygbm, i.tree=1) können Sie den ersten Baum auf mygbm, z.B .: visualisieren

SplitVar SplitCodePred LeftNode RightNode MissingNode ErrorReduction Weight Prediction 
0  46 1.629728e+01  1   5   9  26.462908 1585 -4.396393e-06 
1  45 1.850000e+01  2   3   4  11.363868 939 -4.370936e-04 
2  -1 2.602236e-04  -1  -1   -1  0.000000 271 2.602236e-04 
3  -1 -7.199873e-04  -1  -1   -1  0.000000 668 -7.199873e-04 
4  -1 -4.370936e-04  -1  -1   -1  0.000000 939 -4.370936e-04 
5  20 0.000000e+00  6   7   8  8.638042 646 6.245552e-04 
6  -1 3.533436e-04  -1  -1   -1  0.000000 483 3.533436e-04 
7  -1 1.428207e-03  -1  -1   -1  0.000000 163 1.428207e-03 
8  -1 6.245552e-04  -1  -1   -1  0.000000 646 6.245552e-04 
9  -1 -4.396393e-06  -1  -1   -1  0.000000 1585 -4.396393e-06 

finden Sie in der GBM-Dokumentation. Jede Zeile entspricht einem Knoten, und die erste (unbenannte) Spalte ist die Knotennummer. Wir sehen, dass jeder Knoten einen linken und rechten Knoten hat (die auf -1 gesetzt werden, falls der Knoten ein Blatt ist). Wir sehen auch, dass jedem Knoten eine MissingNode zugeordnet ist.

Um eine Beobachtung in den Baum zu starten, beginnen wir bei Knoten 0. Wenn eine Beobachtung einen fehlenden Wert auf SplitVar = 46 hat, wird sie in den Baum zum Knoten MissingNode = 9 gesendet. Die Vorhersage des Baumes Für eine solche Beobachtung wird SplitCodePred = -4,396393e-06 sein, was die gleiche Vorhersage ist, die der Baum hatte, bevor eine Aufteilung auf den Knoten Null erfolgt (Prediction = -4,396393e-06 für den Knoten Null).

Die Vorgehensweise ist für andere Knoten und Split-Variablen ähnlich.

1

Beginnen Sie mit dem Quellcode dann. Nur gbm an der Konsole eingeben zeigt Ihnen den Quellcode:

function (formula = formula(data), distribution = "bernoulli", 
    data = list(), weights, var.monotone = NULL, n.trees = 100, 
    interaction.depth = 1, n.minobsinnode = 10, shrinkage = 0.001, 
    bag.fraction = 0.5, train.fraction = 1, cv.folds = 0, keep.data = TRUE, 
    verbose = TRUE) 
{ 
    mf <- match.call(expand.dots = FALSE) 
    m <- match(c("formula", "data", "weights", "offset"), names(mf), 
     0) 
    mf <- mf[c(1, m)] 
    mf$drop.unused.levels <- TRUE 
    mf$na.action <- na.pass 
    mf[[1]] <- as.name("model.frame") 
    mf <- eval(mf, parent.frame()) 
    Terms <- attr(mf, "terms") 
    y <- model.response(mf, "numeric") 
    w <- model.weights(mf) 
    offset <- model.offset(mf) 
    var.names <- attributes(Terms)$term.labels 
    x <- model.frame(terms(reformulate(var.names)), data, na.action = na.pass) 
    response.name <- as.character(formula[[2]]) 
    if (is.character(distribution)) 
     distribution <- list(name = distribution) 
    cv.error <- NULL 
    if (cv.folds > 1) { 
     if (distribution$name == "coxph") 
      i.train <- 1:floor(train.fraction * nrow(y)) 
     else i.train <- 1:floor(train.fraction * length(y)) 
     cv.group <- sample(rep(1:cv.folds, length = length(i.train))) 
     cv.error <- rep(0, n.trees) 
     for (i.cv in 1:cv.folds) { 
      if (verbose) 
       cat("CV:", i.cv, "\n") 
      i <- order(cv.group == i.cv) 
      gbm.obj <- gbm.fit(x[i.train, , drop = FALSE][i, 
       , drop = FALSE], y[i.train][i], offset = offset[i.train][i], 
       distribution = distribution, w = ifelse(w == 
        NULL, NULL, w[i.train][i]), var.monotone = var.monotone, 
       n.trees = n.trees, interaction.depth = interaction.depth, 
       n.minobsinnode = n.minobsinnode, shrinkage = shrinkage, 
       bag.fraction = bag.fraction, train.fraction = mean(cv.group != 
        i.cv), keep.data = FALSE, verbose = verbose, 
       var.names = var.names, response.name = response.name) 
      cv.error <- cv.error + gbm.obj$valid.error * sum(cv.group == 
       i.cv) 
     } 
     cv.error <- cv.error/length(i.train) 
    } 
    gbm.obj <- gbm.fit(x, y, offset = offset, distribution = distribution, 
     w = w, var.monotone = var.monotone, n.trees = n.trees, 
     interaction.depth = interaction.depth, n.minobsinnode = n.minobsinnode, 
     shrinkage = shrinkage, bag.fraction = bag.fraction, train.fraction = train.fraction, 
     keep.data = keep.data, verbose = verbose, var.names = var.names, 
     response.name = response.name) 
    gbm.obj$Terms <- Terms 
    gbm.obj$cv.error <- cv.error 
    gbm.obj$cv.folds <- cv.folds 
    return(gbm.obj) 
} 
<environment: namespace:gbm> 

Eine schnelle Lese legt nahe, dass die Daten in ein Modell Rahmen gesetzt wird und dass der NA behandelt werden mit na.pass so wiederum ?na.pass Lesen, dass es aussieht es macht nichts besonderes mit ihnen, aber Sie müssten wahrscheinlich über den ganzen Anpassungsprozess nachlesen, um zu sehen, was das auf lange Sicht bedeutet. Sieht so aus, als müsstest du vielleicht auch den Code von gbm.fit und so weiter betrachten.

1

Die official guide zu gbms führt fehlende Werte zu den Testdaten, so würde ich annehmen, dass sie codiert sind, um fehlende Werte zu behandeln.

4

Es scheint, fehlende Werte an einen separaten Knoten innerhalb jedes Baums zu senden. Wenn Sie ein gbm-Objekt namens "mygbm" haben, sehen Sie, indem Sie "pretty.gbm.tree (mygbm, i.tree = 1)" eingeben, dass es für jeden Split in der Struktur einen LeftNode, einen RightNode und einen MissingNode gibt. Dies impliziert, dass (unter der Annahme, dass interaction.depth = 1 ist) jeder Baum 3 Endknoten hat (1 für jede Seite des Split und einen für wo der Prädiktor fehlt).

1

Das gbm-Paket behandelt insbesondere NAs (fehlende Werte) wie folgt. Der Algorithmus funktioniert, indem er Klassifizierungs- oder Regressionsbäume erstellt und seriell kombiniert. Sogenannte Basis-Lernerbäume werden gebildet, indem Beobachtungen in linke und rechte Teilungen aufgeteilt werden (@ user2332165 ist rechts). Es gibt auch einen separaten Knotentyp von Missing in gbm. Wenn die Zeile oder die Beobachtung keinen Wert für diese Variable enthält, wendet der Algorithmus eine Surrogat-Split-Methode an.

Wenn Sie Surrogat Splitting besser verstehen wollen, empfehle ich das Lesen der package rpart vignette.

Verwandte Themen