如何解释决策树的图形结果并找到信息最多的特征?

Posted

技术标签:

【中文标题】如何解释决策树的图形结果并找到信息最多的特征?【英文标题】:How to interpret decision trees' graph results and find most informative features? 【发布时间】:2016-04-24 14:19:49 【问题描述】:

我正在使用 sk-learn python 27 并输出了一些决策树特征结果。虽然我不确定如何解释结果。起初,我认为这些功能是从信息最多到信息最少(从上到下)列出的,但是检查它所暗示的 \n 值。如何从输出或使用 python 行中识别前 5 个信息量最大的特征?

from sklearn import tree

tree.export_graphviz(classifierUsed2, feature_names=dv.get_feature_names(), out_file=treeFileName)     

# Output below
digraph Tree 
node [shape=box] ;
0 [label="avg-length <= 3.5\ngini = 0.0063\nsamples = 250000\nvalue = [249210, 790]"] ;
1 [label="name-entity <= 2.5\ngini = 0.5\nsamples = 678\nvalue = [338, 340]"] ;
0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ;
2 [label="first-name=wm <= 0.5\ngini = 0.4537\nsamples = 483\nvalue = [168, 315]"] ;
1 -> 2 ;
3 [label="name-entity <= 1.5\ngini = 0.4016\nsamples = 435\nvalue = [121, 314]"] ;
2 -> 3 ;
4 [label="substring=ee <= 0.5\ngini = 0.4414\nsamples = 73\nvalue = [49, 24]"] ;
3 -> 4 ;
5 [label="substring=oy <= 0.5\ngini = 0.4027\nsamples = 68\nvalue = [49, 19]"] ;
4 -> 5 ;
6 [label="substring=im <= 0.5\ngini = 0.3589\nsamples = 64\nvalue = [49, 15]"] ;
5 -> 6 ;
7 [label="lastLetter-firstName=w <= 0.5\ngini = 0.316\nsamples = 61\nvalue = [49, 12]"] ;
6 -> 7 ;
8 [label="firstLetter-firstName=w <= 0.5\ngini = 0.2815\nsamples = 59\nvalue = [49, 10]"] ;
7 -> 8 ;
9 [label="substring=sa <= 0.5\ngini = 0.2221\nsamples = 55\nvalue = [48, 7]"] ;
... many many more lines below

【问题讨论】:

【参考方案1】:

正如 kazemakase 已经指出的那样,您可以使用分类器获得最重要的特征。feature_importances_:

print(sorted(list(zip(classifierUsed2.feature_importances_, dv.get_feature_names()))))

顺便补充一下,我个人更喜欢下面的打印结构(修改自this question/answer):

# Print Decision rules:
def print_decision_tree(tree, feature_names):
    left      = tree.tree_.children_left
    right     = tree.tree_.children_right
    threshold = tree.tree_.threshold
    features  = [feature_names[i] for i in tree.tree_.feature]
    value = tree.tree_.value

    def recurse(left, right, threshold, features, node, indent=""):
        if (threshold[node] != -2):
            print (indent+"if ( " + features[node] + " <= " + str(threshold[node]) + " ) ")
            if left[node] != -1:
                recurse (left, right, threshold, features,left[node],indent+"   ")
            print (indent+" else ")
            if right[node] != -1:
                recurse (left, right, threshold, features,right[node],indent+"   ")
            print (indent+"")
        else:
            print (indent+"return " + str(value[node]))

    recurse(left, right, threshold, features, 0)

# Use it like this:
print_decision_tree(classifierUsed2, dv.get_feature_names())

【讨论】:

有趣,我想知道如何解释这棵锯齿形树。前 5 个功能总是信息量最大的 5 个功能吗?或者当有一个“其他”转弯时,会出现下一个信息量最大的信息? @KubiK888 很可能,但我也不确定。我认为 feature_importances_ 非常可靠,因此您可以将重要性与树中特征的位置进行比较。不幸的是,伯克利大学网站目前不可用(stat.berkeley.edu/~breiman/RandomForests/cc_home.htm),其中描述了计算重要性的过程的背景。【参考方案2】:

    在 Python 中,您可以使用 DecisionTreeClassifier.feature_importances_,根据 documentation 包含

    特征重要性。越高,特征越重要。 特征的重要性被计算为(归一化的)总 降低该特征带来的标准。这也是众所周知的 作为基尼重要性 [R66]。

    只需对特征重要性执行np.argsort 即可获得特征排名(不考虑平局)。

    您可以查看Gini impurity(graphviz 输出中的\ngini)以获得第一个想法。越低越好。但是,请注意,如果在多个拆分中使用一个特征,您将需要一种组合杂质值的方法。通常,这是通过对给定特征的所有拆分获取平均信息增益(或“纯度增益”)来完成的。如果您使用feature_importances_,这将为您完成。

编辑: 我发现问题比我想象的要深。 graphviz 只是树的图形表示。它详细显示了树和树的每个拆分。这是树的表示,而不是特征的表示。特征的信息量(或重要性)并不真正适合这种表示,因为它会在树的多个节点上累积信息。

变量classifierUsed2.feature_importances_ 包含每个特征的重要性信息。如果你得到例如 [0, 0.2, 0, 0.1, ...] 第一个特征的重要性为 0,第二个特征的重要性为 0.2,第三个特征的重要性为 0,第四个特征的重要性0.1,依此类推。

让我们按重要性对特征进行排序(首先是最重要的):

rank = np.argsort(classifierUsed2.feature_importances_)[::-1]

现在排名包含特征的索引,从最重要的一个开始:[1, 3, 0, 1, ...]

想看看五个最重要的功能吗?

print(rank[:5])

这会打印索引。什么索引对应什么特征?这是你应该知道的事情,因为你应该构建了特征矩阵。很有可能,这是可行的:

print(dv.get_feature_names()[rank[:5]])

或者这样:

print('\n'.join(dv.get_feature_names()[i] for i in rank[:5]))

【讨论】:

我添加了 (print tree.feature_importances_) 但它说 'module' 对象没有属性 'feature_importances_' 对不起,我看错了你的代码。我认为tree 是分类器对象。所以在你的情况下classifierUsed2.feature_importances_ 应该可以工作。 我试过了,但它只是添加了这样的列表 [ 0. 0. 0. ..., 0. 0. 0.] 或 [ 0.00924365 0. 0. ..., 0. 0 . 0. ] 这些有什么问题?值为 0 表示此功能没有用(可能在树中根本没有使用)。 我应该用这个“tree.export_graphviz(classifierUsed2.feature_importances_, feature_names=dv.get_feature_names)”替换这个“tree.export_graphviz(classifierUsed2, feature_names=dv.get_feature_names(), out_file=treeFileName)” (), out_file=treeFileName)"?

以上是关于如何解释决策树的图形结果并找到信息最多的特征?的主要内容,如果未能解决你的问题,请参考以下文章

用于决策树的 one-hot 编码后如何解释特征重要性

1-2 决策树节点划分时的特征选择依据

从决策树到随机森林

决策树方法的基本思想是啥

决策树算法原理

决策树的python实现