提问者:小点点

如何获取scikit学习决策树所有节点的pos/neg实例计数?


我已经训练了一个skLearning决策树。

from sklearn.tree import DecisionTreeClassifier
c=DecisionTreeClassifier(class_weight="auto")
c.fit([[0,0],
       [0,1],
       [1,1],
      ],[0,1,0])

现在我想检查每个节点有多少阳性/阴性样本。因此,一个类似于

  counts: [2,1]            labels: (010)
                                 split by x0
    [1,1]       [1,0]         (01)        (0)
                           split by x1
 [1,0] [0,1]      0        (0)   (1)
   0     1

我如何从经过训练的决策树中得到这个(左计数)?

我可以看到一个c.tree\uu变量,但内容似乎不是很有用。有零、权重。。。而且很难猜到如何找回计数。


共1个答案

匿名用户

每个类的样本数存储在树中。值,但它只存储叶的节点值,因此我使用后序遍历来获取所有节点的值。

import numpy as np

def get_value(dt):
    left = dt.tree_.children_left
    right = dt.tree_.children_right
    value = dt.tree_.value
    leaves = np.argwhere(left == -1)[:, 0]

    def visit(node):
        if node in leaves:
            return
        visit(left[node])
        visit(right[node])
        value[node, :] = value[left[node], :] + value[right[node], :]

    visit(0)
    return value

例如

from sklearn.tree import DecisionTreeClassifier
dt = DecisionTreeClassifier()
dt.fit([[0,0],
        [0,1],
        [1,1]], [0,1,0])
get_value(dt)

输出:

[[[ 2.  1.]]

 [[ 1.  1.]]

 [[ 1.  0.]]

 [[ 0.  1.]]

 [[ 1.  0.]]]

更新#1

我想知道为什么tree_. value只存储叶节点的值,然后我发现了https://stackoverflow.com/questions/27417809/show-values-at-each-node-level-of-scikit-learn-decision-tree和这个问题。

事实证明,在0.17.dev0中,tree_. value已经返回了所有节点的值。

In [1]: from sklearn.tree import DecisionTreeClassifier

In [2]: dt = DecisionTreeClassifier()

In [3]: dt.fit([[0,0],
   ...:         [0,1],
   ...:         [1,1]], [0,1,0])
Out[3]:
DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
            max_features=None, max_leaf_nodes=None, min_samples_leaf=1,
            min_samples_split=2, min_weight_fraction_leaf=0.0,
            random_state=None, splitter='best')

In [4]: dt.tree_.value
Out[4]:
array([[[ 2.,  1.]],

       [[ 1.,  1.]],

       [[ 1.,  0.]],

       [[ 0.,  1.]],

       [[ 1.,  0.]]])

更新#2

虽然我认为在给出class_weight时"撤销加权"是没有意义的,但这是可以实现的。

class_权重由以下公式计算:

In [1]: from sklearn.utils import compute_class_weight

In [2]: compute_class_weight('auto', [0, 1], [0, 1, 0])
Out[2]: array([ 0.66666667,  1.33333333])

因此,您可以将value[node,:]/=class_weight添加到if-node in leaves:之后,以重新计算叶节点的值。