所有文章 > AI驱动 > 优化XGBoost分类模型:网格搜索与K折交叉验证实现

优化XGBoost分类模型:网格搜索与K折交叉验证实现

背景

机器学习中,XGBoost是一种极为流行且高效的梯度提升算法,以其卓越的性能和灵活性在各类预测任务中得到了广泛应用,继上篇文章中关于XGBoost在回归预测任务中的调参技巧后——优化XGBoost回归模型:网格搜索与K折交叉验证实现,本篇文章将重点介绍如何在分类任务中对XGBoost进行优化,XGBoost的优势在于其处理大规模数据、提高模型准确性的同时能够防止过拟合,然而,要充分发挥XGBoost在分类任务中的潜力,选择合适的超参数至关重要为了寻找最佳的超参数组合,将借助网格搜索和K折交叉验证,网格搜索通过系统地遍历多个超参数组合来确定最佳配置,而K折交叉验证则通过将数据集分成K个子集以评估模型的泛化能力,结合这两种方法,可以有效地避免单次训练可能带来的过拟合风险,并为模型选择最佳的超参数,接下来,我们将通过具体的示例代码,详细演示如何运用网格搜索和K折交叉验证优化XGBoost分类模型的过程

代码实现

数据处理

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split

df = pd.read_csv('Dataset.csv')

# 划分特征和目标变量
X = df.drop(['target'], axis=1)
y = df['target']

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,
random_state=42, stratify=df['target'])

从 Dataset.csv 中读取数据,并将其分为训练集和测试集,为后续的模型训练和评估做好准备,通过分层采样(stratify 参数)保证训练集和测试集的类别分布一致,这对于模型的公平性和泛化能力至关重要,该数据集为二分类数据

定义XGBoost模型参数

import xgboost as xgb
from sklearn.model_selection import GridSearchCV

# XGBoost模型参数
params_xgb = {
'learning_rate': 0.02, # 学习率,控制每一步的步长,用于防止过拟合。典型值范围:0.01 - 0.1
'booster': 'gbtree', # 提升方法,这里使用梯度提升树(Gradient Boosting Tree)
'objective': 'binary:logistic', # 损失函数,这里使用逻辑回归,用于二分类任务
'max_leaves': 127, # 每棵树的叶子节点数量,控制模型复杂度。较大值可以提高模型复杂度但可能导致过拟合
'verbosity': 1, # 控制 XGBoost 输出信息的详细程度,0表示无输出,1表示输出进度信息
'seed': 42, # 随机种子,用于重现模型的结果
'nthread': -1, # 并行运算的线程数量,-1表示使用所有可用的CPU核心
'colsample_bytree': 0.6, # 每棵树随机选择的特征比例,用于增加模型的泛化能力
'subsample': 0.7, # 每次迭代时随机选择的样本比例,用于增加模型的泛化能力
'eval_metric': 'logloss' # 评价指标,这里使用对数损失(logloss)
}

设置一个初始的 XGBoost 模型参数字典 params_xgb,用于后续的模型训练和优化,这些参数是 XGBoost 在二分类任务中的常见选择,如果是多分类模型你将修改以下参数

params_xgb_multi = {
'learning_rate': 0.02,
'booster': 'gbtree',
'objective': 'multi:softprob', # 选择 'multi:softmax' 或 'multi:softprob'
'num_class': 3, # 类别总数
'max_leaves': 127,
'verbosity': 1,
'seed': 42,
'nthread': -1,
'colsample_bytree': 0.6,
'subsample': 0.7,
'eval_metric': 'mlogloss' # 多分类对数损失
}

objective: ‘multi:softmax’ 或 objective: ‘multi:softprob’,multi:softmax: 输出预测类别,multi:softprob: 输出每个类别的概率num_class:添加参数 num_class,它表示类别的总数例如,如果有三类,设置为 num_class: 3eval_metric:修改为 eval_metric: ‘mlogloss’ 或其他适合多分类的指标,如 merror,mlogloss: 多分类对数损失,merror: 多分类错误率

初始化分类模型

# 初始化XGBoost分类模型
model_xgb = xgb.XGBClassifier(**params_xgb)

使用定义的参数初始化XGBoost分类模型

定义参数网格

# 定义参数网格,用于网格搜索
param_grid = {
'n_estimators': [100, 200, 300, 400, 500], # 树的数量
'max_depth': [3, 4, 5, 6, 7], # 树的深度
'learning_rate': [0.01, 0.02, 0.05, 0.1], # 学习率
}

定义一个参数网格 param_grid,用于进行网格搜索,以便找到 XGBoost 模型的最佳超参数组合,网格搜索通过在给定的参数空间中系统地尝试每一种组合,选择出最优的参数设置,下面给出模型其它常见参数

param_grid = {
'n_estimators': [100, 200, 300], # 树的数量,较多的树可能提高模型性能,但也增加训练时间和风险过拟合
'max_depth': [3, 4, 5], # 树的最大深度,控制树的复杂度,较大值允许更复杂的模型但增加过拟合风险
'learning_rate': [0.01, 0.05, 0.1], # 学习率,控制每棵树对最终模型的贡献,较小值提供更稳健的学习
'min_child_weight': [1, 3, 5], # 最小叶子节点样本权重和,较大值防止过拟合,适用于高噪声数据集
'gamma': [0, 0.1, 0.2], # 节点分裂的最小损失减少,越大模型越保守,减少过拟合风险
'subsample': [0.7, 0.8, 0.9], # 随机选择样本的比例,用于构建每棵树,降低过拟合
'colsample_bytree': [0.7, 0.8, 0.9], # 随机选择特征的比例,用于构建每棵树,增强模型的泛化能力
'reg_alpha': [0, 0.1, 0.5], # L1正则化项的权重,增加稀疏性,降低过拟合
'reg_lambda': [1, 1.5, 2], # L2正则化项的权重,控制模型复杂度,增加泛化能力
'scale_pos_weight': [1, 2, 3] # 类别不平衡时调整正负样本权重比,值为正负样本比例 仅适用为二分类模型
}

这种网格搜索方法通过系统地尝试不同的参数组合,帮助 XGBoost 模型在各种条件下表现良好,并找到最适合数据的参数设置,在定义参数网格时,我们应注意选择最关键的参数,以避免模型运行时间过长的问题,接下来使用的还是第一种网格

使用GridSearchCV进行网格搜索和k折交叉验证

# 使用GridSearchCV进行网格搜索和k折交叉验证
grid_search = GridSearchCV(
estimator=model_xgb,
param_grid=param_grid,
scoring='neg_log_loss', # 评价指标为负对数损失
cv=5, # 5折交叉验证
n_jobs=-1, # 并行计算
verbose=1 # 输出详细进度信息
)

使用 GridSearchCV 结合 5 折交叉验证,在所有 CPU 核心上并行计算,通过负对数损失(neg_log_loss)作为评价指标,系统地搜索并评估 XGBoost 模型的最佳参数组合,同时输出详细的进度信息

训练模型并输出最优参数及得分

# 训练模型
grid_search.fit(X_train, y_train)

# 输出最优参数
print("Best parameters found: ", grid_search.best_params_)
print("Best Log Loss score: ", -grid_search.best_score_)

网格搜索通过系统地评估参数组合,发现最优参数组合为:learning_rate: 0.02(学习率)max_depth: 3(树的最大深度)n_estimators: 200(树的数量)这些参数组合在当前给定的参数网格和交叉验证配置下提供了最佳的模型性能

训练最优参数下的模型

# 使用最优参数训练模型
best_model = grid_search.best_estimator_

使用找到的最优参数重新训练模型,得到最终的最佳模型

模型评价指标输出

from sklearn.metrics import classification_report

# 预测测试集
y_pred = best_model.predict(X_test)

# 输出模型报告, 查看评价指标
print(classification_report(y_test, y_pred))

混淆矩阵热力图绘制

from sklearn.metrics import confusion_matrix
import seaborn as sns
# 输出混淆矩阵
conf_matrix = confusion_matrix(y_test, y_pred)

# 绘制热力图
plt.figure(figsize=(10, 7), dpi=1200)
sns.heatmap(conf_matrix, annot=True, annot_kws={'size':15},
fmt='d', cmap='YlGnBu', cbar_kws={'shrink': 0.75})
plt.xlabel('Predicted Label', fontsize=12)
plt.ylabel('True Label', fontsize=12)
plt.title('Confusion matrix heat map', fontsize=15)
plt.show()

本文章转载微信公众号@Python机器学习AI