为什么只有父节点的边缘在导出的决策树中标记

时间:2018-06-08 11:14:34

标签: scikit-learn graphviz decision-tree dot

我有一个训练有素的DecisionTreeClassifier实例,我实际上对底层决策树本身的谓词感兴趣。所以我需要一种干净的方法来遍历这棵树。

因为获得可遍历表示的唯一官方方法是使用scikit的export_graphviz函数导出到graphviz / dot文件。之后,我可以使用例如解析和分析树的图形表示。 networkx和pydot的组合。

但是...

我的特定点文件的内容如下:

digraph Tree {

node [shape=box] ;

0 [label="X[0] <= 15.0\ngini = 0.75\nsamples = 8\nvalue = [2, 2, 2, 2]"] ;

1 [label="X[1] <= 3.0\ngini = 0.5\nsamples = 4\nvalue = [2, 0, 2, 0]"] ;

0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ;

2 [label="gini = 0.0\nsamples = 2\nvalue = [0, 0, 2, 0]"] ;

1 -> 2 ;

3 [label="gini = 0.0\nsamples = 2\nvalue = [2, 0, 0, 0]"] ;

1 -> 3 ;

4 [label="X[1] <= 3.0\ngini = 0.5\nsamples = 4\nvalue = [0, 2, 0, 2]"] ;

0 -> 4 [labeldistance=2.5, labelangle=-45, headlabel="False"] ;

5 [label="gini = 0.0\nsamples = 2\nvalue = [0, 0, 0, 2]"] ;

4 -> 5 ;

6 [label="gini = 0.0\nsamples = 2\nvalue = [0, 2, 0, 0]"] ;

4 -> 6 ;

}

所以这看起来很精致,但是为什么只有连接到父节点的边缘用布尔值正确标记?这个图中的所有边都不应该附加一个适当的布尔标签/属性吗?

或者,如果有一些奇怪的graphviz / dot约定可以帮助我区分后续的兄弟边缘,那么规则是什么?

我从scikit的documentation on the decision tree classifier注意到,放大后的渲染graphviz决策树实际上也缺少布尔标签。至于我对决策树的洞察力,这就遗漏了关于树的重要信息。我在这里缺少任何惯例吗?例如。是左边缘总是隐含真的吗?我怎么能从点文件中说出它,因为它是垂直组织的?

1 个答案:

答案 0 :(得分:0)

在scikit-learn网站上意外地绊倒了一个例子之后,我意识到我不必解析导出的点文件来获取Python树结构来表示我构建的决策树。显然,我可以使用tree_实例的DecisionTreeClassifier属性,它是根据official API reference(一直到底部)的公开属性,并且它有一个关于如何使用的文档示例这个tree_对象here

然而,至少对我来说这很令人困惑 - 显然这个树对象是作为DecisionTreeClassifier API的一部分公开的,并且它有一个关于如何以特定方式使用它的文档示例,但是没有正式发布其基础类sklearn.tree._tree.Tree的文档。你只需要查看源代码。

关于点文件,我现在很确定它的唯一目的只是渲染决策树。在查看source code of export_graphviz之后我再次确认了这个结论,我注意到它确实是硬编码的,只传递连接到父节点的边标签。 export_graphviz正在使用tree_的{​​{1}}属性。从这个属性的使用方式来看,我认为你可以安全地推断出它总是在为任何节点写出'False'边缘之前首先写出'True'边缘。恕我直言,这保证了一个功能请求,允许在给定特定参数标志的情况下标记所有边缘。