如何确定随机森林分类器中的特征重要性?

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

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

78079 次浏览

它是路由到一个决策节点的样本数量与集合中任何一棵树的特征数量之间的比率,该比率与训练集中的样本总数之间的比率。

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

编辑 : 这个描述只是部分正确: 吉尔斯和彼得的答案是正确的。

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

  1. 将数组 feature_importances初始化为大小为 n_features的所有零。

  2. 遍历树: 对于在特性 i上分裂的每个内部节点,计算该节点的错误减少量乘以路由到该节点的样本数,并将这个数量添加到 feature_importances[i]

减少的误差取决于你使用的杂质准则(例如,基尼,熵,MSE,...)。它是路由到内部节点的示例集的杂质减去由拆分创建的两个分区的杂质之和。

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

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

确实有几种获得特性“重要性”的方法。通常,对于这个词的含义没有严格的共识。

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

在文献或其他一些包中,您还可以发现特性重要性被实现为“均值降低准确度”。基本上,这个想法是当您随机排列该特性的值时,测量 OOB 数据的准确性下降。如果下降幅度很小,那么特征就不重要,反之亦然。

(注意,这两种算法都可以在随机 Forest R 包中找到。)

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

正如@GillesLouppe 在上面指出的,scikit-learn 目前实现了特征重要性的“平均降低杂质”度量。我个人觉得第二个度量更有趣一些,您可以随机地一个一个地排列每个特性的值,然后看看您的现成性能有多差。

因为你所追求的特征重要性是每个特征对你的整体模型的预测性能的贡献,第二个度量实际上给你一个直接的度量,而“平均减少杂质”只是一个很好的代理。

如果你感兴趣,我写了一个小包,它实现了排列重要性度量,可以用来计算一个 scikit-learn 随机森林类的实例的值:

Https://github.com/pjh2011/rf_perm_feat_import

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

密码:

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

返回文章页面决策树地块:
在此输入图像描述
我们得到

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)))

我们得到特征重要性: np.array([0,1.332,6.418,92.30])

归一化后,我们得到 array ([0., 0.01331334, 0.06414793, 0.92253873]),这与 clf.feature_importances_相同。

小心,所有的班级都应该有一个重量级。

对于那些希望参考 scikit-learn 关于这个主题的文档或参考@GillesLouppe 的答案的人:

在随机森林分类器中,estimators_属性是 DecisionTree 分类器的列表(如在 文件中提到的)。为了计算随机森林分类器的 feature_importances_,在 Scikit-learn 的源代码中,它对集合中的所有估计器的(所有 DecisionTree 分类器的) feature_importances_属性进行平均。

在决策树分类器的 文件中,提到“一个特征的重要性被计算为该特征所带来的标准的(规范化)总减少量。这也被称为基尼系数的重要性[1]。”

这里 是一个直接链接,可以获得更多关于变量和基尼重要性的信息,如下面 scikit-learn 的参考文献所提供的。

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

随机森林的特征重要性

  • 随机森林使用许多树,因此,方差减少
  • 随机森林还允许对特征组合进行更多的探索
  • 决策树具有可变重要性,如果杂质减少(基尼杂质减少) ,则重要性更大
  • 每棵树都有不同的重要性顺序

    下面是背景中发生的事情!
  • 我们获取一个属性并检查它所在的所有树,然后获取这个属性分割上同质性变化的平均值。同质性变化的平均值给了我们属性的特征重要性 enter image description here