如何获取 scikit-learn 决策树所有节点的 pos/neg 实例计数?
How to get pos/neg instance counts for all nodes of a scikit-learn decision tree?
我训练了一个 sklearn 决策树。
from sklearn.tree import DecisionTreeClassifier
c=DecisionTreeClassifier(class_weight="auto")
c.fit([[0,0],
[0,1],
[1,1],
],[0,1,0])
现在我想检查每个节点有多少 positive/negative 个样本。因此像
这样的图
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_
变量,但内容似乎不是很有帮助。有零,权重,......很难猜出如何取回计数。
每个 class 的样本数存储在 tree_.value
中,但是它只存储叶子的节点值,所以我使用 post-顺序遍历来获取所有节点的值.
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
只存储叶节点的值,然后我找到了 and this issue。
事实证明,在 scikit-learn 0.17.dev0 中,tree_.value
已经 returns 所有节点的值。
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
时 对 "undo the weighting" 没有 有意义,但有可能实现。
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
重新计算叶子节点的值
我训练了一个 sklearn 决策树。
from sklearn.tree import DecisionTreeClassifier
c=DecisionTreeClassifier(class_weight="auto")
c.fit([[0,0],
[0,1],
[1,1],
],[0,1,0])
现在我想检查每个节点有多少 positive/negative 个样本。因此像
这样的图 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_
变量,但内容似乎不是很有帮助。有零,权重,......很难猜出如何取回计数。
每个 class 的样本数存储在 tree_.value
中,但是它只存储叶子的节点值,所以我使用 post-顺序遍历来获取所有节点的值.
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
只存储叶节点的值,然后我找到了 and this issue。
事实证明,在 scikit-learn 0.17.dev0 中,tree_.value
已经 returns 所有节点的值。
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
时 对 "undo the weighting" 没有 有意义,但有可能实现。
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
重新计算叶子节点的值