我有一个以时间序列作为数据输入的分类任务,其中每个属性 (n=23) 代表一个特定的时间点。除了绝对分类结果,我想知道哪些属性/日期对结果的贡献程度。因此,我只是使用feature_importances_
,这对我来说效果很好。
但是,我想知道它们是如何计算的以及使用了哪种度量/算法。不幸的是,我找不到有关此主题的任何文档。
我有一个以时间序列作为数据输入的分类任务,其中每个属性 (n=23) 代表一个特定的时间点。除了绝对分类结果,我想知道哪些属性/日期对结果的贡献程度。因此,我只是使用feature_importances_
,这对我来说效果很好。
但是,我想知道它们是如何计算的以及使用了哪种度量/算法。不幸的是,我找不到有关此主题的任何文档。
确实有几种方法可以获得功能“重要性”。通常,对于这个词的含义没有严格的共识。
在 scikit-learn 中,我们实现了 [1] 中描述的重要性(经常被引用,但不幸的是很少阅读......)。它有时被称为“基尼重要性”或“平均减少杂质”,定义为节点杂质的总减少量(由到达该节点的概率加权(由到达该节点的样本比例近似))在所有合奏的树。
在文献或其他一些软件包中,您还可以找到实现为“平均降低精度”的特征重要性。基本上,这个想法是在随机排列该特征的值时测量 OOB 数据准确性的降低。如果减少量较低,则该特征不重要,反之亦然。
(请注意,这两种算法都在 randomForest R 包中可用。)
[1]:Breiman, Friedman,“分类和回归树”,1984 年。
计算单个树的特征重要性值的常用方法如下:
feature_importances
您使用 size 初始化一个全零数组n_features
。
您遍历树:对于在特征上拆分的每个内部节点,i
您计算该节点的误差减少乘以路由到该节点的样本数,然后将此数量添加到feature_importances[i]
.
误差减少取决于您使用的杂质标准(例如 Gini、Entropy、MSE、...)。它是路由到内部节点的示例集的杂质减去由拆分创建的两个分区的杂质之和。
重要的是这些值是相对于特定数据集的(误差减少和样本数量都是特定于数据集的),因此无法在不同数据集之间比较这些值。
据我所知,有其他方法可以计算决策树中的特征重要性值。上述方法的简要描述可以在 Trevor Hastie、Robert Tibshirani 和 Jerome Friedman 的“统计学习要素”中找到。
它是路由到决策节点的样本数量与训练集中任何树中涉及该特征的决策节点之间的比率。
决策树的顶级节点中涉及的特征往往会看到更多的样本,因此可能更重要。
编辑:这个描述只是部分正确:吉尔斯和彼得的答案是正确的答案。
正如@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)))
我们得到 feature_importance: np.array([0,1.332,6.418,92.30])
。
归一化后,我们得到array ([0., 0.01331334, 0.06414793, 0.92253873])
,这与 相同clf.feature_importances_
。
小心所有的课程都应该有一个权重。
对于那些寻找 scikit-learn 关于此主题的文档的参考或对@GillesLouppe 答案的参考的人:
在 RandomForestClassifier 中,estimators_
属性是 DecisionTreeClassifier 的列表(如文档中所述)。为了计算feature_importances_
RandomForestClassifier的_feature_importances_
在 DecisionTreeClassifer 的文档中,提到“特征的重要性被计算为该特征带来的标准的(归一化)总减少。它也被称为基尼重要性 [1]。”
这是有关变量和基尼重要性的更多信息的直接链接,如下面的 scikit-learn 参考提供的。
[1] L. Breiman 和 A. Cutler,“随机森林”,http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm