XGBoost模型调优:如何避免过拟合,提升预测准确性

向量数据库大模型机器学习

picture.image

背景

在机器学习模型的训练过程中,过拟合是一个常见且需要避免的问题。简单来说,过拟合是指模型在训练数据上表现得非常好,但在未见过的测试数据上表现较差。这是因为模型过度“记忆”了训练数据中的噪声和细节,而不是学习到数据中的一般规律或特征,过拟合通常发生在以下几种情况下:

  • 模型过于复杂:例如,使用过多的特征或者设置过深的树结构时,模型容易在训练数据上拟合得过于精确,导致它对测试数据的泛化能力下降
  • 训练数据量不足:当训练数据过少时,模型很容易在有限的数据上学到不具代表性的噪声,而不是数据的真实模式
  • 缺乏正则化:正则化是一种技术手段,用来控制模型的复杂度,防止其过度拟合训练数据

过拟合的后果是显而易见的:虽然模型在训练集上准确度很高,但在实际应用中,其对新数据的预测能力却不理想。为了解决这个问题,需要采取一系列的措施,比如调整模型参数、增加训练数据量、引入正则化手段等,以提升模型的泛化能力,在本文中,将探讨如何通过调节XGBoost模型的参数,来有效地解决过拟合问题,从而提升模型在实际应用中的表现

代码实现

数据读取整理


            
import pandas as pd
            
import numpy as np
            
import matplotlib.pyplot as plt 
            
import warnings
            
warnings.filterwarnings("ignore")
            
plt.rcParams['font.family'] = 'Times New Roman'
            
plt.rcParams['axes.unicode_minus'] = False
            
df = pd.read_excel('2024-12-8公众号Python机器学习AI.xlsx')
            
from sklearn.model_selection import train_test_split, KFold
            
X = df.drop(['Y'],axis=1)
            
y = df['Y']
            
# 划分训练集和测试集
            
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, 
            
                                                    random_state=42)
        

加载数据并将其划分为特征(X)和目标变量(y),然后使用train_test_split将数据分为训练集和测试集,为后续的回归模型训练做准备,调参思想分类模型的处理方式也类似

模型构建


          
from xgboost import XGBRegressor
          
from sklearn.model_selection import GridSearchCV
          

          
# 定义 XGBoost 的基础参数
          
params_xgb = {
          
    'learning_rate': 0.02,            # 学习率
          
    'max_depth': 3,                   # 树的最大深度
          
    'random_state': 42,               # 随机种子
          
    'subsample': 0.7,                 # 子样本比例
          
    'objective': 'reg:squarederror',  # 回归目标函数
          
    'eval_metric': 'rmse'             # 评估指标为均方根误差
          
}
          

          
# 初始化 XGBoost 回归模型
          
model_xgb = XGBRegressor(**params_xgb)
          

          
# 定义参数网格
          
param_grid_xgb = {
          
    'n_estimators': [100, 200, 300],  # 树的数量
          
    'max_depth': [3, 4, 5],           # 树的深度
          
    'learning_rate': [0.01, 0.1],     # 学习率
          
}
          

          
# 使用 GridSearchCV 进行网格搜索和 k 折交叉验证
          
grid_search_xgb = GridSearchCV(
          
    estimator=model_xgb,
          
    param_grid=param_grid_xgb,
          
    scoring='neg_mean_squared_error',  # 评价指标为负均方误差
          
    cv=5,                              # 5 折交叉验证
          
    n_jobs=-1,                         # 并行计算
          
    verbose=1                          # 输出详细进度信息
          
)
          

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

          
# 使用最优参数训练模型
          
best_model_xgb = grid_search_xgb.best_estimator_
          

          

          
# 定义 XGBoost 的基础参数
          
params_xgb_v2 = {
          
    'learning_rate': 0.01,            # 降低学习率
          
    'max_depth': 3,                   # 树的最大深度
          
    'random_state': 42,               # 随机种子
          
    'subsample': 0.7,                 # 样本子采样比例
          
    'colsample_bytree': 0.7,          # 特征子采样比例
          
    'objective': 'reg:squarederror',  # 回归目标函数
          
    'eval_metric': 'rmse',            # 评估指标为均方根误差
          
    'min_child_weight': 10,           # 增大最小叶节点权重
          
    'gamma': 0.1,                     # 分裂所需的最小增益
          
    'reg_alpha': 0.5,                 # L1 正则化系数
          
    'reg_lambda': 1.0                 # L2 正则化系数
          
}
          

          
# 初始化新的回归模型
          
model_xgb_v2 = XGBRegressor(**params_xgb_v2)
          
param_grid_xgb_v2 = {
          
    'n_estimators': [300, 500, 700],   # 树的数量
          
    'max_depth': [3, 4, 5],            # 树的深度
          
    'subsample': [0.6, 0.7, 0.8],      # 样本子采样比例
          
    'colsample_bytree': [0.6, 0.7, 0.8] # 特征子采样比例
          
}
          

          
grid_search_xgb_v2 = GridSearchCV(
          
    estimator=model_xgb_v2,
          
    param_grid=param_grid_xgb_v2,
          
    scoring='neg_mean_squared_error',  
          
    cv=5,                              
          
    n_jobs=-1,                         
          
    verbose=1                          
          
)
          

          
grid_search_xgb_v2.fit(X_train, y_train)
          
best_model_xgb_v2 = grid_search_xgb_v2.best_estimator_
      

这里构建两个XGBoost回归模型 (model_xgb 和 model_xgb_v2),并通过GridSearchCV进行超参数调优,它们的主要差异体现在以下几个方面:

  • 学习率——model_xgb: 使用较高的学习率 0.02,这个学习率使得每棵树的影响较大,模型更新较快,但容易过拟合;model_xgb_v2: 使用较低的学习率 0.01,通过减小步长来提高模型的泛化能力,避免过拟合,通常较低的学习率配合更多的树(n_estimators)能提供更好的性能
  • 特征子采样比例——model_xgb: 没有设置colsample_bytree参数,意味着每棵树在构建时使用所有特征;model_xgb_v2: 设置了colsample_bytree为 0.7,即每棵树只随机选择70%的特征进行训练,这可以帮助减少模型的方差,提高模型的泛化能力
  • 最小叶节点权重——model_xgb: 没有设置min_child_weight,这意味着默认情况下,树的每个叶节点至少需要一个样本;model_xgb_v2: 设置了min_child_weight为10,这意味着每个叶节点需要至少有10个样本。这有助于防止模型生成过于细小的叶节点,从而降低过拟合的风险
  • 分裂所需的最小增益——model_xgb: 没有设置gamma,意味着树的分裂是基于数据中最大的信息增益来进行的;model_xgb_v2: 设置了gamma 为0.1,即每次分裂时,增益必须大于0.1才会继续分裂。gamma 提高可以防止树的分裂过多,有助于减少过拟合
  • L1正则化系数和 L2正则化系数——model_xgb: 没有设置reg_alpha和reg_lambda,这些参数默认值通常较低;model_xgb_v2: 设置了reg_alpha为0.5和reg_lambda为1.0,分别控制 L1 和 L2 正则化强度。增加这些正则化项有助于减少模型复杂度,从而提高模型的泛化能力,减少过拟合的风险
  • 树的数量——model_xgb: 在param_grid_xgb中,使用了较少的树的数量选项 [100, 200, 300];model_xgb_v2: 在param_grid_xgb_v2中,使用了更多树的数量选项 [300, 500, 700]。结合较低的学习率(learning_rate),更多的树可以帮助更精细地拟合数据,而不会过快过度拟合
  • 子样本比例——model_xgb: 设置为0.7,表示每棵树训练时只使用70%的样本,避免过拟合并提高模型的泛化能力;

model_xgb_v2: 同样设置为 0.6, 0.7, 0.8,通过调整不同的子样本比例来探索不同的模型表现,进一步增强模型的泛化能力

model_xgb是一个基础的XGBoost模型,设置了较为基础的超参数(较高的学习率,标准的样本采样比例等,model_xgb_v2则通过引入更多的正则化项、较低的学习率、更高的树数量等措施,目的是提高模型的稳定性和泛化能力,尤其是在应对过拟合时更为有效

模型评价指标计算


          
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score, explained_variance_score
          

          
def evaluate_model(model, X_train, y_train, X_test, y_test):
          
    y_train_pred = model.predict(X_train)
          
    y_test_pred = model.predict(X_test)
          
    
          
    return {
          
        "Dataset": ["Train", "Test"],
          
        "MSE": [
          
            mean_squared_error(y_train, y_train_pred),
          
            mean_squared_error(y_test, y_test_pred)
          
        ],
          
        "RMSE": [
          
            np.sqrt(mean_squared_error(y_train, y_train_pred)),
          
            np.sqrt(mean_squared_error(y_test, y_test_pred))
          
        ],
          
        "MAE": [
          
            mean_absolute_error(y_train, y_train_pred),
          
            mean_absolute_error(y_test, y_test_pred)
          
        ],
          
        "R^2": [
          
            r2_score(y_train, y_train_pred),
          
            r2_score(y_test, y_test_pred)
          
        ],
          
        "EV": [
          
            explained_variance_score(y_train, y_train_pred),
          
            explained_variance_score(y_test, y_test_pred)
          
        ]
          
    }
          

          
metrics_xgb_v1 = evaluate_model(best_model_xgb, X_train, y_train, X_test, y_test)
          
metrics_xgb_v2 = evaluate_model(best_model_xgb_v2, X_train, y_train, X_test, y_test)
          
df_metrics_v1 = pd.DataFrame(metrics_xgb_v1)
          
df_metrics_v2 = pd.DataFrame(metrics_xgb_v2)
          
df_metrics_v1["Model"] = "XGB Model V1"
          
df_metrics_v2["Model"] = "XGB Model V2"
          
comparison_df = pd.concat([df_metrics_v1, df_metrics_v2], ignore_index=True)
          
comparison_df
      

picture.image

对前面两个XGBoost回归模型在训练集和测试集上的表现进行评估,并将各自的评估指标(MSE、RMSE、MAE、R²和EV)整合到一个数据框中,通过参数调整(如降低学习率、增加正则化项和优化采样比例等),XGB Model V2 在训练集上的表现有所下降(R^2从 0.986降至 0.905),但测试集性能显著提升(R^2从0.791增加到0.844,MSE从0.179降至0.134),这表明模型在泛化能力上得到了增强,同时缓解了过拟合问题,使得预测结果对新数据更加稳健和准确,当然,两者之间仍然存在一定的差异,可以进一步通过调整参数、优化采样策略以及改进数据集处理方式来进一步降低过拟合情况

可视化展示


          
# 提取 XGB Model V1 的评价指标
          
metrics_v1 = df_metrics_v1[df_metrics_v1['Model'] == 'XGB Model V1']
          
metrics_train_v1 = metrics_v1.iloc[0, 1:6].values  # 训练集指标
          
metrics_test_v1 = metrics_v1.iloc[1, 1:6].values   # 测试集指标
          
# 提取 XGB Model V2 的评价指标
          
metrics_v2 = df_metrics_v2[df_metrics_v2['Model'] == 'XGB Model V2']
          
metrics_train_v2 = metrics_v2.iloc[0, 1:6].values  # 训练集指标
          
metrics_test_v2 = metrics_v2.iloc[1, 1:6].values   # 测试集指标
          
labels = ['MSE', 'RMSE', 'MAE', 'R^2', 'EV']
          
num_vars = len(labels)
          
angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()
          
metrics_train_v1 = np.concatenate((metrics_train_v1, [metrics_train_v1[0]]))
          
metrics_test_v1 = np.concatenate((metrics_test_v1, [metrics_test_v1[0]]))
          
metrics_train_v2 = np.concatenate((metrics_train_v2, [metrics_train_v2[0]]))
          
metrics_test_v2 = np.concatenate((metrics_test_v2, [metrics_test_v2[0]]))
          
angles += angles[:1] 
          
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6), dpi=80, subplot_kw=dict(polar=True))
          
ax1.plot(angles, metrics_train_v1, color='blue', linewidth=2, linestyle='solid', label='Train')
          
ax1.fill(angles, metrics_train_v1, color='blue', alpha=0.25)
          
ax1.plot(angles, metrics_test_v1, color='red', linewidth=2, linestyle='solid', label='Test')
          
ax1.fill(angles, metrics_test_v1, color='red', alpha=0.25)
          
ax1.set_yticklabels([])  
          
ax1.set_xticks(angles[:-1])  
          
ax1.set_xticklabels(labels)
          
ax1.set_ylim(0, 1)  
          
ax1.set_title('Model Evaluation Metrics: XGB Model V1', size=16)
          
ax1.legend(loc='upper right', bbox_to_anchor=(1.2, 1))
          
ax2.plot(angles, metrics_train_v2, color='green', linewidth=2, linestyle='solid', label='Train')
          
ax2.fill(angles, metrics_train_v2, color='green', alpha=0.25)
          
ax2.plot(angles, metrics_test_v2, color='orange', linewidth=2, linestyle='solid', label='Test')
          
ax2.fill(angles, metrics_test_v2, color='orange', alpha=0.25)
          
ax2.set_yticklabels([])  
          
ax2.set_xticks(angles[:-1])  
          
ax2.set_xticklabels(labels)
          
ax2.set_ylim(0, 1)  
          
ax2.set_title('Model Evaluation Metrics: XGB Model V2', size=16)
          
ax2.legend(loc='upper right', bbox_to_anchor=(1.2, 1))
          
plt.savefig('雷达图.pdf', format="pdf", bbox_inches="tight", dpi=300)
          
plt.tight_layout()
          
plt.show()
      

picture.image

通过雷达图可视化展示两个模型在训练集和测试集上的各项指标表现,直观体现XGB Model V2 相较于XGB Model V1在测试集上的性能提升和过拟合现象的缓解,代码与数据集获取:如需获取本文的源代码和数据集,请添加作者微信联系

往期推荐

SCI图表复现:整合数据分布与相关系数的高级可视化策略

SCI图表:基于相关性和标准差的多模型评价——泰勒图解析

期刊文章配图:基于分组折线图的多机器学习模型表现评估对比

复现SCI文章 SHAP 依赖图可视化以增强机器学习模型的可解释性

SCI图表复现:优化SHAP特征贡献图展示更多模型细节

复现 Nature 图表——基于PCA的高维数据降维与可视化实践及其扩展

复现Nature图表——基于PCA降维与模型预测概率的分类效果可视化

SCI图表复现:特征相关性气泡热图展示

一图胜千言:回归预测模型训练集与测试集的进阶可视化

期刊文章配图:基于雷达图的多机器学习模型表现评估对比

期刊文章配图:斯皮尔曼相关系数热图反应非线性变量相关性

picture.image

如果你对类似于这样的文章感兴趣。

欢迎关注、点赞、转发~

个人观点,仅供参

0
0
0
0
关于作者

文章

0

获赞

0

收藏

0

相关资源
CV 技术在视频创作中的应用
本次演讲将介绍在拍摄、编辑等场景,我们如何利用 AI 技术赋能创作者;以及基于这些场景,字节跳动积累的领先技术能力。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论