如何在Python的Scikit-learn中输出随机森林中每个树的回归预测?

19
有没有办法获得随机森林中每棵树的预测结果,除了组合预测结果之外?我想将所有的预测结果输出到一个列表中,而不是查看整个决策树。我知道可以使用apply方法获取叶节点索引,但我不确定如何从叶节点中获取值。
编辑:以下是我在下面评论中得出的结果。以前我不清楚estimators_属性中的树可以被调用,但似乎predict方法可以使用该属性对每棵树进行预测。然而,这是否是最好的方法呢?
numberTrees = 100
clf = RandomForestRegressor(n_estimators=numberTrees)
clf.fit(X,Y)
for tree in range(numberTrees):
    print(clf.estimators_[tree].predict(val.irow(1)))

11
你可以使用列表推导式完成相同的操作:per_tree_pred = [tree.predict(X) for tree in clf.estimators_] - Bill Cheatham
如果您想匹配模型的并行作业行为,只需复制“predict”的源代码,并省略最后一步,即平均预测! - Matt Hancock
4个回答

4

我相信你所提供的信息已经是最好的了。就像你所说的,predict()方法返回的是整个随机森林的预测结果,而不是它的组成部分树的预测结果。它可以返回一个矩阵,但这仅适用于多目标学习的情况下。在这种情况下,它会为每个目标返回一个预测值,而不是每个树的预测结果。你可以通过在R的随机森林中使用predict.all=True来获取单独的树预测结果,但是sklearn没有这样的功能。如果你尝试使用apply()方法,你会得到一个叶子索引矩阵,然后你仍需要遍历每个树来找出该树/叶子组合的预测结果。因此,我认为你所提供的信息已经是最好的了。


1
感谢您的回复。这似乎是任何使用scikit-learn中集成方法的人都会使用的东西,所以我很惊讶为什么没有更多人提供意见。我的特别兴趣是看看如何使用RF进行具有2个或更多答案的预测。因此,我正在绘制每棵树的预测结果,以查看结果的分布情况。 - chunky

1

我曾遇到同样的问题,不知道你是如何使用 print(clf.estimators_[tree].predict(val.irow(1))) 得到正确答案的。它给我随机数而非实际类别。在阅读了SKlearn源代码后,我意识到我们实际上需要在代码中使用 predict_proba() 而不是 predict,并且它会根据 clf.classes_ 中的顺序给出树预测的类别。例如:

tree_num = 2
tree_pred = clf.estimators_[tree_num].predict_proba(data_test)
print clf.classes_  #gives you the order of the classes
print tree_pred  #gives you an array of 0 with the predicted class as 1
>>> ['class1','class2','class3']
>>> [0, 1, 0]

你可以在数据上使用cls.predict_proba(),它会给出每个类别预测的概率,通过树的累积计算,并且避免了自己逐个查看每棵树的痛苦。
x = clf.predict_proba(data_test) # assume data_test has two instances
print rfc.classes_
print x
>>> ['class1', 'class2', 'class3']
>>> [[0.12 ,  0.02,  0.86], # probabilities for the first instance
     [0.35 ,  0.01,  0.64]]  # for the second instance

嗨,也许是一个后续问题,是否还有一些东西可以取所有这些树的标准偏差/方差?即让我知道我的预测有多可靠? - HME
@HME,建议单独发布跟进问题,以帮助其他可能遇到相同问题的人找到答案。简短回答你的问题:sklearn随机森林回归器中的其中一种方法是“score”,它可以在给定数据和真实类别的情况下给出判定系数。请在此处查看:https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestRegressor.html#sklearn.ensemble.RandomForestRegressor.score - pegah

0
我最近所做的是修改sklearn源代码以获取它。在sklearn包内,sklearn.ensemble.Randomforestregressor中有一个函数,如果你添加print,你将看到每棵树的个别结果。你可以将其更改为返回并获取每棵树的个别结果。
def _accumulate_prediction(predict, X, out, lock):
    """
    This is a utility function for joblib's Parallel.

    It can't go locally in ForestClassifier or ForestRegressor, because joblib
    complains that it cannot pickle it when placed there.
    """
    prediction = predict(X, check_input=False)
    print(prediction)
    with lock:
        if len(out) == 1:
            out[0] += prediction
        else:
            for i in range(len(out)):
                out[i] += prediction[i]

这有点复杂,因为你需要修改sklearn源代码。

-1

我不确定您确切想要什么,但是Scikit-learn的随机森林回归器中有其他一些方法很可能会返回您想要的内容,特别是predict方法!该方法返回一个预测值数组。您所提到的关于获取平均值的是score方法,它只是使用predict方法来返回R平方确定系数的系数。


随机森林是一种集成方法,它平均了许多决策树的预测结果。predict方法给出了所有树的预测结果的平均值,但我想看到给定输入的所有预测结果。例如,如果我在随机森林回归器中使用10个估计器,我想看到来自这10棵树的预测结果,而不是predict方法给出的平均值。 - chunky
@chunky 我知道什么是随机森林,而这很奇怪,因为根据文档,predict 应该会给出每棵树的预测数组,这就是你所要求的。我已经有几个月没有使用随机森林了,现在无法为你测试,但根据文档,你正在描述得分(score),而不是预测(predict)。得分输出平均值,预测输出基于所有树的所有预测数组。 - Ryan Saxe
分数返回的是 R^2 值,这完全不是我想要的。根据文档,预测返回“输入样本的预测回归目标计算为森林中树的平均预测回归目标”。它返回所有树预测的平均值。我不想要预测的平均值,而是预测值本身。 - chunky
啊..我觉得我现在接近了。我正在使用Random Forest中的predict方法来获取森林中树的平均预测值。我只需要对每棵树使用predict方法即可。它看起来像这样。clf = RandomForestRegressor(); clf.fit(X,Y); for tree in range(numberTrees): print(clf.estimators_[tree].predict(val.irow(1)))但我不确定这是否是最好的方法。 - chunky
我的意思是,这样做可以实现,但我仍然不明白当predict返回每个树的预测数组时,你实际上是如何获取值的...理论上,predict返回的是你在for循环中所做的事情的数组。也许你没有使用最新版本的Scikit learn。 - Ryan Saxe
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接