【问题标题】:How to plot per tree ROC curves from randomForest in R?如何从 R 中的 randomForest 绘制每棵树的 ROC 曲线?
【发布时间】:2017-07-23 07:25:15
【问题描述】:

我知道 randomForest 应该是一个黑盒子,并且大多数人都对分类器的整体 ROC 曲线感兴趣,但我正在解决一个问题,我需要检查 RF 的单个树.我对 R 不是很有经验,那么为 RF 生成的单个树绘制 ROC 曲线的简单方法是什么?

【问题讨论】:

  • 如果你的森林有 1000 根发束,那么将它们可视化是没有意义的。
  • 是的。我正在选择要可视化的树子集。
  • 请提供一些代码,以便我们了解您的意图。

标签: r random-forest roc


【解决方案1】:

我认为您不能从 randomForest 包生成的随机森林中的一棵树生成 ROC 曲线。您可以从预测中访问每棵树的输出,例如在训练集上。

# caret for an example data set
library(caret)
library(randomForest)

data(GermanCredit)

# use only 50 rows for demonstration
nrows = 50

# extract the first 9 columns and 50 rows as training data (column 10 is "Class", the target)
x = GermanCredit[1:nrows, 1:9]
y = GermanCredit$Class[1:nrows]

# build the model
rf_model = randomForest(x = x, y = y, ntree = 11)

# Compute the prediction over the training data. Note predict.all = TRUE
rf_pred = predict(rf_model, newdata = x, predict.all = TRUE, type = "prob")

您可以访问每棵树的预测

 rf_pred$individual

然而,单棵树的预测只是最可能的标签。对于 ROC 曲线,您需要类别概率,以便更改决策阈值会更改预测类别以改变真阳性率和假阳性率。

据我所知,至少在 randomForest 包中,没有办法让叶子输出概率而不是标签。如果你用 getTree() 检查一棵树,你会看到预测是二元的;使用 getTree(rf_model, k = 1, labelVar = TRUE) 你会看到纯文本的标签。

不过,您可以做的是通过 predict.all = TRUE 检索单个预测,然后手动计算整个森林子集的类别标签。然后,您可以将其输入到一个函数中来计算 ROC 曲线,就像 ROCR 包中的曲线一样。

编辑:好的,从您在评论中提供的链接中,我了解了如何获得 ROC 曲线。首先,我们需要提取一棵特定的树,然后将每个数据点输入到树中,以便计算每个节点成功类的出现次数以及每个节点中的总数据点。该比率给出了成功类的节点概率。接下来,我们做类似的事情,即将每个数据点输入到树中,但现在记录概率。这样我们就可以将类概率与真实标签进行比较。 代码如下:

# libraries we need
library(randomForest)
library(ROCR)

# Set fixed seed for reproducibility
set.seed(54321)

# Define function to read out output node of a tree for a given data    point
travelTree = function(tree, data_row) {
    node = 1
    while (tree[node, "status"] != -1) {
        split_value = data_row[, tree[node, "split var"]]
        if (tree[node, "split point"] > split_value ) {
            node = tree[node, "right daughter"]
        } else {
            node = tree[node, "left daughter"]
        }
    }
    return(node)
}

# define number of data rows
nrows = 100
ntree = 11

# load example data
data(GermanCredit)

# Easier access of variables
x = GermanCredit[1:nrows, 1:9]
y = GermanCredit$Class[1:nrows]

# Build RF model
rf_model = randomForest(x = x, y = y, ntree = ntree, nodesize = 10)

# Extract single tree and add variables we need to compute class probs
single_tree = getTree(rf_model, k = 2, labelVar = TRUE)
single_tree$"split var" = as.character(single_tree$"split var")
single_tree$sum_good = 0
single_tree$sum = 0
single_tree$pred_prob = 0


for (zeile in 1:nrow(x)) {
    out_node = travelTree(single_tree, x[zeile, ])
    single_tree$sum_good[out_node] = single_tree$sum_good[out_node] + (y[zeile] == "Good")
    single_tree$sum[out_node] = single_tree$sum[out_node] + 1
}

# Compute class probabilities from count of "Good" data points in each node.
# Make sure we do not divide by zero
idcs = single_tree$sum != 0
single_tree$pred_prob[idcs] = single_tree$sum_good[idcs] /     single_tree$sum[idcs]

# Compute prediction by inserting again data set into tree, but read out
# previously computed probs

single_tree_pred = rep(0, nrow(x))

for (zeile in 1:nrow(x)) {
    out_node = travelTree(single_tree, x[zeile, ])
    single_tree_pred[zeile] = single_tree$pred_prob[out_node]
}

# Et voila: The ROC curve for single tree!
plot(performance(prediction(single_tree_pred, y), "tpr", "fpr"))

【讨论】:

  • 这很有意义!我在 javascript 中读取树并通过沿树运行整个数据集并计算像here 这样的分数来计算叶节点概率。尽管在多类分类案例中,我不确定在叶子中什么才是真正的预测。我是否像您所说的那样使用最有可能的标签?这片叶子中的其他所有内容都算作假吗?以及如何在树的叶子上汇总分数?非常感谢。
  • 我没有想过使用getTree给出的树形结构来手动计算数据上的标签。我认为 randomForest 包中没有这个功能,但实际上可以计算概率。没有多类分类经验;如果按下,我会做一对多的分类。在 ROC 曲线的上下文中,多类也没有任何意义。很抱歉,我无法为您提供更多帮助。
  • 如果您仍在听(可能不再相关,但为了完整起见),我添加了代码以便从随机森林中的一棵树计算 ROC 曲线。玩得开心!
  • 感谢您添加代码!不过,我不确定我对这一行的理解是否正确:single_tree_pred[zeile] = single_tree$pred_prob[out_node] 是否抓住了该样本所在叶节点中真实类的概率?
  • 是的。 single_tree_pred 是一个向量,它保存训练数据x 中每一行的树的输出概率(“zeile”是德语中“row”的意思,忘记更改变量名),所以这一行符合您的想法确实如此。 ROCR 包中的函数prediction() 需要一个与真实标签向量对齐的概率向量,所以这就是我这样做的原因。实际上,您在第一条评论中给出的链接,rapaio 的回答,给了我如何为一棵树提供类概率的灵感。最后这是一个有趣的练习,希望对您有所帮助!
猜你喜欢
  • 2019-02-27
  • 2018-02-17
  • 2017-10-29
  • 2015-11-24
  • 2014-11-18
  • 1970-01-01
  • 1970-01-01
  • 2013-02-27
  • 2017-06-19
相关资源
最近更新 更多