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

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

背景

机器学习数据科学领域,模型的性能优化是至关重要的一步,而XGBoost作为一种高效的梯度提升树算法,因其卓越的性能和灵活性,广泛应用于各种回归和分类问题中,然而,如何最大化利用XGBoost的潜力并实现最佳模型性能,离不开参数调优和交叉验证的加持,本文将详细介绍如何实现通过网格搜索和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_excel('数据.xlsx')

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

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

加载Excel文件中的数据,分离特征和目标变量,并将数据划分为训练集和测试集

定义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': 'reg:squarederror', # 损失函数,这里使用平方误差
'max_leaves': 127, # 每棵树的叶子节点数量,控制模型复杂度。较大值可以提高模型复杂度但可能导致过拟合
'verbosity': 1, # 控制 XGBoost 输出信息的详细程度,0表示无输出,1表示输出进度信息
'seed': 42, # 随机种子,用于重现模型的结果
'nthread': -1, # 并行运算的线程数量,-1表示使用所有可用的CPU核心
'colsample_bytree': 0.6, # 每棵树随机选择的特征比例,用于增加模型的泛化能力
'subsample': 0.7 # 每次迭代时随机选择的样本比例,用于增加模型的泛化能力
}

这里定义一组初始参数,控制模型的学习速率、提升方法、损失函数等,这些参数用来初始化XGBoost模型

初始化回归模型

model_xgb = xgb.XGBRegressor(**params_xgb)

使用定义的参数初始化XGBoost回归模型

定义参数网格

# 定义参数网格,用于网格搜索
param_grid = {
'n_estimators': [100, 200, 300, 400, 500], # 树的数量,控制模型的复杂度
'max_depth': [3, 4, 5, 6, 7], # 树的最大深度,控制模型的复杂度,防止过拟合
'min_child_weight': [1, 2, 3, 4, 5], # 节点最小权重,值越大,算法越保守,用于控制过拟合
}

定义需要进行网格搜索的参数范围,包括树的数量、最大深度和最小节点权重,这些参数用于调整模型的复杂度和防止过拟合,当然除了这些参数以外还存在很对参数,下面给出一些参考(这些参数并没有参与网格调参),网格参数范围多少当对运行速度成倍数增长

param_grid = {
'learning_rate': [0.01, 0.02, 0.05, 0.1], # 学习率,控制每一步的步长,防止过拟合
'gamma': [0, 0.1, 0.2, 0.3], # 节点分裂所需的最小损失减少量,值越大,算法越保守,用于控制过拟合
'subsample': [0.6, 0.7, 0.8, 0.9], # 每次迭代时随机选择的样本比例,防止过拟合
'colsample_bytree': [0.5, 0.6, 0.7, 0.8], # 每棵树随机选择的特征比例,防止过拟合
'reg_alpha': [0, 0.01, 0.1, 1], # L1正则化项的权重,值越大,模型越简单,用于防止过拟合
'reg_lambda': [0, 0.01, 0.1, 1], # L2正则化项的权重,值越大,模型越简单,用于防止过拟合
}

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

grid_search = GridSearchCV(
estimator=model_xgb,
param_grid=param_grid,
scoring='neg_root_mean_squared_error',
cv=5,
n_jobs=-1,
verbose=1
)

GridSearchCV用于进行网格搜索和交叉验证,scoring设为neg_root_mean_squared_error,即负均方根误差,作为评估指标,cv=5表示使用5折交叉验证,n_jobs=-1表示使用所有可用的CPU核心进行并行计算

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

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

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

5 folds: 表示使用5折交叉验证。数据集被分成5个子集,每次使用其中的4个子集进行训练,1个子集进行验证,这样进行5次,每个子集都作为一次验证集,125 candidates: 表示总共有125组不同的参数组合需要评估(5x5x5)也就是定义的网格参数存在的组合形式,totalling 625 fits: 因为每个参数组合都要经过5次交叉验证,所以总共进行625次模型训练和评估(5×125=625),最后模型找到的最佳参数组合为max_depth=7、min_child_weight=5、n_estimators=500,使用这些参数,模型在验证集上的平均RMSE分数为0.4666597060108463

训练最优参数下的模型

best_model = grid_search.best_estimator_

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

模型评价指标输出

from sklearn import metrics
# 预测
y_pred = best_model.predict(X_test)
y_pred_list = y_pred.tolist()
mse = metrics.mean_squared_error(y_test, y_pred_list)
rmse = np.sqrt(mse)
mae = metrics.mean_absolute_error(y_test, y_pred_list)
r2 = metrics.r2_score(y_test, y_pred_list)
print("均方误差 (MSE):", mse)
print("均方根误差 (RMSE):", rmse)
print("平均绝对误差 (MAE):", mae)
print("拟合优度 (R-squared):", r2)

这里对测试集输出该模型具体的评价指标

可视化

plt.figure(figsize=(10, 6), dpi=1200)
# 绘制 y_pred 和 y_test 的散点图
plt.scatter(y_test, y_pred, alpha=0.3, color='blue', label='Predicted vs Actual')
# 绘制一条 y = x 的对角线,用于参考
max_value = max(max(y_test), max(y_pred))
plt.plot([0, max_value], [0, max_value], color='red', linestyle='--', linewidth=2, label='Ideal Line (y = x)')
plt.title(f'Actual vs Predicted Values\nR-squared: {r2:.2f}')
plt.xlabel('Actual Values')
plt.ylabel('Predicted Values')
plt.legend()
plt.grid(True)
plt.show()

绘制实际值 (y_test) 和预测值 (y_pred) 之间的散点图,并在图中添加一个理想对角线(y = x),以便比较实际值和预测值的关系,最后望读者掌握XGBoost回归模型的参数调优技巧,并通过网格搜索和K折交叉验证实现更高效、更准确的模型

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