【问题标题】:How to get pos/neg instance counts for all nodes of a scikit-learn decision tree?如何获取 scikit-learn 决策树的所有节点的 pos/neg 实例计数?
【发布时间】:2015-11-06 14:46:51
【问题描述】:

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

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_ 变量,但内容似乎不是很有帮助。有零、权重……很难猜测如何恢复计数。

【问题讨论】:

  • 只是每个节点的计数值。在i.imgur.com/9WC72.png 中创建类似饼图的东西
  • 我仍然对你想要的输出有点困惑。为什么counts 中的叶子标记为 1、0、1?样本的标签是[0, 1, 0]。为什么根节点是[2, 1] 而其子节点是[1, 1][0, 1]
  • 你是对的。我弄乱了号码。他们现在得到纠正。但是我该如何弥补class_weight

标签: python scikit-learn decision-tree


【解决方案1】:

每个类的样本数存储在tree_.value中,但是它只存储叶子的节点值,所以我使用后序遍历来获取所有节点的值。

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-treethis issue

原来在 scikit-learn 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_weight 的计算公式为

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])

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

【讨论】:

  • 目前看起来不错。如何撤消权重?如果我使用class_weight="auto",它会以某种方式更改数字。
  • 如果给定了class_weight,则对这些值进行加权。我认为“取消权重”是没有意义的。也许您可以通过根据叶节点所属的类重新加权叶节点来中和权重。
  • 在我的示例中,重新加权是什么?我相信在我的示例中,单位大小的叶子得到了 0.66 和 1.33。但我不确定它们与我的班级分布到底有什么关系。
  • 查看我的更新。我没有给出完整的例子,但希望你能理解。
  • 谢谢!我不知道utils.compute_class_weight
猜你喜欢
  • 2017-03-26
  • 2019-12-11
  • 2017-01-21
  • 2020-08-29
  • 2016-12-31
  • 2013-12-12
相关资源
最近更新 更多