不平衡分类的成本敏感型决策树

决策树算法对于平衡分类是有效的,尽管它在不平衡数据集上的表现不佳。

树的分割点被选择以最佳地将样本分成两组,且混合程度最低。当两组都由一个类别的样本主导时,用于选择分割点的标准会显示出良好的分离,而实际上,少数类别的样本被忽略了。

这个问题可以通过修改用于评估分割点的标准来解决,使其考虑到每个类别的重要性,这通常被称为加权分割点或加权决策树。

在本教程中,您将学习用于不平衡分类的加权决策树。

完成本教程后,您将了解:

  • 标准决策树算法如何不支持不平衡分类。
  • 决策树算法如何通过在选择分割时按类别权重加权模型错误来进行修改。
  • 如何为决策树算法配置类别权重,以及如何网格搜索不同的类别权重配置。

通过我的新书《使用Python进行不平衡分类启动您的项目,其中包括逐步教程和所有示例的Python源代码文件。

让我们开始吧。

How to Implement Weighted Decision Trees for Imbalanced Classification

如何实现不平衡分类的加权决策树
图片由Bonnie Moreland提供,保留部分权利。

教程概述

本教程分为四个部分;它们是

  1. 不平衡分类数据集
  2. 不平衡分类的决策树
  3. 使用Scikit-Learn的加权决策树
  4. 网格搜索加权决策树

不平衡分类数据集

在我们深入探讨不平衡分类的决策修改之前,让我们首先定义一个不平衡分类数据集。

我们可以使用make_classification()函数来定义一个合成的不平衡两类分类数据集。我们将生成10,000个样本,其中少数类与多数类的比例约为1:100。

生成后,我们可以总结类别分布,以确认数据集的创建符合预期。

最后,我们可以创建一个样本的散点图,并根据类别标签对其进行着色,以帮助理解对该数据集中的样本进行分类的挑战。

综合起来,生成合成数据集并绘制样本的完整示例如下所示。

运行示例首先创建数据集并总结类别分布。

我们可以看到数据集的类别分布约为1:100,多数类有不到10,000个样本,少数类有100个样本。

接下来,创建数据集的散点图,显示多数类(蓝色)的大量样本和少数类(橙色)的少量样本,并存在一些适度的类别重叠。

Scatter Plot of Binary Classification Dataset With 1 to 100 Class Imbalance

具有1比100类别不平衡的二元分类数据集散点图

接下来,我们可以在数据集上拟合一个标准决策树模型。

决策树可以使用 scikit-learn 库中的 DecisionTreeClassifier 类来定义。

我们将使用重复交叉验证来评估模型,进行三次重复的10折交叉验证。模型性能将使用平均ROC曲线下面积(ROC AUC)报告,该平均值在所有重复和所有折叠中进行。

综合起来,下面列出了在不平衡分类问题上定义和评估标准决策树模型的完整示例。

决策树是二元分类任务的有效模型,但默认情况下,它们在不平衡分类方面效果不佳。

运行示例会评估不平衡数据集上的标准决策树模型,并报告平均ROC AUC。

注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请尝试运行示例几次并比较平均结果。

我们可以看到模型具有一定的技能,ROC AUC高于0.5,在这种情况下达到了0.746的平均分数。

这为对标准决策树算法进行的任何修改提供了比较基线。

想要开始学习不平衡分类吗?

立即参加我为期7天的免费电子邮件速成课程(附示例代码)。

点击注册,同时获得该课程的免费PDF电子书版本。

不平衡分类的决策树

决策树算法也被称为分类和回归树(CART),它涉及构建一棵树来对训练数据集中的样本进行分类。

可以认为这棵树将训练数据集进行划分,样本沿着树的决策点向下移动,最终到达树的叶子节点并被分配一个类别标签。

这棵树是通过使用数据集中变量的值来分割训练数据集而构建的。在每个点上,以贪婪的方式选择数据中的分割,该分割会产生最纯净(混合最少)的样本组。

这里,纯度意味着将样本清晰地分离成组,其中由所有0或所有1类别组成的样本组是最纯净的,而50-50混合的两个类别是最不纯净的。纯度最常使用基尼不纯度(Gini impurity)计算,但也可以使用计算。

纯度度量的计算涉及计算给定类别的样本被分割错误分类的概率。计算这些概率涉及对每个组中每个类别中的样本数量进行求和。

可以更新分割准则,使其不仅考虑分割的纯度,而且还根据每个类别的重要性进行加权。

我们对成本敏感型树归纳的直觉是,根据错误分类实例所属类别的成本,按比例修改实例的权重……

——一种用于生成成本敏感型树的实例加权方法,2002年。

这可以通过将每个组中的样本计数替换为加权和来实现,其中系数用于对和进行加权。

更重要的类别被赋予更大的权重,而不那么重要的类别被赋予更小的权重。

  • 小权重:重要性较低,对节点纯度的影响较小。
  • 大权重:重要性较高,对节点纯度的影响较大。

可以将较小的权重分配给多数类,这样可以改善(降低)节点纯度得分,否则该节点可能看起来排序不佳。反过来,这可能允许将多数类中的更多样本分类为少数类,从而更好地适应少数类中的这些样本。

误分类成本较高的类别中的实例被赋予更高的权重。

——第71页,从不平衡数据集中学习,2018年。

因此,这种决策树算法的修改被称为加权决策树、类别加权决策树或成本敏感型决策树。

修改分割点计算是最常见的,尽管已经有很多研究针对决策树构建算法的其他一系列修改,以更好地适应类别不平衡。

使用 Scikit-Learn 的加权决策树

scikit-learn Python 机器学习库提供了一个支持类别加权的决策树算法实现。

DecisionTreeClassifier 类提供了 `class_weight` 参数,可以将其指定为模型超参数。`class_weight` 是一个字典,定义了每个类别标签(例如 0 和 1)以及在拟合模型时决策树中分割点组纯度计算中要应用的权重。

例如,类别 0 和 1 的 1 比 1 权重可以定义如下:

类别加权可以通过多种方式定义;例如:

  • 领域专业知识,通过与主题专家交谈确定。
  • 调优,通过超参数搜索(如网格搜索)确定。
  • 启发式方法,使用一般的最佳实践指定。

使用类别加权的最佳实践是使用训练数据集中类别分布的倒数。

例如,测试数据集的类别分布是少数类与多数类的比例为1:100。这个比例的倒数可以用作多数类的权重为1,少数类的权重为100。

例如:

我们也可以用分数定义相同的比例,并达到相同的结果。

例如:

通过将 `class_weight` 设置为 `'balanced'`,可以直接使用这种启发式方法。

例如:

我们可以使用上一节中定义的相同评估程序来评估具有类别加权的决策树算法。

我们期望类别加权版本的决策树比没有任何类别加权的标准版本表现更好。

完整的示例如下所示。

运行示例会准备合成的不平衡分类数据集,然后使用重复交叉验证评估类别加权版本的决策树算法。

注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请尝试运行示例几次并比较平均结果。

报告了平均 ROC AUC 分数,在本例中,它显示了比未加权版本的决策树算法更好的分数:0.759 对比 0.746。

网格搜索加权决策树

使用训练数据逆比例的类别权重只是一种启发式方法。

使用不同的类别权重可能会获得更好的性能,这也将取决于用于评估模型的性能指标的选择。

在本节中,我们将对加权决策树的一系列不同类别权重进行网格搜索,并找出哪个权重配置能产生最佳的 ROC AUC 分数。

我们将尝试以下类别 0 和 1 的权重:

  • 类别 0:100,类别 1:1。
  • 类别 0:10,类别 1:1。
  • 类别 0:1,类别 1:1。
  • 类别 0:1,类别 1:10。
  • 类别 0:1,类别 1:100。

这些可以定义为GridSearchCV类的网格搜索参数,如下所示:

我们可以使用重复交叉验证对这些参数执行网格搜索,并使用 ROC AUC 评估模型性能。

执行后,我们可以总结最佳配置以及所有结果,如下所示:

综合起来,下面的示例对不平衡数据集上的决策树算法的五种不同类别权重进行网格搜索。

我们可能会期望启发式类别加权是表现最好的配置。

运行示例会使用重复的k折交叉验证评估每个类别权重,并报告最佳配置和相关的平均ROC AUC分数。

注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请尝试运行示例几次并比较平均结果。

在这种情况下,我们可以看到1:100多数类与少数类加权取得了最佳的平均ROC分数。这与通用启发式方法的配置相符。

探索更极端的类别权重以查看它们对平均ROC AUC分数的影响可能会很有趣。

进一步阅读

如果您想深入了解,本节提供了更多关于该主题的资源。

论文

书籍

API

总结

在本教程中,您学习了不平衡分类的加权决策树。

具体来说,你学到了:

  • 标准决策树算法如何不支持不平衡分类。
  • 决策树算法如何通过在选择分割时按类别权重加权模型错误来进行修改。
  • 如何为决策树算法配置类别权重,以及如何网格搜索不同的类别权重配置。

你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。

掌控不平衡分类!

Imbalanced Classification with Python

在几分钟内开发不平衡学习模型

...只需几行python代码

在我的新电子书中探索如何实现
使用 Python 处理不平衡分类问题

它提供了关于以下内容的自学教程端到端项目
性能指标欠采样方法SMOTE阈值移动概率校准成本敏感算法
以及更多...

将不平衡分类方法引入您的机器学习项目

查看内容

不平衡分类的成本敏感型决策树的18条回复

  1. marco 2020年1月31日 上午1:19 #

    你好 Jason,
    我有一个一般性问题。
    我从去年五月开始学习M/L和D/L,我在想是否值得继续
    学习机器学习(即Scikit-Learn)还是最好学习深度学习(Keras)。
    或者最好两者都继续关注?
    两者各有什么优缺点(简而言之)?
    谢谢

    • Jason Brownlee 2020年1月31日 上午7:56 #

      两者兼顾。它们是解决不同问题的不同工具。

      大多数用于分类和回归的表格数据最好使用 sklearn 解决。大多数其他数据,如图像、文本等,最好使用神经网络解决。

  2. Peter Marelas 2020年1月31日 下午1:03 #

    我正在想,调整类别权重是否足以确定最佳参数。原因是您没有校准决策边界(阈值)。如果没有这个,我想知道结果是否具有决定性?

    • Jason Brownlee 2020年1月31日 下午2:06 #

      不,调整权重通常是建模流程中的一步,但在类别不平衡时可以提供很大的帮助。

  3. Varsha 2021年1月16日 下午4:35 #

    你好,
    如何为不平衡多类别数据集创建加权决策树?

    • Jason Brownlee 2021年1月17日 上午6:04 #

      完全一样的方式。

      指定数据集中类别的平衡。

  4. Meriem Ferdjouni 2021年5月22日 下午4:29 #

    你好,

    我认为如果我们在 cross_validation_score() 中将 'roc_auc' 作为评分参数传入,则需要在评分中进行一些更改。

    在 roc_auc_score() 中有一个名为 multi_class 的参数,其默认值为 'raise',如果将其用于多类问题,则会引发错误。如果遇到多类问题,我们需要将 'ovr' 或 'ovo' 传入 multi_class 参数。

    如果我错了,请纠正我,因为当我在多类数据上运行相同的评估代码行时,我遇到了一个错误“ValueError: multiclass format is not supported”。

  5. Meriem 2021年5月23日 上午5:11 #

    你好,

    我正在不平衡的多类数据上运行相同的标准模型,当我使用“cross_val_score”和参数“scoring”=‘roc_auc’评估它时,我遇到了一个错误。“ValueError: multiclass format is not supported”。

    有什么办法可以解决吗?

    请注意,我尝试了不同的方法,也尝试升级sklearn。

    谢谢!

  6. João 2021年5月26日 晚上9:12 #

    你好,

    我可能遗漏了什么,但是如何在DT根节点中分配误分类成本呢,因为在第一个节点中我仍然不知道哪些是FP和FN案例?我在实现自己的成本敏感DT的初始步骤中遇到了困难。

    谢谢!

    • Jason Brownlee 2021年5月27日 上午5:38 #

      您可以设置“class_weight”变量,并且该权重将用于每次分割的评估。

  7. Brian 2022年4月1日 上午10:42 #

    嗨,Jason,您能详细说明 class_weight 是如何修改熵方程的吗?sklearn 文档不清楚。一种可能性是关于所有类别的求和 wi*p(X=i)log(wi*p(X=i)),其中 wi 是每个类别的权重。谢谢。

  8. Brian 2022年4月4日 上午8:13 #

    我会看看这个——谢谢!

    • James Carmichael 2022年4月4日 上午8:55 #

      Brian,继续努力!

发表回复

Machine Learning Mastery 是 Guiding Tech Media 的一部分,Guiding Tech Media 是一家领先的数字媒体出版商,专注于帮助人们了解技术。访问我们的公司网站以了解更多关于我们的使命和团队的信息。