前言

Xgboost对特征工程和数据处理比较友好,相比之下调参成为用好Xgboost重要的一环,本文分别从参数、调参方法、Python实现的维度进行梳理,作为调参思路的记录。

本文将关注以下几个问题:

1.Xgboost哪些参数需要调参?

2.通用的调参方法有哪些 ? 如何实现?

Xgboost哪些参数需要调参?

下表列出了 xgboost 0.90版本下 xgboost.sklearn 中 XGBBaseModel 的所有输入参数;根据对全部31个参数功能的初步了解并参考了其他博文(包括XGBoost调参笔记_浅笑古今的博客-CSDN博客_xgboost调参,https://segmentfault.com/a/1190000014040317等),初步对xgboost 实践中各参数调参重要性进行了排序,详见rank列;其中3>2>1。需要说明的是,这种调参重要性的划分只是提供一种参考,仍需要根据具体问题具体分析。(TODO:其中有些None值和空值还需要完善

参数名简说明范围默认典型值rank说明
n_estimators学习器的数量int100100~5003基本学习器的数量
max_depth树深度0,∞33~103每个基本学习器树的最大深度,值越大数越复杂
learning_rate学习率[0,1]0.10.01~0.23每次迭代更新权重时的步长。值越小,训练的越慢。
gamma损失减少阈值0,∞0None3分裂节点时,损失函数减小值只有大于等于gamma节点才分裂,gamma值越大,算法越保守
reg_alphaL1正则化float0None3增加该值会让模型更加收敛
reg_lambdaL2正则化float1None3控制XGBoost的正则化部分的,可以减少过拟合
min_child_weight子集最小权重0,∞1None3如果节点的样本权重和小于该阈值,就不再进行拆分,该指数越大越大算法越保守。回归中是指建立每个模型所需要的最小样本数
subsample样本子采样(0,1]10.5-0.93随机选取一定比例的样本来训练树。设置为0.5,则意味着XGBoost将从整个样本集合中随机的抽取出50%子样本建立树模型
colsample_bytree列子采样(0,1]10.5-0.93列采样率,也就是特征采样率。在建立树时对特征采样的比例
booster基模型类型gbtree gblineargbtreeNone2gbtree使用基于树的模型进行提升计算,gblinear使用线性模型进行提升计算
colsample_bylevel列子采样(0,1]1None2构建每一层时,列采样率
colsample_bynode列子采样[0,1]1None2是每个节点(拆分)的列的子采样率
scale_pos_weight处理样本不平衡float1None2处理样本不平衡问题。在样本高度不平衡时,将参数设置大于0,可以加快算法收敛。
random_state随机数种子int0None2设置它可以复现随机数据的结果,也可以用于调整参数
max_delta_step树权重最大增量0,∞00~101每棵树所被允许的权重估计为最大增量。如果该值设置为0,则表示没有约束。如果将其设置为正值,则有助于使更新步骤更加保守。通常不需要这个参数,但当类极不平衡时,它可能有助于logistic回归。
verbosity日志长度intNone1日志冗长程度0-3
tree_method指定树方法auto exact approx hist gpu_exact gpu_histautoNone1指定要使用的树生成算法
base_score全局偏差int/float0.51所有实例的初始预测得分,整体偏倚
silent过程打印设置0,1 or True,False0None1取0时表示打印出运行时信息,取1时表示不打印运行时信息
importance_type特征重要性类型NoneNone1feature_importances_属性的特征重要性类型
eval_metric指定评估指标rmse mae logloss error merror mlogloss auc回归:rmse 分类:error回归:rmse分类:error1校验数据所需要的评价指标,不同的目标函数将会有缺省的评价指标 rmse:均方根误差,mae:平均绝对误差,logloss:负对数似然函数值,error:二分类错误率(阈值为0.5),merror:多分类错误率,mlogloss:多分类logloss损失函数,auc:曲线下面积
missing缺失值NoneNone0需要作为缺失值存在的数据中的值,如果为none,则默认为np.nan
num_parallel_tree增强随机森林intNone0用于增强随机森林
kwargs字典形式传参dictNone0以字典形式传递参数
n_jobs线程数目int1None0线程数目
nthread并行计算设置int默认当前系统可以获得的最大线程数None0XGBoost运行时的线程数
monotone_constraints变量单调性约束NoneNone0变量单调性约束
interaction_constraints交互约束NoneNone0表示允许交互的交互约束
gpu_idgpu IDNoneNone0
validate_parameters验证参数NoneNone0
objective指定损失函数reg:linear reg:logistic binary:logistic binary:logitraw count:poisson multi:softmax multi:softprob rank:pairwiseNone0指的是需要被最小化的损失函数 reg:linear:线性回归
reg:logistic:逻辑回归
binary:logistic:二分类
binary:logitraw:二分类
count:poisson:计数问题
multi:softmax:多分类
multi:softprob:多分类
rank:pairwise:排名

重要参数介绍

各参数的主要功能虽然已经在上表中列出,但为了方便对调参的过程有进一步的理解,本小节对以下9个重要参数进行略微详细的介绍。

n_estimators(基本学习器的数量):要拟合的弱学习器数量,该值越大,模型越复杂,越容易过拟合

max_depth(基本学习器的深度): 树的最大深度,该值越大,模型越复杂,越容易拟合训练数据,越容易过拟合;树生长停止条件之一

learning_rate(学习率):每个基模型的惩罚项,降低单个模型的影响,为了防止过拟合,该值越接近1越容易或拟合,越接近0精度越低

gamma(损失减少阈值):在树的叶节点上进一步划分所需的最小损失减少,在模型训练过程中,只有损失下降的值超过该值,才会继续分裂节点,该值越小模型越复杂,越容易过拟合,树生长停止条件之一

reg_alpha(L1正则化):L1正则化用于对叶子的个数进行惩罚,用于防止过拟合

reg_lambda(L2正则化):L2正则化用于对叶子节点的得分进行惩罚,L1和L2正则化项共同惩罚树的复杂度,值越小模型的鲁棒性越高

min_child_weight(子集最小权重):最小样本的权重之和,在树的生长过程中,如果样本的权重之和小于该值,将不再分裂;树生长停止条件之一

subsample(样本子采样):训练集对样本实例的采样率,用于防止过拟合

colsample_bytree(列子采样):每棵树对特征的采样率,用于防止过拟合

通用的调参方法有哪些 ? 如何实现?

机器学习模型的训练过程,就是为模型找到最优超参数组合,使得模型在保证足够精度的情况下同时具有良好的鲁棒性;下面简单介绍四种常用的机器学习调参方法的基本思路和优缺点。

需要说明的是,下面几种搜索最佳参数的方法都需要事先指定要优化哪些超参数以及超参数优化的范围(有限可列集合),其中搜索代码都调用了sklearn.model_selection 模块。

1.手动调参

顾名思义,此方法手动从参数集中选择参与调优的参数,并手动设置超参数的数值,如果训练效果不佳再重新设置超参数的数值,直到达到满意的训练效果;这种方法依赖调参者对超参数在算法中影响的深刻理解,和丰富的调参经验,往往也很难验证调参结果是否是最优或接近最优的结果。手动调参方式比较随意,不附代码

2.网格搜索

网格搜索首先为每个待优化的超参数列出一个值列表,然后尝试列表中值的所有组合,这种方法的特点是尝试的参数组合最全,如果参数值步长足够小,参数足够全,理论上模型可以接近全局最优解,但是由于连续值参数我们仍然需要采样,因此仍然不能保证达到全局最优解。网格搜索的计算量也非常巨大,速度非常的慢。

#coding:utf-8from xgboost.sklearn import XGBRegressorfrom sklearn.model_selection import GridSearchCVimport pandas as pdimport numpy as npfrom math import sqrtfrom sklearn.metrics import mean_squared_error#1.以CSV形式导入数据集df_train = pd.read_csv(r"C:\Users\ld\Desktop\train.csv")df_test = pd.read_csv(r"C:\Users\ld\Desktop\test.csv")X_train = df_train[[i for i in df_train.columns.tolist() if i not in ["label"]]] #训练集y_train = df_train["label"]#训练标签X_test =df_test[[i for i in df_test.columns.tolist() if i not in ["label"]]] #测试集y_test = df_test["label"]#测试标签#2.参数集定义param_grid = {'max_depth': [2, 3, 4, 5, 6, 7, 8],'n_estimators': [30, 50, 100, 300, 500, 1000,2000],'learning_rate': [0.1, 0.2, 0.3, 0.4, 0.01, 0.02, 0.03, 0.05, 0.5],"gamma":[0.0, 0.1, 0.2, 0.3, 0.4],"reg_alpha":[0.0001,0.001, 0.01, 0.1, 1, 100],"reg_lambda":[0.0001,0.001, 0.01, 0.1, 1, 100],"min_child_weight": [2,3,4,5,6,7,8],"colsample_bytree": [0.6, 0.7, 0.8, 0.9],"subsample":[0.6, 0.7, 0.8, 0.9]}#3.网格搜索并打印最佳参数gsearch1 = GridSearchCV(estimator=XGBRegressor(scoring='ls',seed=27), param_grid=param_grid, cv=5)gsearch1.fit(X_train, y_train)print("best_score_:",gsearch1.best_params_,gsearch1.best_score_)#4.用最佳参数进行预测y_test_pre= gsearch1.predict(X_test)#5.打印测试集RMSErmse = sqrt(mean_squared_error(np.array(list(y_test)), np.array(list(y_test_pre))))print("rmse:",rmse)

3.随机搜索

随机搜索是指在超参数分布中随机选择参数值的方法;这种方法类似于对网格搜索的超参组合进行抽样后,再对抽样集进行网格搜索,随机搜索的速度比网格搜索快很多,但也很难保证模型收敛于全局最优解或最优解附近。

#coding:utf-8from xgboost.sklearn import XGBRegressorfrom sklearn.model_selection import RandomizedSearchCVimport pandas as pdimport numpy as npfrom math import sqrtfrom sklearn.metrics import mean_squared_error#1.以CSV形式导入数据集df_train = pd.read_csv(r"C:\Users\ld\Desktop\train.csv")df_test = pd.read_csv(r"C:\Users\ld\Desktop\test.csv")X_train = df_train[[i for i in df_train.columns.tolist() if i not in ["label"]]] #训练集y_train = df_train["label"]#训练标签X_test =df_test[[i for i in df_test.columns.tolist() if i not in ["label"]]] #测试集y_test = df_test["label"]#测试标签#2.参数集定义param_grid = {'max_depth': [2, 3, 4, 5, 6, 7, 8],'n_estimators': [30, 50, 100, 300, 500, 1000,2000],'learning_rate': [0.1, 0.2, 0.3, 0.4, 0.01, 0.02, 0.03, 0.05, 0.5],"gamma":[0.0, 0.1, 0.2, 0.3, 0.4],"reg_alpha":[0.0001,0.001, 0.01, 0.1, 1, 100],"reg_lambda":[0.0001,0.001, 0.01, 0.1, 1, 100],"min_child_weight": [2,3,4,5,6,7,8],"colsample_bytree": [0.6, 0.7, 0.8, 0.9],"subsample":[0.6, 0.7, 0.8, 0.9]}#3.随机搜索并打印最佳参数gsearch1 = RandomizedSearchCV(XGBRegressor(scoring='ls',seed=27), param_grid, cv=5)gsearch1.fit(X_train, y_train)print("best_score_:",gsearch1.best_params_,gsearch1.best_score_)#4.用最佳参数进行预测y_test_pre= gsearch1.predict(X_test)#5.打印测试集RMSErmse = sqrt(mean_squared_error(np.array(list(y_test)), np.array(list(y_test_pre))))print("rmse:",rmse)

4.贝叶斯搜索

前面介绍的三种搜索方法,参数组合之间的尝试是相互独立的,不会因为一个参数组合而影响其他参数组合;而贝叶斯优化算法在寻找最优参数时,会充分利用之前尝试过的参数组合信息,来学习目标函数的期望和走向,并找到使目标函数更优的参数组合,并迭代。但有时初始参数的选择不当可能导致贝叶斯搜索陷入局部最优解,因此贝叶斯分布会在还未取样的区域进行采样或后验概率分布下全局最值出现概率最大的区域进行采样中进行平衡。相比网格搜索,贝叶斯搜索的速度更快,相比随机搜索,贝叶斯搜索的可以更好的保留重要信息,搜索效果更稳健。

补充:除了上述几种基础的调参方法外,网上还有一种结合手动调参和网格搜索为Xgboost调参的半自动化方法,目前没有做尝试,仅作为记录;步骤如下:

(1)先网格搜索 n_estimators 参数,其他参数取定值

(2)取(1)中最优化结果加入参数定值,并网格搜索min_child_weight和max_depth两参数

(3)取(1)(2)中最优化结果加入参数定值,并网格搜索 gamma 参数

(4)取(1)~(3)中最优化结果加入参数定值,并网格搜索 subsample和colsample_bytree参数

(5)取(1)~(4)中最优化结果加入参数定值,并网格搜索 reg_alpha 和 reg_lambda参数

(6)取(1)~(5)中最优化结果加入参数定值,并网格搜索 learning_rate 参数

参考文档:

机器学习中四种调参方法总结

Sina Visitor System

贝叶斯优化(Bayesian Optimization)只需要看这一篇就够了,算法到python实现 – 知乎

几种机器学习常用调参方式对比(网格搜索,随机搜索,贝叶斯优化)_tomwang0322的博客-CSDN博客_网格搜索策略

机器学习:超参数调优的方法(网格搜索 、随机搜索、贝叶斯优化算法)_WellWang_S的博客-CSDN博客_网格搜索算法设置最优超参数

https://segmentfault.com/a/1190000014040317