scikit learn中的节点重要性

数据挖掘 scikit-学习 特征重要性
2022-02-09 22:27:00

我试图准确了解 scikit-learn 的 RandomForestClassifier 中的 feature_importances 是如何工作的。我设法找到解释大部分过程的有用链接:https ://towardsdatascience.com/the-mathematics-of-decision-trees-random-forest-and-feature-importance-in-scikit-learn-and-spark -f2861df67e3

我只有两个关于 ni_j 方程的问题(节点重要性方程,特征重要性部分的第一个方程):

  1. 到达节点 j 的加权样本数是什么意思?他们是否通过树运行所有训练样本并计算有多少到达节点 j?如果是这样,为什么需要“加权”这个词?
  2. 我们能在数学上确定 ni_j >= 0 吗?

编辑:查看 forest.py 的代码,我看到了这个相当神秘的功能:

def feature_importances_(self):
        """Return the feature importances (the higher, the more important the
           feature).
        Returns
        -------
        feature_importances_ : array, shape = [n_features]
        """
        check_is_fitted(self, 'estimators_')

        all_importances = Parallel(n_jobs=self.n_jobs,
                                   backend="threading")(
            delayed(getattr)(tree, 'feature_importances_')
            for tree in self.estimators_)

        return sum(all_importances) / len(self.estimators_)

我可以看到它正在计算每棵树的特征重要性,然后对所有树取平均值。但是它是如何在不调用任何函数来计算样本或计算杂质的情况下计算树上的特征重要性的,我不明白。

2个回答

到达节点 j 的加权样本数

我们必须将 Parent 与两个孩子进行比较,然后必须对孩子的杂质进行加权。

假设 Parent 有100 个样本并且impurity=5 Children 具有与 [20, 2] 和 [80, 4]
相同的数据

Dip = 5 - (0.2 * 2 + 0.8 * 4)
=> 5 - 3.6
=> Dip = 1.4

加权”表示在此处应用适当的比率,即 0.2 和 0.8

问题 1: 决策树(因此随机森林)允许加权样本:您可以为训练数据中的每一行提供不同的正实值权重,而损失函数更关心权重较高的行。当您使用样品重量时,您需要调整所有计算,因此“样品数”变为“样品总重量”或“样品加权数”等。(注意,在问题公式中,杂质是也使用样本权重计算。)

问题 2:您在证明决策树中的基尼杂质单调递减?

编辑和评论: 跟进跟踪源代码的评论:当您进入实际的树构造时,您会进入 cython 并且事情变得更难追踪。但在这种情况下,只需测试一下就很容易了。使用没有权重的 iris 数据集n_node_samplesweighted_n_node_samples

clf = DecisionTreeClassifier(max_leaf_nodes=3, random_state=0)
clf.fit(X, y)
print(clf.tree_.n_node_samples)
# [150  50 100  54  46]
print(clf.tree_.weighted_n_node_samples)
# [150.  50. 100.  54.  46.]

并且使用权重(在这种情况下使用类权重,这相当于分别对每个类的行进行样本加权),节点会受到影响,具体取决于它们的类组合是什么样的:

wclf = DecisionTreeClassifier(max_leaf_nodes=3, random_state=0, class_weight={0: 1, 1: 2, 2: 1})
wclf.fit(X, y)
print(wclf.tree_.n_node_samples)
# [150  50 100  54  46]
print(wclf.tree_.weighted_n_node_samples)
# [200.  50. 150. 103.  47.]

(具体来说,在根节点处,所有 150 行,但属于 1 类的 50 行被计算为加权样本数的两倍。在节点 5 有 46 行,其中 1 行是 1 类,因此被计算在内双倍的。