如何解释(意外)sklearn.tree.tree_tree.value属性的值?

时间:2019-01-10 17:52:53

标签: python scikit-learn decision-tree adaboost

与AdaBoostClassifier一起使用的决策树分类器存根相对应的value属性值与期望值不匹配,我无法确定这些值指示什么。我想了解这些值,以帮助分析存根估计器的行为以及存根对AdaBoostClassifier的贡献。与Stackoverflow类似的问题与我的数据无关。

版本信息

  • python:3.6.5
  • sklearn版本:0.20.2

DecisionTreeClassifier存根配置为:

number_estimators = 301
bdt= AdaBoostClassifier(DecisionTreeClassifier(max_depth=1), 
algorithm="SAMME.R", n_estimators=number_estimators)

AdaBoostClassifier是一个二进制分类器,其输出状态为Class A和Class B(编码为+1和-1)。训练集包含23个功能,分类器执行正常(预测准确性,精确度,召回率均为79%)。我正在分析错过的预测,以便对分类错误有所了解。

有782个训练样本。 301个存根估计量是通过以下方式从AdaBoostClassifier获得的:

tree_stubs = bdt.estimators_

与第六个估计量(基于0的列表)相对应的示例存根:

bdt.estimators_[5]
DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=1,
        max_features=None, max_leaf_nodes=None,
        min_impurity_decrease=0.0, min_impurity_split=None,
        min_samples_leaf=1, min_samples_split=2,
        min_weight_fraction_leaf=0.0, presort=False,
        random_state=421257592, splitter='best')

此存根的值:

stub_5.tree_.value
array([[[0.5       , 0.5       ]],
   [[0.29308331, 0.1861591 ]],
   [[0.20691669, 0.3138409 ]]])       

对于那些熟悉graphviz的人来说,树桩看起来像:

tree stub

根节点正确显示了样本数(782)。值属性指示[0.5,0.5]。我期望value属性是每个类中的样本数量而不是百分比。但是在根节点中,0.5的值确实反映了我拥有的均衡训练集,并且两个类的表示均相同。

现在解决问题。此存根中的拆分功能根据delta_win_pct值小于或等于-.001的阈值对样本进行拆分。我的数据集的确有385个样本记录,其中delta_win_pct小于此阈值,还有397个样本,其中delta_win_pct大于阈值。因此在树桩的左右叶子节点中样本数据是正确的。

但是值数据似乎不正确。在左子节点中,值报告为value = [0.293,0.186],而在右子节点中,值报告为[0.207,0.314]。请注意,这是sklearn.tree._tee.Tree类报告的数据,并不表示graphviz有任何问题。

这些价​​值量代表什么?

考虑到左叶节点,我的数据集实际上有264个A类样本,其delta_win_pct <= -0.001,和121个B类样本匹配此分割阈值。这些数字对应的百分比为[.6857,.3143]而不是[0.293,0.186]。错误的值不会线性缩放到期望值。

类似地,为右子节点提供的值数据为[0.207,0.314],但对于delta_win_pct超过阈值的397个样本的期望值应为[.330,.670]。

我注意到提供的值数据中的数字(0.293、0.186、0.207、0.314)加起来为1.0。但是,每个节点的值之和不等于1.0。我尝试使用提供的值作为所有样本的百分比,例如0.293 * 782 = 229,这与任何内容都不相关。

有人对提供的价值数据的含义有任何见识吗?我对这些值的解释和期望不正确吗?

最后,我注意到数据中值的相对大小与每个节点中的大多数样本正确相关。左子节点中的0.293大于0.186,指示左节点具有大多数A类样本。而在右叶节点中,当delta_win_pct>阈值时,0.207 <0.314表示大多数B类采样。我怀疑这就是AdaBoostClassifier似乎可以正常工作的原因。

无论如何,我想了解这些值。

2 个答案:

答案 0 :(得分:1)

我尝试在生成的数据集上重现它:

import pydot 
import numpy as np
from IPython.display import Image, display
from sklearn.externals.six import StringIO  
from sklearn.tree import DecisionTreeClassifier,  _tree
from sklearn.datasets import make_classification
from sklearn.ensemble import AdaBoostClassifier


X, y = make_classification(n_informative=2, n_features=3, n_samples=200, n_redundant=1, random_state=42, n_classes=2)
feature_names = ['X0','X1','X2','X3']
clf = AdaBoostClassifier(DecisionTreeClassifier(max_depth=1), 
algorithm="SAMME.R", n_estimators=301)
clf.fit(X, y)

estimator = clf.estimators_[0]
dot_data = StringIO() 
tree.export_graphviz(estimator, out_file=dot_data, proportion=False, filled=True,node_ids=True,rounded=True,class_names=['0','1']) 
graph = pydot.graph_from_dot_data(dot_data.getvalue()) [0]

def viewPydot(pdot):
    plt = Image(pdot.create_png())
    display(plt)
viewPydot(graph)

我发现有两种情况,一种是“ proper”(clf.estimators_[0]),看起来像这样 enter image description here

这里value代表节点中特定类相对于样本总数的比例,因此node#1:[84/200=0.42,7/200=0.035],node#2:[16/200=0.08,93/200=0.465]

如果将proportion参数设置为True,您将获得每个节点的类分布百分比,例如对于节点#2:[16/109, 93/109]=[0.147, 0.853]。它是calculated using weighted_n_node_samples属性,在适当情况下,该属性等于节点的样本数除以样本总数,例如109/200 = 0.545,[0.08, 0.465]/0.545=[0.147, 0.853]

您遇到的另一种情况(clf.estimators_[4]

enter image description here

左节点类:[74, 7]

Rignt节点类:[93, 26]

这里的类分布与value不相关,左节点甚至可以预测少数类。 唯一合适的情况似乎是第一个估计量,其他人有这个问题,也许这是提升程序的一部分?另外,如果您采用任何估算器树并对其进行手动拟合,您将获得与第一个估算器树相同的数字,例如

>>> DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=1,
            max_features=None, max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, presort=False,
            random_state=441365315, splitter='best').fit(X,y).tree_.value
array([[[100., 100.]],

       [[ 84.,   7.]],

       [[ 16.,  93.]]])

答案 1 :(得分:0)

当值数组不是平衡问题时,它以某种方式表示了预期的结果。当模型参数未设置为class_weight ='Balanced'时,则值给出该节点内A类和B类的比例;但是当模型参数设置为class_weight ='Balanced'时,这些值将提供意外的输出。