【文章系列】

第一章 集成学习_LightGBM————集成学习之Boosting方法系列_LightGBM

第二章 集成学习_XGBoost————集成学习之Boosting方法系列_XGboost

第三章 集成学习_CatBoost————

【前言】

【算法简介】

【正文】

(一)CatBoost核心概念

1. 梯度提升树

CatBoost使用梯度提升树作为基本学习器,这是一种集成学习方法,通过逐步构建多个决策树来改进预测性能。每棵树都试图纠正前一棵树的错误。

2. 目标函数

CatBoost的目标函数是优化的核心,它是一个损失函数的组合,用于衡量模型的预测误差。在训练过程中,CatBoost通过最小化目标函数来不断优化模型的参数,使模型的预测更接近实际值。

3. 损失函数

损失函数是目标函数的一部分,它是用来度量模型对训练数据的拟合程度的函数。在分类问题中,常见的损失函数包括对数损失(Logarithmic Loss),均方误差(Mean Squared Error)用于回归问题。CatBoost允许用户自定义损失函数以满足特定任务需求。

4. 特征重要性

CatBoost可以估计每个特征的重要性,这有助于了解哪些特征对模型的预测起到关键作用。它可以通过不同的方式来计算特征重要性,如基于树的方法、基于Permutation Importance的方法等,帮助用户进行特征选择和解释模型。


(二)CatBoost与LightGBM、XGBoost的关联

1. 共同之处

(1)基于梯度提升树:CatBoost、LightGBM和XGBoost都使用梯度提升树作为基本学习器,通过构建多个决策树来改进预测性能。

(2)支持分类和回归:这三种算法都可以用于解决分类问题和回归问题,具有广泛的应用领域。

(3)可处理缺失值:它们都具有处理缺失值的能力,无需额外的数据预处理。

(4)提供特征重要性:CatBoost、LightGBM和XGBoost都能够估计特征的重要性,帮助用户进行特征选择和模型解释。

2. 优势

(1)CatBoost的优势

  • 自动处理分类特征:CatBoost可以自动处理分类特征,无需进行独热编码或标签编码,因此更加方便。
  • 防止过拟合:CatBoost使用对称树的正则化方法来防止过拟合。
  • 内置的数据处理:CatBoost内置了数据处理功能,可以处理缺失值。
  • 鲁棒性:CatBoost在处理噪声数据时表现出色,具有良好的鲁棒性。

(2)LightGBM的优势

  • 高效的训练速度:LightGBM以其基于直方图的分割方法,通常能够比其他算法更快地训练模型。
  • 内存效率:LightGBM具有较低的内存占用,适合处理大规模数据集。

(3)XGBoost的优势

  • 丰富的生态系统:XGBoost有一个强大的生态系统,有丰富的支持库和工具。
  • 可解释性:XGBoost提供了较好的模型可解释性,能够帮助用户理解模型的预测过程。

(三)CatBoost的工作原理

1. 基本数学模型

梯度提升是一种集成学习技术,它通过迭代地添加预测模型 (通常是决策树) 来最小化损失函数。每一步都尝试添加一个新的模型,以纠正前一步骤中的残差 (即真实值与当前模型预测值之间的差异) 。

在 CatBoost 中,模型的预测值 y ^ \hat{y} y^ 是通过累加所有决策树的贡献来计算的:

y ^ i = ∑ k = 1 K f k ( x i ) \hat{y}_i=\sum_{k=1}^Kf_k(x_i) y^i=k=1Kfk(xi)
其中, f k ( x i ) f_k(x_i) fk(xi) 是第 k k k 个决策树对第 i i i 个样本的预测贡献, K K K 是决策树的总数, x i x_i xi 是第
i i i 个样本的特征向量。
在每一步 k k k, CatBoost 会找到一个新的决策树 f k f_k fk, 以最大化损失函数的负梯度,这可
以视为解决以下优化问题:

f k = arg ⁡ min ⁡ f ∑ i = 1 N L ( y i , y ^ i ( k − 1 ) + f ( x i ) ) f_k=\arg\min_f\sum_{i=1}^NL(y_i,\hat{y}_i^{(k-1)}+f(x_i)) fk=argfmini=1NL(yi,y^i(k1)+f(xi))
其中, L L L 是损失函数, N N N 是训练样本的数量, y ^ i ( k − 1 ) \hat{y}_i^{(k-1)} y^i(k1) 是在加入 f k f_k fk 之前,使用前 k − 1 k-1 k1 个决策树对第 i i i 个样本的预测值。

2. 优化提高

CatBoost 采用了几个独特的技术来提高模型的性能和减少过拟合,包括:

(1)目标统计:这是处理分类特征的一种技术,旨在减少目标泄露和过拟合。

(2)有序提升:这是一种避免训练数据的时间顺序影响模型的技术,通过随机排列数据来提高泛化能力。

(3)边界感知梯度提升:这是一种特殊的梯度提升实现,用于优化特定于 CatBoost 的损失函数,以改进对稀疏数据和分类特征的处理。


(四)CatBoost实际操作

1. 前期准备
(1)数据格式

CatBoost 支持的几种主要数据格式:

  1. NumPy 数组:CatBoost 可以直接处理 NumPy 数组作为输入数据。这是最基本的数据格式,适用于已经预处理好的数值型数据。
  2. Pandas DataFrame:CatBoost 也可以直接处理 Pandas DataFrame。这对于包含数值型和类别型特征的数据集特别有用,因为 CatBoost 在内部对类别型特征进行优化处理,无需手动进行独热编码或其他预处理步骤。
  3. CatBoost Pool 类:对于更复杂的数据处理需求,CatBoost 提供了一个 Pool 类。Pool 类可以用来处理包含特征名称、权重和分组信息的数据集。如果您需要对数据进行高级处理(如指定特征的类型或处理缺失值),可以使用 Pool 类来实现。
  4. 文本特征:CatBoost 支持直接处理文本特征。您可以将文本列直接作为 DataFrame 的一部分传入模型,CatBoost 会自动进行文本特征的处理。
  5. 类别型特征:CatBoost 特别优化了对类别型特征的处理。您只需要在训练模型时通过 cat_features 参数指定 DataFrame 中哪些列是类别型特征,CatBoost 会自动处理这些特征,无需进行传统的预处理步骤(如独热编码)。
(2)参数设置
2. 实际演示
(1)获取数据

以UCI Raisin数据集为例

导入相关包

import numpy as np
import pandas as pd
from ucimlrepo import fetch_ucirepo  
from sklearn.model_selection import train_test_split
from catboost import CatBoostClassifier, Pool  # 导入CatBoost分类器
import matplotlib.pyplot as plt

获取UCI Raisin数据集

# fetch dataset 
raisin = fetch_ucirepo(id=850) 
  
# data (as pandas dataframes) 
train = raisin.data.features 
label = raisin.data.targets 
  
# metadata 
print(raisin.metadata) 
  
# variable information 
print(raisin.variables) 

查看输入属性与输出属性

train.info()

集成学习之Boosting方法系列_CatBoost-LMLPHP

label.info()

集成学习之Boosting方法系列_CatBoost-LMLPHP

对object数据类型,进行字典编码

def change_object_cols(se):
    value = se.unique().tolist()
    value.sort()
    return se.map(pd.Series(range(len(value)), index=value)).values
label['Class'] = change_object_cols(label['Class'])
label.info()

集成学习之Boosting方法系列_CatBoost-LMLPHP

全部转换为0、1编码

label['Class'].values

集成学习之Boosting方法系列_CatBoost-LMLPHP

(2)划分训练、测试数据集
x_train, x_test, y_train, y_test = train_test_split(train, label, test_size=0.3, random_state=0)

# 将标签向量转换为一维数组
y_train = y_train.values.ravel()
y_test = y_test.values.ravel()
(3)设定参数

与XGBoost的区别:

# 定义XGBoost的参数
params = {
    'objective': 'binary:logistic',  # 适用于二分类问题
    'max_depth': 8,                 # 决策树深度
    'learning_rate': 0.03,          # 学习率
    'eval_metric': 'logloss',       # 评估指标
    'num_leaves': 6,                # 树的叶子节点数
    'subsample': 0.8,               # 每次迭代时用于训练的子样本比例
    'colsample_bytree': 0.8,        # 每次迭代时用于训练的特征比例
    'early_stopping_rounds': 20     # 提前停止的轮数,如果验证误差不再下降
}
# 定义CatBoost的参数
params = {
    'loss_function': 'Logloss',        # 用于二分类问题的损失函数
    'depth': 8,                        # 决策树深度,与 XGBoost 的 'max_depth' 相似
    'learning_rate': 0.03,             # 学习率,与 XGBoost 相同
    # CatBoost 没有 'num_leaves' 参数,因为它自动管理叶子节点的数量
    'subsample': 0.8,                  # 每次迭代时用于训练的子样本比例,CatBoost 中称为 'bagging_temperature'
    'colsample_bylevel': 0.8,          # 每个级别的特征采样比例,与 XGBoost 的 'colsample_bytree' 近似
    # CatBoost 使用的是 'iterations' 和 'early_stopping_rounds' 参数,需要设置迭代次数
    'iterations': 1000,                # 最大迭代次数
    'early_stopping_rounds': 20        # 提前停止的轮数,如果验证误差不再下降
}

CatBoost 的 subsample 参数与 XGBoost 中的不完全相同。CatBoost 中,bagging_temperature 控制了子采样的强度,但它的工作原理与 XGBoost 的 subsample 略有不同。在 CatBoost 中,较大的 bagging_temperature 值会导致更强的子采样。如果需要子样本采样,需要对 bagging_temperature 参数进行调整以获得最佳效果。

此外,CatBoost 的 colsample_bylevel 与 XGBoost 的 colsample_bytree 在概念上是相似的,但 CatBoost 还提供了 colsample_bytreecolsample_bynode 选项,以提供不同级别的特征采样控制。

需要注意的是,CatBoost 中没有直接等价于 XGBoost 的 num_leaves 参数,因为 CatBoost 自动管理决策树的复杂度。

(4)开始训练

可以将数据集封装成CatBoost的Pool格式,有助于控制训练过程

train_pool = Pool(x_train, y_train)
test_pool = Pool(x_test, y_test)

# 初始化 CatBoost 分类器
catboost_model = CatBoostClassifier(**params)

# 训练模型
catboost_model.fit(train_pool, eval_set=test_pool, plot=True)

# 获取评估结果
eval_result = catboost_model.get_evals_result()

accuracy = catboost_model.score(x_test, y_test)

print("评估结果示例:", eval_result)
print(f"模型在测试集上的正确率为:{accuracy:.2f}")

集成学习之Boosting方法系列_CatBoost-LMLPHP

(5)可视化训练过程
  • 特征重要程度
# 获取特征重要性
feature_importances = catboost_model.get_feature_importance()

# 创建特征名称列表
importance_pairs = sorted(zip(feature_names, feature_importances), key=lambda x: x[1], reverse=True)

# 解压配对列表以分别获取排序后的特征名称和重要性值
sorted_features, sorted_importances = zip(*importance_pairs)

# 创建一个条形图
plt.figure(figsize=(10, 4))
plt.barh(range(len(sorted_importances)), sorted_importances, align='center')
plt.yticks(range(len(sorted_importances)), sorted_features)
plt.xlabel('importance')
plt.ylabel('features')
plt.title('CatBoost features importance')
plt.tight_layout()
plt.show()

集成学习之Boosting方法系列_CatBoost-LMLPHP

  • SHAP值解释

简单来讲:SHAP 值是一个实数值,可以是正数或负数。正值表示特征的该值增加了模型输出的概率(例如,在二分类问题中增加了类别为 1 的概率),而负值表示它降低了模型输出的概率。

import catboost
import shap

# 计算 SHAP 值
explainer = shap.TreeExplainer(catboost_model)
shap_values = explainer.shap_values(x_train)

# 绘制摘要图,展示最重要的特征对模型预测的影响
shap.summary_plot(shap_values, x_train)

集成学习之Boosting方法系列_CatBoost-LMLPHP

01-31 08:05