如何确定RandomForestClassifier中的feature_importances?


125

我有一个按时间序列作为数据输入的分类任务,其中每个属性(n = 23)代表一个特定的时间点。除了绝对分类结果之外,我还想知道,哪些属性/日期对结果有多大程度的贡献。因此,我只是使用feature_importances_,对我来说效果很好。

但是,我想知道如何计算它们以及使用哪种度量/算法。不幸的是,我找不到有关此主题的任何文档。


10
在一个SO线程中拥有三个核心开发人员。那一定是某种记录^^
Andreas Mueller

Answers:


158

实际上,有几种获取功能“重要性”的方法。通常,对该词的含义没有严格的共识。

在scikit-learn中,我们实现了[1]中描述的重要性(经常被引用,但不幸的是很少阅读...)。有时称为“基尼重要性”或“平均减少杂质”,定义为所有节点平均的节点杂质的总减少量(由到达该节点的概率加权(由到达该节点的样本比例近似)合奏的树木。

在文献或其他软件包中,您还可以找到实现为“平均降低精度”的功能重要性。基本上,该想法是测量当您随机排列该功能的值时,OOB数据的准确性下降的情况。如果降低幅度很小,则该功能并不重要,反之亦然。

(请注意,randomForest R软件包中都提供了这两种算法。)

[1]:Breiman,Friedman,“分类和回归树”,1984年。


48
如果重要性属性/示例的文档中提到了此答案,那就太好了。也一直在寻找它:)
d1337

2
看来重要性分数是相对价值?例如,所有功能的重要性得分总和始终为1(请参见scikit-learn.org/stable/auto_examples/ensemble/…的示例)
RNA

5
@RNA:是的,默认情况下,变量重要性在scikit-learn中进行了归一化,因此它们的总和为1。您可以通过遍历各个基本估计量并调用来规避此问题tree_.compute_feature_importances(normalize=False)
吉尔斯·卢佩

2
@GillesLouppe您是否使用袋外样本来衡量每棵决策树回归树森林中MSE的减少?还是树上使用了所有训练数据?
2015年

1
两个有用的资源。(1)blog.datadive.net/…Ando Saabas的博客同时实现了Gilles提到的“平均减少杂质”和“平均减少准确性”。(2)下载并阅读Gilles Louppe的论文。
Mark Teese '18年

54

计算单个树的特征重要性值的常用方法如下:

  1. 您可以feature_importances使用size 初始化一个全零的数组n_features

  2. 您遍历了该树:对于每个在要素上进行了拆分的内部节点,i您需要计算该节点的错误减少率乘以路由到该节点的样本数量,然后将此数量加到feature_importances[i]

减少误差取决于您使用的杂质标准(例如,Gini,熵,MSE等)。它被路由到内部节点的示例集中的杂质减去拆分产生的两个分区的杂质之和。

重要的是这些值是相对于特定数据集的(减少误差和样本数量都是特定于数据集的),因此不能在不同数据集之间比较这些值。

据我所知,还有其他方法可以计算决策树中的特征重要性值。可以在Trevor Hastie,Robert Tibshirani和Jerome Friedman的“统计学习要素”中找到上述方法的简要说明。


12

它是路由到集合中任何树中涉及该功能的决策节点的样本数与训练集中样本总数之间的比率。

决策树的顶级节点中涉及的功能往往会看到更多的样本,因此可能具有更大的重要性。

编辑:此描述仅部分正确:Gilles和Peter的答案是正确的答案。


1
您知道是否有关于确切方法的书面文件/文档吗?例如。Breiman,2001年。如果我有一些适当的文档,可以引用该方法,那将是很棒的。
user2244670 2013年

@ogrisel,如果您可以将您的回答清楚地标记为“权重”的解释,那将是很好的。权重本身并不能决定特征的重要性。在树上平均的“杂质度量”(“基尼重要性”或RSS)与权重相结合,确定了整体特征的重要性。不幸的是,关于scikit-learn的文档在这里:scikit-learn.org/stable/modules/…不准确,并且错误地将“深度”作为杂质度量。
Ariel

11

正如@GillesLouppe上文指出的那样,scikit-learn当前为实现功能重要性而实施了“平均减少杂质”度量。我个人觉得第二个指标更有趣,您可以将每个功能的值随机地一次一个地排列,并查看您的袋装性能有多糟糕。

由于您所追求的功能重要性是每个功能对整体模型的预测性能有多大的贡献,因此第二个指标实际上可以直接衡量您这一点,而“平均减少杂质”只是一个很好的替代。

如果您有兴趣,我写了一个小包来实现置换重要性指标,该包可用于从scikit-learn随机森林类的实例计算值:

https://github.com/pjh2011/rf_perm_feat_import

编辑:这适用于Python 2.7,而不是3


嗨,@ Peter,当我使用您的代码时,出现以下错误:NameError:未定义名称'xrange'。
Aizzaac '17

嗨@Aizzaac。抱歉,我刚开始编写软件包,所以我应该注意到我是为Python 2.7编写的。尝试def xrange(x):在运行它之前返回iter(range(x))
彼得

2

让我尝试回答这个问题。码:

iris = datasets.load_iris()  
X = iris.data  
y = iris.target  
clf = DecisionTreeClassifier()  
clf.fit(X, y)  

Decision_tree 图:
在此处输入图像描述
我们可以获得compute_feature_importance:[0。,0.01333333,0.06405596,0.92261071]
检查源代码:

cpdef compute_feature_importances(self, normalize=True):
    """Computes the importance of each feature (aka variable)."""
    cdef Node* left
    cdef Node* right
    cdef Node* nodes = self.nodes
    cdef Node* node = nodes
    cdef Node* end_node = node + self.node_count

    cdef double normalizer = 0.

    cdef np.ndarray[np.float64_t, ndim=1] importances
    importances = np.zeros((self.n_features,))
    cdef DOUBLE_t* importance_data = <DOUBLE_t*>importances.data

    with nogil:
        while node != end_node:
            if node.left_child != _TREE_LEAF:
                # ... and node.right_child != _TREE_LEAF:
                left = &nodes[node.left_child]
                right = &nodes[node.right_child]

                importance_data[node.feature] += (
                    node.weighted_n_node_samples * node.impurity -
                    left.weighted_n_node_samples * left.impurity -
                    right.weighted_n_node_samples * right.impurity)
            node += 1

    importances /= nodes[0].weighted_n_node_samples

    if normalize:
        normalizer = np.sum(importances)

        if normalizer > 0.0:
            # Avoid dividing by zero (e.g., when root is pure)
            importances /= normalizer

    return importances

尝试计算功能重要性:

print("sepal length (cm)",0)
print("sepal width (cm)",(3*0.444-(0+0)))
print("petal length (cm)",(54* 0.168 - (48*0.041+6*0.444)) +(46*0.043 -(0+3*0.444)) + (3*0.444-(0+0)))
print("petal width (cm)",(150* 0.667 - (0+100*0.5)) +(100*0.5-(54*0.168+46*0.043))+(6*0.444 -(0+3*0.444)) + (48*0.041-(0+0)))

我们得到feature_importance:np.array([0,1.332,6.418,92.30])。
归一化后,我们可以得到数组([0.,0.01331334,0.06414793,0.92253873]),这与相同clf.feature_importances_
请注意,所有班级都应具有一等分量。


1

对于那些希望参考此主题的scikit-learn文档或@GillesLouppe的答案的参考文献:

在RandomForestClassifier中,estimators_attribute是DecisionTreeClassifier的列表(如文档中所述)。为了计算feature_importances_RandomForestClassifier的,在scikit-learn的源代码中,它对feature_importances_集合中所有估算器(所有DecisionTreeClassifer)属性进行平均。

在DecisionTreeClassifer的文档中,提到“要素的重要性是作为该要素带来的条件的(归一化)总缩减而计算的。这也被称为基尼重要性[1]”。

是直接链接,以获取有关变量和基尼重要性的更多信息,如下面scikit-learn的参考所提供。

[1] L. Breiman和A. Cutler,“随机森林”,http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.