【问题标题】:What does `sample_weight` do to the way a `DecisionTreeClassifier` works in sklearn?`sample_weight` 对 `DecisionTreeClassifier` 在 sklearn 中的工作方式有什么作用?
【发布时间】:2016-03-27 04:04:50
【问题描述】:

我从relevant documentation 读到:

可以通过从每个类别中抽取相同数量的样本来实现类别平衡,或者最好将每个类别的样本权重之和 (sample_weight) 归一化为相同的值。

但是,我仍然不清楚这是如何工作的。如果我将sample_weight 设置为只有两个可能值的数组,12,这是否意味着2 的样本的采样频率将是@ 的样本的两倍987654327@'s 什么时候做套袋?我想不出一个实际的例子。

【问题讨论】:

    标签: scikit-learn decision-tree


    【解决方案1】:

    一些快速的准备工作:

    假设我们有 K 个类别的分类问题。在由决策树节点表示的特征空间区域中,回想一下,该区域的“杂质”是通过使用该区域中类的概率来量化不均匀性来测量的。通常,我们估计:

    Pr(Class=k) = #(examples of class k in region) / #(total examples in region)
    

    杂质度量以类别概率数组作为输入:

    [Pr(Class=1), Pr(Class=2), ..., Pr(Class=K)]
    

    并吐出一个数字,它告诉您特征空间区域的“不纯”或按类别的不均匀程度。例如,两级问题的基尼系数是2*p*(1-p),其中p = Pr(Class=1)1-p=Pr(Class=2)


    现在,基本上你的问题的简短答案是:

    sample_weight 增加了概率数组中的概率估计 ...增加了杂质度量...增加了节点的分裂方式...增加了树的构建方式... . 这增加了特征空间如何被分割以进行分类。

    我相信最好通过例子来说明这一点。


    首先考虑以下输入为一维的 2 类问题:

    from sklearn.tree import DecisionTreeClassifier as DTC
    
    X = [[0],[1],[2]] # 3 simple training examples
    Y = [ 1,  2,  1 ] # class labels
    
    dtc = DTC(max_depth=1)
    

    因此,我们将查看只有一个根节点和两个子节点的树。请注意,默认的杂质度量是基尼度量。


    案例1:没有sample_weight

    dtc.fit(X,Y)
    print dtc.tree_.threshold
    # [0.5, -2, -2]
    print dtc.tree_.impurity
    # [0.44444444, 0, 0.5]
    

    threshold数组中的第一个值告诉我们第一个训练样例被发送到左子节点,第二个和第三个训练样例被发送到右子节点。 threshold 中的最后两个值是占位符,将被忽略。 impurity 数组分别告诉我们计算出的父节点、左节点和右节点中的杂质值。

    在父节点p = Pr(Class=1) = 2. / 3.,这样gini = 2*(2.0/3.0)*(1.0/3.0) = 0.444....。也可以确认子节点的杂质。


    案例2:sample_weight

    现在,让我们试试吧:

    dtc.fit(X,Y,sample_weight=[1,2,3])
    print dtc.tree_.threshold
    # [1.5, -2, -2]
    print dtc.tree_.impurity
    # [0.44444444, 0.44444444, 0.]
    

    你可以看到特征阈值是不同的。 sample_weight 也会影响每个节点的杂质测量。具体来说,在概率估计中,由于我们提供的样本权重,第一个训练样本被计算为相同,第二个被计算为两倍,第三个被计算为三倍。

    父节点区域的杂质是一样的。这只是一个巧合。我们可以直接计算:

    p = Pr(Class=1) = (1+3) / (1+2+3) = 2.0/3.0
    

    4/9 的基尼系数如下。

    现在,您可以从选择的阈值中看到,第一个和第二个训练示例被发送到左侧子节点,而第三个被发送到右侧。我们看到,在左子节点中,杂质也被计算为4/9,因为:

    p = Pr(Class=1) = 1 / (1+2) = 1/3.
    

    右孩子中的零杂质是由于该区域中只有一个训练样本。

    您可以类似地使用非整数样本权重扩展它。我建议尝试sample_weight = [1,2,2.5] 之类的方法,并确认计算出的杂质。

    【讨论】:

    • 对于gini measure,不应该是2/3 * (1 - 2/3) = 2/9吗?好的,所以我看到它会影响杂质测量,但这与仅基于相对 sample weights 更频繁或更不频繁地采样某个样本有何不同?感谢您的详细解释!
    • 二进制分类的基尼系数是2*p*(1-p),这就是为什么结果是4/9。你的解释是正确的。然而,“抽样”暗示了随机性,但并不存在(只是为了清楚)。当sample_weights 是整数时,就像在杂质测量中复制ith 训练示例samples_weights[i] 次一样。当然sample_weights不一定是整数,但思路是一样的。
    • 不知criterion = 'entropy'时是否有类似的程序
    • IIRC @Chris 杂质度量被抽象为一个可配置的可调用对象,并且该可调用对象在相关位中使用,因此它应该工作相同,独立于任何特定的标准选择。虽然,自从我潜入源头将其分开以来已经有一段时间了。不过,代码很漂亮,因此您可以阅读它来查看。
    • @MattHancock @Brick 这是一个很好的答案,但它有助于解释如何计算分类器的最佳样本权重,例如 sklearn.utils.class_weight.compute_sample_weight
    猜你喜欢
    • 2018-03-27
    • 1970-01-01
    • 2020-05-23
    • 2019-05-23
    • 2019-09-18
    • 1970-01-01
    • 2018-01-21
    • 2013-11-19
    • 1970-01-01
    相关资源
    最近更新 更多