【问题标题】:scikit learn - feature importance calculation in decision treesscikit learn - 决策树中的特征重要性计算
【发布时间】:2018-08-16 15:21:57
【问题描述】:

我试图了解如何为 sci-kit learn 中的决策树计算特征重要性。之前已经提出过这个问题,但我无法重现算法提供的结果。

例如:

from StringIO import StringIO

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree.export import export_graphviz
from sklearn.feature_selection import mutual_info_classif

X = [[1,0,0], [0,0,0], [0,0,1], [0,1,0]]

y = [1,0,1,1]

clf = DecisionTreeClassifier()
clf.fit(X, y)

feat_importance = clf.tree_.compute_feature_importances(normalize=False)
print("feat importance = " + str(feat_importance))

out = StringIO()
out = export_graphviz(clf, out_file='test/tree.dot')

导致特征重要性:

feat importance = [0.25       0.08333333 0.04166667]

并给出以下决策树:

现在,answer 的类似问题表明重要性计算为

其中 G 是节点杂质,在本例中为 gini 杂质。据我了解,这是减少杂质。但是,对于功能 1,这应该是:

answer 表明重要性由到达节点的概率加权(近似于到达该节点的样本比例)。同样,对于功能 1,这应该是:

这两个公式都提供了错误的结果。如何正确计算特征重要性?

【问题讨论】:

  • 如果您查看source code,重要性也会被归一化。归一化是以输出的总和等于 1 的方式完成的。您还可以在此处查看有关计算的其他详细信息。
  • 是的,实际上我的示例代码是错误的。计算出的特征重要性使用clf.tree_.compute_feature_importances(normalize=False) 计算。我更新了我的答案。

标签: python scikit-learn decision-tree feature-selection


【解决方案1】:

我认为特性的重要性取决于实现,所以我们需要查看 scikit-learn 的文档。

特征重要性。越高,特征越重要。特征的重要性被计算为该特征带来的标准的(归一化)总减少。它也被称为基尼重要性

减少或加权信息增益定义为:

加权杂质减少方程如下:

N_t / N * (impurity - N_t_R / N_t * right_impurity - N_t_L / N_t * left_impurity)

其中N是样本总数,N_t是当前节点的样本数,N_t_L是左孩子的样本数,N_t_R是右孩子的样本数。

http://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html#sklearn.tree.DecisionTreeClassifier

由于在您的情况下每个功能都使用一次,因此功能信息必须等于上面的等式。

对于 X[2]:

feature_importance = (4 / 4) * (0.375 - (0.75 * 0.444)) = 0.042

对于 X[1]:

feature_importance = (3 / 4) * (0.444 - (2/3 * 0.5)) = 0.083

对于 X[0]:

feature_importance = (2 / 4) * (0.5) = 0.25

【讨论】:

  • 很好的答案!只是 X[2] 是 X[0],而 X[0] 是 X[2]
  • 你从哪里引用公式?
  • @Pulse9 我认为你说的不是真的。 X[2]的特征重要性为0.042
  • @agent18,公式位于给定链接的min_impurity_decrease参数下。
【解决方案2】:

单个特征可以在树的不同分支中使用,特征重要性是它在减少杂质方面的总贡献。

feature_importance += number_of_samples_at_parent_where_feature_is_used\*impurity_at_parent-left_child_samples\*impurity_left-right_child_samples\*impurity_right

杂质是基尼/熵值

normalized_importance = feature_importance/number_of_samples_root_node(total num of samples)

如上例:

feature_2_importance = 0.375*4-0.444*3-0*1 = 0.16799 , 
normalized = 0.16799/4(total_num_of_samples) = 0.04199

如果在其他分支中使用了feature_2,则计算它在每个此类父节点的重要性并对值求和。

计算的特征重要性与库返回的特征重要性存在差异,因为我们使用的是图中看到的截断值。

相反,我们可以使用分类器的“tree_”属性访问所有需要的数据,该属性可用于探测使用的特征、阈值、杂质、每个节点的样本数等。

例如:clf.tree_.feature 给出了使用的功能列表。负值表示它是叶节点。

类似地,clf.tree_.children_left/right 为左右孩子提供clf.tree_.feature 的索引

使用上述遍历树并使用clf.tree_.impurity & clf.tree_.weighted_n_node_samples 中的相同索引来获取每个节点及其子节点处的基尼/熵值和样本数。

def dt_feature_importance(model,normalize=True):

    left_c = model.tree_.children_left
    right_c = model.tree_.children_right

    impurity = model.tree_.impurity    
    node_samples = model.tree_.weighted_n_node_samples 

    # Initialize the feature importance, those not used remain zero
    feature_importance = np.zeros((model.tree_.n_features,))

    for idx,node in enumerate(model.tree_.feature):
        if node >= 0:
            # Accumulate the feature importance over all the nodes where it's used
            feature_importance[node]+=impurity[idx]*node_samples[idx]- \
                                   impurity[left_c[idx]]*node_samples[left_c[idx]]-\
                                   impurity[right_c[idx]]*node_samples[right_c[idx]]

    # Number of samples at the root node
    feature_importance/=node_samples[0]

    if normalize:
        normalizer = feature_importance.sum()
        if normalizer > 0:
            feature_importance/=normalizer

    return feature_importance

此函数将返回与clf.tree_.compute_feature_importances(normalize=...) 返回的完全相同的值

根据重要性对特征进行排序

features = clf.tree_.feature[clf.tree_.feature>=0] # Feature number should not be negative, indicates a leaf node
sorted(zip(features,dt_feature_importance(clf,False)[features]),key=lambda x:x[1],reverse=True)

【讨论】:

    猜你喜欢
    • 2016-03-18
    • 2019-12-11
    • 2016-12-31
    • 2017-11-04
    • 2020-05-27
    • 2018-05-15
    • 2017-03-02
    • 2019-02-14
    • 2017-02-23
    相关资源
    最近更新 更多