`sample_weight` 对 `DecisionTreeClassifier` 在 sklearn 中的工作方式做了什么?

What does `sample_weight` do to the way a `DecisionTreeClassifier` works in sklearn?

我从 relevant documentation 中读到:

Class balancing can be done by sampling an equal number of samples from each class, or preferably by normalizing the sum of the sample weights (sample_weight) for each class to the same value.

但是,我仍然不清楚这是如何工作的。如果我将 sample_weight 设置为仅包含两个可能值的数组,即 12,这是否意味着将对具有 2 的样本进行采样进行装袋时,频率是 1 样本的两倍?我想不出一个实际的例子。

一些快速准备:

假设我们有 K classes 的 class化问题。在由决策树节点表示的特征 space 区域中,回想一下该区域的“不纯度”是通过使用该区域中 class 的概率量化不均匀性来衡量的。通常,我们估计:

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

杂质度量作为输入,class 概率数组:

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

并吐出一个数字,告诉您 inhomogeneous-by-class 特征区域 space 有多“不纯”。例如,两个 class 问题的基尼系数是 2*p*(1-p),其中 p = Pr(Class=1)1-p=Pr(Class=2).


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

sample_weight 增加了概率数组中的概率估计 ...这增加了杂质度量...这增加了节点的分裂方式...这增加了树是如何构建的...这增加了特征 space 是如何被分割成 classification.

我认为最好通过示例来说明这一点。


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

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)

因此,我们将查看只有一个根节点和两个 children 的树。请注意,默认的不纯度衡量基尼系数。


情况一:没有sample_weight

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

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

在parent节点中,p = Pr(Class=1) = 2. / 3.,所以gini = 2*(2.0/3.0)*(1.0/3.0) = 0.444....。您也可以确认 child 节点杂质。


案例 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 还会影响每个节点中的杂质度量。具体来说,在概率估计中,由于我们提供的样本权重,第一个训练示例被计算为相同,第二个被计算为两倍,第三个被计算为三倍。

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

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

4/9 的基尼系数如下。

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

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

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

您可以用 non-integer sample-wights 类似地扩展它。我建议尝试 sample_weight = [1,2,2.5] 之类的方法,并确认计算出的杂质。