CatBoost 与 XGBoost

2025年6月17日 | 阅读13分钟

对于结构化数据问题的机器学习,有两种非常流行的梯度提升算法:CatBoost和XGBoost。它们在本质上是不同的,尽管它们的目标都是在提高准确性的同时获得相应的计算速度提升。

XGBoost 是一个用了好几年的机器学习主力军。它在内存处理方面的能力使其非常强大,再加上强大的并行处理能力和控制过拟合的L1和L2正则化。XGBoost非常灵活,它对变量的特征抽样、学习率和树的深度有很高的控制度。它本身不支持分类变量,因此需要进行一些修改,例如进行独热编码,这意味着对分类数据的预处理必须非常谨慎。

特点CatBoostXGBoost
处理分类数据使用有效的编码技术来原生处理分类特征。不需要进行独热编码等预处理。需要手动预处理来适应分类特征,例如标签编码或独热编码。
易用性易于使用,具有开箱即用的预设超参数,通常效果不错。为了获得最佳结果,需要进行严格的超参数调整。
在分类数据上的性能在较小的数据集和包含分类变量的数据集上表现出色。表现良好,但在处理分类特征时会遇到困难,需要预处理。
防止过拟合通过使用有序提升来减少过拟合,尤其是在较小的数据集上。使用L1和L2正则化方法来处理过拟合。
大型数据集上的速度由于复杂的提升技术,对于非常大的数据集来说速度会稍慢。大型数据集通常处理速度更快,尤其是在使用并行处理时。
超参数调整设置是可靠的,只需要很少的调整。为了获得最佳结果,需要更彻底的超参数调整。
并行处理支持多线程,但效果略逊于XGBoost。有效的并行处理,可以加快大型任务的速度。
可解释性提供用于可视化特征重要性的集成工具。提供SHAP值和特征重要性,但需要其他工具进行深入研究。
默认提升算法使用有序提升来防止过拟合。使用梯度提升(GBDT)的决策树。
库支持对R和Python提供强大的支持,并为各种操作系统提供现成的软件包。提供许多机器学习框架连接器,并在跨平台支持方面拥有广泛的支持。
内存效率经过优化,但在某些情况下,比XGBoost消耗更多内存。经过优化,但在某些情况下,比XGBoost消耗更多内存。

因此,我们将通过精度、速度和易用性来探讨两种最流行的梯度提升方法,以获得更全面的理解。梯度提升决策树(GBDT)是最有意义的机器学习模型之一。如果我们知道如何快速实现和优化梯度提升树,我们就可以处理各种问题并进行快速迭代。本内核将说明每种梯度提升方法的实现,通过贝叶斯优化执行超参数搜索,并最终以一个我们希望能够带来一些清晰度的比较结束。

梯度提升决策树(GBDT)

梯度提升决策树是分类和回归问题的标准,也是可能是最受欢迎的模型。GBDT源自AdaBoost,AdaBoost通过将弱学习器组合在一起并使用由每个学习器的准确性加权的多数投票来解决二元分类问题。在这种情况下,具有单次拆分的决策树(称为决策桩)是弱学习器。

梯度提升树成为一个统计框架,其中弱学习器的添加减少了模型的损失,而提升本质上是一个数值优化问题。随着提升树越来越受欢迎,如何将弱学习器添加到模型中、如何构建学习器以及使用哪种损失函数等问题也得到了扩展。由于有许多资源可以更详细地解释提升算法,我们将继续探索最受欢迎的两种梯度提升决策树:XGBoost和CatBoost。本内核的主要目的是实现这些技术,评估性能,并看看未来我们可能如何选择其中一种。

输出

CatBoost Vs XGBoost
CatBoost Vs XGBoost

数据探索

数据清理。数据集不需要太多清理,但有几件事很重要需要检查:缺失数据、跨特征的数据类型一致性、列中的异常值或不一致性,以及最后,观察特征之间的关系,因为它们以后可能会对特征工程有用。幸运的是,没有缺失数据,所以我们的重点将放在主要目标上:比较不同的梯度提升树算法。为了更好地理解数据,我们查看了哪些特征根据目标类别具有最分散的分布,检查了目标标签的不平衡性,观察了独立变量相对于目标标签的分布,并寻找与彼此之间具有强线性或单调关系的特征。这可以通过相关性热力图来更好地查看潜在的共线性特征。

输出

CatBoost Vs XGBoost

输出

CatBoost Vs XGBoost

输出

CatBoost Vs XGBoost

输出

CatBoost Vs XGBoost

我们数据中的第一个问题之一是目标标签的不对称性。“否”与“是”的客户流失率之比约为 6:1。虽然如果我们的类别分隔得更好,这会是个小问题,但在配对图中,不平衡的影响最为明显,其中“是”标记在散点图中几乎被淹没了。当我们开始测试我们的模型时,查看混淆矩阵并了解我们的模型在少数类别中的表现将是审慎的。如果我们难以对“是”类别进行分类,我们可以使用SMOTE等技术来对其进行过采样。或者,我想使用Tomek Links来对多数类别进行欠采样,并希望能为我们的散点图提供一个更清晰的边界。

我们在配对图中包含了来自箱线图的各种变量。在配对图中绘制这些变量中最有趣的变量是那些属性,因为它们在箱线图中显示了我们目标标签之间最大的分布差异。幸运的是,这些数据有很多特征,这对我们的决策树来说是好事,尽管从对角线分布来看,似乎没有任何特征在我们类别之间有非常不同的分布。最后,为了识别共线性关系,我们绘制了特征之间的相关性。这些通常是 GBDT 的一个问题,但如果我们有很多高度相关的特征,我们可以尝试进行特征工程或只保留一个。

超参数调优

Hyperopt 是一个用于超参数贝叶斯优化的 Python 库。与网格搜索和随机搜索等经典方法相比,它具有一些优势:首先,它具有更好的整体性能,并且找到最优超参数所需的时间更少;其次,它的 API 更灵活,因此更容易与各种机器学习模型集成,与 sklearn 的 gridsearch 相比,这可能使其在实践中更加普遍。

Hyperopt 将超参数调优视为一个优化问题。它使用目标函数 fit_model(parameters) 返回的损失来决定下一组要尝试的超参数。由于超参数搜索可能涉及大而高维的空间,因此 Hyperopt 中的贝叶斯优化比网格搜索和随机搜索有了显著改进,尤其是在广阔的搜索空间中。

Hyperopt 的组成部分

Hyperopt 由几个关键组件构建而成

  • 目标函数:此函数包含机器学习模型并接受超参数作为输入。目标函数至少必须返回损失,但更高级的设计返回具有额外字段的对象也很常见。
  • 特征空间:定义超参数范围和分布。Hyperopt 的 hp 对象提供了灵活构建这些空间的函数。
  • Trials 对象:虽然不是必需的,但 Trials 对象对于存储从实验中返回的所有值非常有用,这可以实现更好的跟踪和分析。
  • fmin 函数:这是执行目标最小化的主函数。它将目标、空间、trials 和最大评估次数 (max_evals) 作为输入。

凭借其灵活高效的设计,Hyperopt 简化了超参数调优,因此已成为任何机器学习工作流程的重要工具。

XGBoost

最流行的基于梯度的提升决策树方法之一称为 XGBoost。它于 2014 年首次发布,其出现对 Kaggle 和数据科学界产生了巨大影响。XGB 引入的梯度提升是通过拟合先前模型残差的新模型来完成的,同时使用梯度下降算法优化损失来累加所有这些模型。

XGBoost 参数有三种类型:学习任务参数、树提升参数和通用参数。我们将花费大部分时间在树提升参数上,因为通用参数和学习参数主要由我们建模的模型决定。让我们回顾一下 GBDT 算法的常见参数,以便更好地理解数据科学家可以用来适应模型中出现的问题的各种控制。

通用选项

  • silent (默认值=0):如果为 `True`,则抑制训练更新的显示。
  • nthread (默认值=可用最大值):用于并行处理的线程数。
  • Booster (默认值=gbtree):每次迭代使用的模型类型。可能的值为 `gbtree`(树模型)和 `gblinear`(线性模型)。

树提升参数

  • eta (默认值=0.3):也称为学习率。典型值范围在 0.01 到 0.3 之间。
  • lambda (默认值=1):L2 正则化参数,有助于控制模型复杂度。
  • alpha (默认值=0):用于特征选择和稀疏性的 L1 正则化参数。
  • scale_pos_weight (默认值=1):平衡正负类别的权重,用于处理不平衡数据集。
  • subsample (默认值=1):在构建树之前随机抽样的训练数据比例。例如,值为 0.5 表示抽样一半的数据,有助于防止过拟合。
  • colsample_bytree (默认值=1):每次树迭代中考虑用于随机抽样的特征比例。
  • colsample_bylevel (默认值=1):指定用于每个树级别的特征比例,而不是全局树。
  • min_child_weight (默认值=1):设置子节点所需的跨所有观测值的最小权重之和。有助于控制过拟合;值越高可能导致欠拟合。
  • max_depth (默认值=6):确定树的深度。更高的深度可以学习更具体的模式。典型值范围在 3 到 10 之间。
  • gamma (默认值=0):拆分叶节点所需的最小损失减少量。值越大,算法越保守。
  • max_delta_step (默认值=0):每次迭代中每个叶子输出允许的最大变化。很少使用,但有助于高度不平衡数据集上的逻辑回归。

输出

CatBoost Vs XGBoost

CatBoost

尽管Catboost将有序提升算法作为梯度提升算法的改进版本提出,但它以创新的方式处理分类数据。将分类数据编码为数值会带来许多困难,因为一个分类特征如果具有 n 个类别的类别列,则需要 n 个虚拟变量列,这些列将被划分为 n 列独热编码的特征,这可能会导致我们的特征集爆炸。一种称为目标均值编码的技术是将我们的类别值设置为该类别目标变量的平均值。Catboost 使用一种目标编码的变体,它使用可用历史记录来确定目标编码,然后对我们的分类数据进行编码和处理的随机排列。由于实时模型无法知道其目标的真实平均值,Catboost 使用它可用的内容而不是平均值。当然,由于我们拥有所有数据,我们可以在训练时计算平均值。这会导致目标泄露,使我们模型的训练精度高于其生产精度。

Catboost 的其他功能包括绘制特征交互和对象(行)重要性。

CatBoost 参数

CatBoost 参数有别名,因此检查不同来源的一致性很重要。这些参数分为八类,但对于优化,通常只强调其中一部分。

  • 输出参数 (9):控制输出文件和详细程度。
  • CTR 参数 (8):处理将分类特征转换为数值特征。
  • 通用参数 (32):用于训练和模型配置的常规设置。
  • 性能参数 (1):优化资源效率。
  • 处理单元参数 (2):设置硬件使用情况,如 CPU 或 GPU。
  • 过拟合检测参数 (4):控制检测和防止过拟合。
  • 二值化参数 (2):处理将数值特征拆分成 bin。
  • 多分类参数 (1):用于多分类任务的特定参数。

关键超参数

  • learning_rate (默认值=0.03):梯度下降中的步长。
  • border_count (默认值=CPU 为 254,GPU 为 128):数值特征的拆分次数。它接受 1 到 255 之间的整数值。
  • ctr_border_count:分类特征的拆分次数,限制在 1 到 255 之间的整数。
  • iterations (默认值=1000):训练期间要构建的最大树数。
  • l2_leaf_reg (默认值=3):叶子计算的 L2 正则化系数;允许正值。
  • bagging_temperature:配置贝叶斯自助抽样。如果设置为 1,则权重从指数分布中抽取;如果设置为 0,则权重均匀等于 1。
  • depth (默认值=6):树的深度,它控制准确性和训练时间。典型值范围在 1 到 10 之间,但任何高达 32 的整数都是允许的。
  • random_strength:调整评分拆分的随机性以防止过拟合。

输出

CatBoost Vs XGBoost

结果

输出

CatBoost Vs XGBoost

没有明确的赢家。似乎每种梯度提升算法在不同方面都表现得非常出色。XGBoost 凭借其出色的文档和多年的使用经验,仍然是一项出色的技术。我们有信心 XGB 没有过度拟合我们的训练集,因为它在训练集和测试集分数之间始终保持相对较小的差异,并显示出良好的准确性。我们特别有兴趣使用 CatBoost,因为它在处理分类数据方面具有所谓的进步。

CatBoost 的速度似乎比其他算法慢得多,并且在几项测试中停滞不前,但当我们从 50 减少 early_stopping_rounds 到 30 时,这种情况得到了缓解。我们希望进一步测试 CatBoost 和具有大量类别变量的数据,以便更好地了解它何时可能效果最佳。