点击获取AI摘要

CatBoost内容补充

1. CatBoost (Categorical Boosting)

CatBoost (Categorical Boosting) 是俄罗斯搜索巨头 Yandex 开发的一个开源梯度提升框架。它在 GBDT 的基础上进行了优化,尤其擅长处理类别特征,并且在训练过程中引入了独特的机制来缓解预测偏移 (Prediction Shift) 问题,提高了模型的鲁棒性和泛化能力。

  • 核心思想: CatBoost 延续了梯度提升框架,迭代地构建决策树来优化目标函数。其最大的特点和创新在于其针对类别特征的处理方式以及有序提升 (Ordered Boosting) 算法。
  • 与 XGBoost / LightGBM 的主要区别和改进 (重点内容):
    1. 类别特征处理 (Categorical Feature Handling): 这是 CatBoost 的核心优势。它使用了一种被称为有序目标编码 (Ordered Target Encoding) 或 “Middles” 的方法,结合特征组合来有效地处理类别特征,避免了传统方法(如 One-Hot 或标准目标编码)可能带来的问题(维度爆炸、信息丢失、预测偏移)。
    2. 预测偏移问题与有序提升 (Prediction Shift & Ordered Boosting): 标准的 Boosting 算法在计算梯度时使用了基于整个数据集的模型,这可能导致训练和预测分布不一致(预测偏移)。CatBoost 引入了有序提升,在计算每个样本的梯度时,仅使用基于该样本之前的数据子集训练的模型,从而缓解了这个问题。
    3. 决策树结构 (Tree Structure): CatBoost 默认使用对称的决策树 (Symmetric Trees)。在构建树时,同一深度的节点都使用相同的特征和分裂阈值进行分裂。这使得树结构更加规则,预测速度快,并且有一定的正则化效果。
    4. 基于直方图的数值特征处理 (Histogram-based Numerical Feature Handling): 对于数值特征,CatBoost 也采用了类似于 LightGBM 的直方图算法,将连续值离散化,提高了分裂点查找的效率。
    5. 更少的参数调优 (Less Parameter Tuning): 相比 XGBoost 和 LightGBM,CatBoost 在许多数据集上使用默认参数就能获得不错的效果,减少了调参的复杂性(尽管依然有很多参数可供调整)。
    6. 支持 GPU 训练: 对 GPU 的支持良好,可以显著加速训练过程。

1.1 类别特征处理 (Categorical Feature Handling)

标准的处理类别特征的方法有 One-Hot Encoding 和 Target Encoding。

  • One-Hot Encoding (独热编码): 对于高基数(类别数量多)的类别特征,One-Hot Encoding 会产生大量的稀疏特征,增加模型复杂度和内存消耗。
  • Target Encoding (目标编码): 将类别特征的值替换为该类别对应目标变量的统计量(如均值)。例如,对于分类问题,可以将类别替换为该类别下样本属于正类的比例 E[ycategory]E[y | \text{category}]. 这种方法虽然有效,但在标准的 Boosting 框架下,容易导致信息泄露 (Data Leakage)预测偏移 (Prediction Shift):在训练时,计算目标编码使用了整个数据集的信息,包括当前样本的目标值,这使得模型在训练集上表现很好,但在未见过的数据(测试集)上性能下降。

CatBoost 针对这些问题提出了解决方案:

  1. 有序目标编码 (Ordered Target Encoding) / “Middles”:

    • 为了避免信息泄露,CatBoost 在计算类别特征的目标编码时,采用了一种基于随机排列的方法。

    • 对于训练集的一个随机排列,当计算样本 ii 的某个类别特征的目标编码时,只使用在该排列中位于样本 ii 之前的样本来计算统计量。

    • 具体公式通常为:

      EncodedValuei=j=1i1[categoryj=categoryi]targetj+priorweightj=1i1[categoryj=categoryi]weight+prior\text{EncodedValue}_i = \frac{\sum_{j=1}^{i-1} [\text{category}_j = \text{category}_i] \cdot \text{target}_j + \text{prior} \cdot \text{weight}}{\sum_{j=1}^{i-1} [\text{category}_j = \text{category}_i] \cdot \text{weight} + \text{prior}}

      其中,[][\cdot] 是指示函数,prior\text{prior} 是一个先验值(如整个数据集的目标均值),weight\text{weight} 是先验的权重。使用先验可以减少低频类别带来的噪声。

    • CatBoost 可以使用多个随机排列来计算不同的编码,增加鲁棒性。

    • 优点: 有效地处理了类别特征,避免了信息泄露和预测偏移,无需手动进行 One-Hot 或目标编码。

    • 缺点: 需要对数据进行排序和多次统计计算,增加了训练时间。

  2. 特征组合 (Feature Combinations):

    • CatBoost 可以在训练过程中自动地将某些类别特征进行组合,生成新的组合特征(例如,将 Country=USACity=NewYork 组合成 Country=USA_City=NewYork)。
    • 这些组合特征也使用有序目标编码进行处理。
    • 优点: 可以发现特征之间的交互作用,提高模型的表达能力。

1.2 预测偏移与有序提升 (Prediction Shift & Ordered Boosting)

  • 预测偏移问题: 在标准的梯度提升算法中,训练第 tt 棵树时计算的梯度是基于前 t1t-1 棵树的模型对整个训练集的预测误差。这个模型是使用整个训练集的信息构建的。这意味着,当前用来计算梯度的模型,包含了未来将被用来训练第 tt 棵树的数据的信息。这导致训练过程中使用的预测分布与最终模型在全新数据上的预测分布之间存在差异,即预测偏移。这个问题在使用基于目标统计量的特征(如目标编码)时尤其突出。
  • 有序提升 (Ordered Boosting):
    • CatBoost 提出有序提升来解决预测偏移问题。
    • 在训练第 tt 棵树时,它使用两个不同的模型:一个用于计算梯度和 Hessian(基于随机子集训练),一个用于构建当前的树。
    • 更直观地理解:对于一个随机排列的训练集,当训练用于预测样本 ii 的模型时,只使用该排列中位于样本 ii 之前的样本来构建这棵树。然后用这棵树在样本 ii 上计算梯度。
    • 实际上,为了效率,CatBoost 通常会使用多组随机排列,并对每个排列独立地训练一个模型来计算梯度。
    • 优点: 显著减轻了预测偏移问题,提高了模型的泛化能力和鲁棒性。
    • 缺点: 相比标准提升(Plain Boosting),计算成本更高,训练时间可能更长。

1.3 对称树结构 (Symmetric Tree Structure)

  • 策略: CatBoost 默认构建对称树。在每一层,它找到一个最佳的分裂 (特征 + 阈值),然后将该分裂应用到该层的所有叶子节点上。
  • 优点:
    • 预测速度快: 由于结构规则,可以高效地进行矢量化计算。
    • 防止过拟合: 对称结构限制了树的灵活性,起到一定的正则化作用。
  • 缺点:
    • 可能不如非对称树(如 Leaf-wise)灵活,在某些问题上可能无法达到理论上的最优解。
    • 可以通过 grow_policy 参数切换到非对称结构(Lossguide)。

1.4 LightGBM 的目标函数与优化

CatBoost 基于 GBDT 框架,目标函数与 XGBoost 类似,也是最小化损失函数加上正则化项。虽然它也使用了二阶泰勒展开来近似损失函数,但在有序提升框架下,计算梯度 gig_i 和 Hessian hih_i 的模型是不同的。

假设要优化的简化目标函数(类似 XGBoost):

Obj(t)i=1n[giht(xi)+12hiht(xi)2]+Ω(ht)\text{Obj}^{(t)} \approx \sum_{i=1}^n \left[ g_i h_t(x_i) + \frac{1}{2} h_i h_t(x_i)^2 \right] + \Omega(h_t)

在有序提升中,计算 gig_ihih_i 时,y^i(t1)\hat{y}_i^{(t-1)} 是由一个只训练到样本 ii 之前的数据的模型产生的预测。

1.5 CatBoost 参数解释 (部分关键参数)

CatBoost 也有很多参数,许多与 XGBoost 和 LightGBM 类似,但处理类别特征和有序提升相关的参数是其特色。

参数/属性 描述 默认值 类型/选项 重要性级别 与XGBoost/LightGBM对比
loss_function / objective 定义学习任务及损失函数。类似 XGBoost/LightGBM。支持多种损失函数。 'RMSE' (回归), 'Logloss' (二分类) string 类似
eval_metric 评估指标。类似 XGBoost/LightGBM 的 eval_metric/metric 根据 loss_function string or list of strings 高 (用于评估) 类似
iterations / n_estimators Boosting 迭代次数,即树的数量。 100 int 类似
learning_rate 学习率 (Learning Rate)。 缩放每棵树的贡献。 0.03 float 默认值通常较低
depth 树的深度。 对于默认的对称树结构,这是严格的最大深度。 6 int 类似 XGBoost 的 max_depth,但针对对称树结构
l2_leaf_reg L2 正则化系数。 叶子节点权重的 L2 正则化。与 XGBoost 的 reg_lambda 类似。 3 float 类似
model_shrink_rate [仅用于 Ordered Boosting] 模型收缩率。 影响 Leaf Estimation 计算过程。 0 float CatBoost 独有 (Ordered Boosting)
random_seed 随机种子。用于数据采样、排列等随机过程,确保结果可复现。 0 int 实用 类似
cat_features 指定哪些特征是类别特征。 可以是特征索引列表或特征名称列表。非常重要! None list of int or list of str 高 (处理类别特征时) CatBoost 核心参数
verbose 控制训练过程输出信息的详细程度。可以指定整数(如 0, 100 表示每 100 轮打印一次)或布尔值。 True bool or int 实用 类似
early_stopping_rounds [fit 方法参数] 早期停止轮数。fit 方法中指定。如果在验证集上经过 early_stopping_rounds 轮迭代后,评估指标没有提升,训练就会停止。需要同时提供验证集和 eval_metric非常重要! N/A int 高 (用于早期停止) 类似
border_count [数值特征参数] 用于构建数值特征直方图的桶的数量。 值越大,分裂点选择越精确,但训练越慢。 254 int 实用 类似 LightGBM
grow_policy 树的生长策略。 'SymmetricTrees' (默认,对称生长),'Depthwise' (按层生长),'Lossguide' (按损失最佳优先生长,类似 LightGBM 的 Leaf-wise)。 'SymmetricTrees' 'SymmetricTrees', 'Depthwise', 'Lossguide' 控制树结构,与 XGBoost/LightGBM 策略对应
min_data_in_leaf 叶子节点中所需的最小样本数。 与 LightGBM 的 min_child_samples 类似。 1 int 类似 LightGBM 的 min_child_samples
boosting_type Boosting 类型。 'Ordered' (有序提升,默认), 'Plain' (标准提升)。使用 Ordered 可以缓解预测偏移,但训练较慢。 'Ordered' 'Ordered', 'Plain' CatBoost 核心参数
allow_writing_files 是否允许 CatBoost 在训练期间创建临时文件(用于存储中间计算结果,如有序统计量)。禁用可以避免生成文件,但在处理大规模数据时可能需要更多内存。 True bool 实用 CatBoost 相关
feature_importances_ [属性] 特征重要性。 拟合后可用。CatBoost 支持多种计算方式。 N/A array N/A 类似

1.6 Scikit-learn API 示例 (CatBoost)

CatBoost 也提供了与 scikit-learn 兼容的 API (CatBoostClassifierCatBoostRegressor)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# 导入 CatBoost 的 Scikit-learn API
from catboost import CatBoostClassifier, Pool
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
from sklearn.datasets import load_iris # 使用一个简单数据集
import pandas as pd # 方便处理数据和指定类别特征

# 加载数据集
iris = load_iris()
X, y = iris.data, iris.target
feature_names = iris.feature_names
target_names = iris.target_names

# 转换为 Pandas DataFrame,并添加一个模拟的类别特征
X_df = pd.DataFrame(X, columns=feature_names)
# 假设第一个特征(sepal length)根据某个阈值(例如 5.5)分为两类
X_df['sepal length category'] = X_df['sepal length (cm)'].apply(lambda x: 'long' if x > 5.5 else 'short')
# 确保类别特征的 dtype 是 'category' 或 'object'
X_df['sepal length category'] = X_df['sepal length category'].astype('category')

y_series = pd.Series(y)

# 分割数据集
X_train, X_test, y_train, y_test = train_test_split(X_df, y_series, test_size=0.3, random_state=42, stratify=y_series)

print("\n--- CatBoost Classifier 示例 ---")

# 初始化 CatBoost 分类器
# loss_function='MultiClass' 用于多分类
# eval_metric='MultiClass' 或 'MultiLogloss'
# cat_features 指定类别特征列的索引或名称
# CatBoost 默认使用有序提升和对称树
catb_clf = CatBoostClassifier(iterations=500, # 迭代次数,配合 early stopping
learning_rate=0.1,
depth=6, # 树的深度
l2_leaf_reg=3, # L2 正则化
loss_function='MultiClass', # 损失函数
eval_metric='MultiClass', # 评估指标
random_seed=42,
verbose=100, # 每100轮打印一次信息
# cat_features=[4] # 如果指定列索引,这里是新加的类别列索引
cat_features=['sepal length category'], # 指定列名称更直观
early_stopping_rounds=10, # 早期停止轮数
# boosting_type='Ordered' # 默认就是Ordered,也可以显式指定
# grow_policy='SymmetricTrees' # 默认就是SymmetricTrees
# allow_writing_files=False # 如果不希望生成文件,可以设为False
)

# CatBoost 的 fit 方法可以直接传入类别特征信息
# eval_set 参数用于指定验证集
catb_clf.fit(X_train, y_train,
eval_set=(X_test, y_test), # 验证集
# cat_features 指定类别特征列的索引或名称 (也可以在这里指定)
# cat_features=['sepal length category']
)

# 预测
y_pred_catb = catb_clf.predict(X_test)
# CatBoost predict 默认返回原始预测结果(类别索引或回归值),对于分类问题通常需要 predict_proba 获取概率
# y_pred_proba_catb = catb_clf.predict_proba(X_test)

# 如果是多分类且 loss_function 为 MultiClass,predict 返回的是类别索引
# 如果是二分类且 loss_function 为 Logloss,predict 返回的是原始预测值,需要 sigmoid 转换为概率或使用 predict_proba
accuracy_catb = accuracy_score(y_test, y_pred_catb)
print(f"\n准确率: {accuracy_catb:.4f}")
# print("分类报告:\n", classification_report(y_test, y_pred_catb, target_names=target_names))

# 打印实际训练的树数量
print(f"实际训练的树数量: {catb_clf.get_best_iteration() + 1 if catb_clf.get_best_iteration() else catb_clf.get_params()['iterations']}")

# 打印特征重要性 (默认是基于分裂次数)
print("特征重要性 (CatBoost - Default):")
feature_names_with_cat = feature_names + ['sepal length category']
importances = catb_clf.get_feature_importance()
for name, importance in zip(feature_names_with_cat, importances):
print(f" {name}: {importance:.4f}")

# 也可以获取基于增益的特征重要性
# print("\n特征重要性 (CatBoost - Gain):")
# importances_gain = catb_clf.get_feature_importance(prettified=True, importance_type='Gain')
# print(importances_gain) # prettified=True 返回DataFrame

1.7 CatBoost 的优点和缺点

  • 优点:
    • 强大的类别特征处理能力: 内置的有序目标编码和特征组合,无需复杂的预处理。
    • 缓解预测偏移: 有序提升算法提高了模型的鲁棒性和泛化能力。
    • 较少的参数调优: 通常使用默认参数就能获得不错的效果。
    • 预测速度快: 默认的对称树结构有助于加速预测。
    • 支持 GPU: 可以利用 GPU 加速训练。
    • 鲁棒性: 对异常值和缺失值不敏感(部分程度上)。
  • 缺点:
    • 训练速度可能不如 LightGBM (特别是Plain模式下): 有序提升增加了计算复杂度。
    • 内存消耗相对较高: 特别是 Ordered 模式和处理大量类别特征时,需要存储中间统计信息。
    • 默认对称树的限制: 在某些问题上可能限制了模型的灵活性,不如 Leaf-wise 策略能更快地逼近最优解。
    • 模型大小: 模型文件可能较大。
    • 需要显式指定类别特征: 必须通过 cat_features 参数告知 CatBoost 哪些列是类别特征。

1.8 小结

CatBoost 是一个专注于类别特征处理缓解预测偏移的梯度提升框架。它通过独特的有序目标编码有序提升算法,解决了传统方法在处理类别特征时遇到的问题。其默认的对称树结构提供了快速预测和一定的正则化效果。尽管在训练速度上可能不如 LightGBM,但其在处理类别特征时的便利性和由此带来的模型鲁棒性,使其成为许多实际应用中的有力选择,尤其当数据包含大量类别特征时。相比 XGBoost 和 LightGBM,CatBoost 的默认参数往往更“开箱即用”。