9

有谁知道如何gbm处理R缺失值?我似乎无法使用谷歌找到任何解释。

4

5 回答 5

14

为了解释 gbm 对缺失预测变量的作用,让我们首先可视化 gbm 对象的单个树。

假设您有一个 gbm 对象mygbm。使用pretty.gbm.tree(mygbm, i.tree=1)您可以可视化 mygbm 上的第一棵树,例如:

  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

有关详细信息,请参阅 gbm 文档。每行对应一个节点,第一列(未命名)是节点号。我们看到每个节点都有一个左右节点(如果节点是叶子,则设置为 -1)。我们还看到每个节点都关联了一个MissingNode.

为了在树上运行观察,我们从节点 0 开始。如果观察在SplitVar= 46 上有缺失值,那么它将沿着树向下发送到节点MissingNode= 9。对于这种观察的树的预测将是SplitCodePred= -4.396393e-06,这与在对节点零进行任何拆分之前树的预测相同(节点零Prediction= -4.396393e-06)。

该过程与其他节点和拆分变量类似。

于 2015-09-14T17:39:26.897 回答
5

它似乎将缺失值发送到每棵树中的单独节点。如果您有一个名为“mygbm”的 gbm 对象,那么您将通过键入“pretty.gbm.tree(mygbm, i.tree = 1)”看到树中的每个拆分都有一个 LeftNode、一个 RightNode 和一个 MissingNode。这意味着(假设您有interaction.depth=1)每棵树将有3个终端节点(分裂的每一侧1个,预测器缺失的地方一个)。

于 2013-04-29T12:59:58.067 回答
2

gbms的官方指南在测试数据中引入了缺失值,所以我假设它们被编码为处理缺失值。

于 2013-02-18T17:41:09.257 回答
2

gbm 包特别处理 NA(缺失值),如下所示。该算法通过构建和连续组合分类或回归树来工作。所谓的基础学习树是通过将观察结果分成左右两部分来构建的(@user2332165 是正确的)。gbm 中还有一个单独的节点类型 Missing。如果行或观察没有该变量的值,则算法将应用代理拆分方法。

如果您想更好地理解代理拆分,我建议您阅读包 rpart vignette

于 2014-04-10T22:32:38.627 回答
1

然后从源代码开始。只需gbm在控制台输入即可显示源代码:

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>

快速阅读表明数据被放入模型框架中,NAna.pass依次?na.pass处理从长远来看这意味着什么。看起来您可能还需要查看代码gbm.fit等。

于 2013-02-06T00:20:33.107 回答