六级考试时间2020 九月XGBoost、LightGBM与CatBoost算法对⽐与调参
机器学习
Author:louwill
Machine Learning Lab
虽然现在深度学习⼤⾏其道,但以XGBoost、LightGBM和CatBoost为代表的Boosting算法仍有其⼴阔的⽤武之地。抛开深度学习适⽤的图像、⽂本、语⾳和视频等⾮结构化的数据应⽤,Boosting算法对于训练样本较少的结构化数据领域仍然是第⼀选择。本⽂先对前述章节的三⼤Boosting的联系与区别进⾏简单阐述,并⼀个实际数据案例来对三⼤算法进⾏对⽐。然后对常⽤的Boosting算法超参数调优⽅法进⾏介绍,包括随机调参法、⽹格搜索法和贝叶斯调参法,并给出相应的代码⽰例。
三⼤Boosting算法对⽐
⾸先,XGBoost、LightGBM和CatBoost都是⽬前经典的SOTA(state of the art)Boosting算法,都可以归类到梯度提升决策树算法系列。三个模型都是以决策树为⽀撑的集成学习框架,其中XGBoost是对原始版本的GBDT算法的改进,⽽LightGBM和CatBoost则是在XGBoost基础上做了进⼀步的优化,在精度和速度上都有各⾃的优点。
envelope怎么读三⼤模型的原理细节我们本⽂不做叙述,可参考。那么这三⼤Boosting算法⼜有哪些⼤的⽅⾯的区别呢?主要有两个⽅⾯。第⼀个是三个模型树的构造⽅式有所不同,XGBoost使⽤按层⽣长(level-wi)的决策树构建策略,LightGBM则是使⽤按叶⼦⽣长(leaf-wi)的构建策略,⽽CatBoost使⽤了对称树结构,其决策树都是完全⼆叉树。第⼆个有较⼤区别的⽅⾯是对于类别特征的处理。XGBoost本⾝不具备⾃动处理类别特征的能⼒,对于数据中的类别特征,需要我们⼿动处理变换成数值后才能输⼊到模型中;LightGBM中则需要指定类别特征名称,算法即可对其⾃动进⾏处理;CatBoost以处理类别特征⽽闻名,通过⽬标变量统计等特征编码⽅式也能实现类别特征的⾼效处理。
下⾯我们以kaggle 2015年航班延误数据集为⽰例,分别⽤XGBoost、LightGBM和CatBoost模型进⾏实验。图1是flights数据集简介。
图2 flights数据集
该数据集完整数据量有500多万条航班记录数据,特征有31个,仅作演⽰⽤的情况下,我们采⽤抽样
的⽅式从原始数据集中抽样1%的数据,并筛选11个特征,经过预处理后重新构建训练数据集,⽬标是构建对航班是否延误的⼆分类模型。数据读取和简单预处理过程如代码1所⽰。
代码1 数据处理
# 导⼊pandas和sklearn数据划分模块
import pandas as pd
del_lection import train_test_split
# 读取flights数据集
flights = pd.read_csv('flights.csv')
# 数据集抽样1%
flights = flights.sample(frac=0.01, random_state=10)
# 特征抽样,获取指定的11个特征
flights = flights[["MONTH", "DAY", "DAY_OF_WEEK", "AIRLINE",
"FLIGHT_NUMBER","DESTINATION_AIRPORT", "ORIGIN_AIRPORT","AIR_TIME",
"DEPARTURE_TIME", "DISTANCE", "ARRIVAL_DELAY"]]
# 对标签进⾏离散化,延误10分钟以上才算延误
flights["ARRIVAL_DELAY"] = (flights["ARRIVAL_DELAY"]>10)*1
# 类别特征
cat_cols = ["AIRLINE", "FLIGHT_NUMBER", "DESTINATION_AIRPORT",
"ORIGIN_AIRPORT"]
# 类别特征编码
米歇尔泰勒for item in cat_cols:
flights[item] = flights[item].astype("category").des +1
# 数据集划分
firefly什么意思
X_train, X_test, y_train, y_test = train_test_split(
flights.drop(["ARRIVAL_DELAY"], axis=1),
flights["ARRIVAL_DELAY"],
random_state=10, test_size=0.3)
# 打印划分后的数据集⼤⼩
print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)
输出:
(39956, 10) (39956,) (17125, 10) (17125,)
在代码1中,我们先读取了flights原始数据集,因为原始数据集量太⼤,我们对其进⾏抽样1%,并筛选了11个特征,构建有57081条1、11个特征的航班记录数据集。然后对抽样数据集进⾏简单的预处理,先对训练标签进⾏⼆值离散化,延误⼤于10分钟的转化为1(延误),延误⼩于10分钟的转化为0(不延误),然后对“航线”、“航班号”、“⽬的地机场”、“出发地机场”等类别特征进⾏类别编码处理。最后划分数据集,得到有39956条训练样本,17125条测试样本。
XGBoost
下⾯我们开始来测试三个模型在该数据集上的效果。先来看XGBoost,如代码2所⽰。
代码2 XGBoost
# 导⼊模型评估auc函数
ics import roc_auc_score
# 设置模型超参数
params = {
'booster': 'gbtree',
'objective': 'binary:logistic',
'gamma': 0.1,
'max_depth': 8,
'lambda': 2,
'subsample': 0.7,
'colsample_bytree': 0.7,
'min_child_weight': 3,
'eta': 0.001,
'ed': 1000,
'nthread': 4,
}
# 封装xgboost数据集
dtrain = xgb.DMatrix(X_train, y_train)
# 训练轮数,即树的棵数
num_rounds = 500
# 模型训练
model_xgb = ain(params, dtrain, num_rounds)
# 对测试集进⾏预测
sundaysdtest = xgb.DMatrix(X_test)
y_pred = model_xgb.predict(dtest)
print('AUC of testt bad on XGBoost: ', roc_auc_score(y_test, y_pred))
输出:
AUC of testt bad on XGBoost: 0.6845368959487046
在代码15-2中,我们测试了XGBoost在flights数据集上的表现,导⼊相关模块并设置模型超参数,便可基于训练集进⾏XGBoost模型拟合,最后将训练好的模型⽤于测试集预测,可得到测试集AUC为0.6845。
LightGBM
LightGBM在flights数据集上的测试过程如代码3所⽰。
代码3 LightGBM
dtrain = lgb.Datat(X_train, label=y_train)
params = {
"max_depth": 5,
zpn"learning_rate" : 0.05,
"num_leaves": 500,
"n_estimators": 300
}
# 指定类别特征
cate_features_name = ["MONTH","DAY","DAY_OF_WEEK","AIRLINE",
狗屎的英文"DESTINATION_AIRPORT", "ORIGIN_AIRPORT"]
# lightgbm模型拟合
model_lgb = ain(params, d_train,
categorical_feature = cate_features_name)
bepatient# 对测试集进⾏预测
y_pred = model_lgb.predict(X_test)
print('AUC of testt bad on XGBoost: 'roc_auc_score(y_test, y_pred))
输出:
AUC of testt bad on XGBoost: 0.6873707383550387
在代码3中,我们测试了LightGBM在flights数据集上的表现,导⼊相关模块并设置模型超参数,便可
基于训练集进⾏LightGBM模型拟合,最后将训练好的模型⽤于测试集预测,可得到测试集AUC为0.6873,跟XGBoost效果差不多。
CatBoost
CatBoost在flights数据集上的测试过程如代码4所⽰。
代码4 CatBoost
# 导⼊lightgbm模块
import catboost as cb
# 类别特征索引
cat_features_index = [0,1,2,3,4,5,6]
# 创建catboost模型实例
model_cb = cb.CatBoostClassifier(eval_metric="AUC",
one_hot_max_size=50, depth=6, iterations=300, l2_leaf_reg=1,
learning_rate=0.1)
# catboost模型拟合
model_cb.fit(X_train, y_train, cat_features=cat_features_index)
# 对测试集进⾏预测
y_pred = model_cb.predict(X_test)
print('AUC of testt bad on CatBoost: 'roc_auc_score(y_test, y_pred))
输出:
AUC of testt bad on CatBoost: 0.5463773041667715
在代码4中,我们测试了CatBoost在flights数据集上的表现,导⼊相关模块并设置模型超参数,便可基于训练集进⾏CatBoost模型拟合,最后将训练好的模型⽤于测试集预测,可得到测试集AUC为0.54,相较于XGBoost和LightGBM,CatBoost在该数据集上的效果要差不少。表1是针对flights数据集三⼤模型的综合对⽐结果。
从表1的综合对⽐结果来看,LightGBM⽆论是在精度上还是速度上,都要优于XGBoost和CatBoost。当然了,我们只是在数据集上直接⽤三个模型做了⽐较,没有做进⼀步的数据特征⼯程和超参数调优,表1的结果均可做进⼀步的优化。
常⽤的超参数调优⽅法judy
机器学习模型中有⼤量需要事先进⾏⼈为设定的参数,⽐如说神经⽹络训练的batch-size,XGBoost
等集成学习模型的树相关参数,我们将这类不是经过模型训练得到的参数叫做超参数(hyperparameter)。⼈为的对超参数调整的过程也就是我们熟知的调参。机器学习中常⽤的调参⽅法包括⽹格搜索法(grid arch)、随机搜索法(random arch)和贝叶斯优化(bayesian optimization)。
⽹格搜索法
⽹格搜索是⼀项常⽤的超参数调优⽅法,常⽤于优化三个或者更少数量的超参数,本质是⼀种穷举法。对于每个超参数,使⽤者选择⼀个较⼩的有限集去探索。然后,这些超参数笛卡尔乘积得到若⼲组超参数。⽹格搜索使⽤每组超参数训练模型,挑选验证集误差最⼩的超参数作为最好的超参数。
例如,我们有三个需要优化的超参数a,b,c,候选的取值分别是{1,2},{3,4},{5,6}。则所有可能的参数取值组合组成了⼀个8个点的3维空间⽹格如下:{(1,3,5),(1,3,6),(1,4,5),(1,4,6),(2,3,5),(2,3,6),(2,4,5),(2,4,6)},⽹格搜索就是通过遍历这8个可能的参数取值组合,进⾏训练和验证,最终得到最优超参数。
Sklearn中通过model_lection模块下的GridSearchCV来实现⽹格搜索调参,并且这个调参过程是加了交叉验证的。我们同样以前述flights数据集为例,展⽰XGBoost的⽹格搜索代码⽰例。
代码5 ⽹格搜索
### 基于XGBoost的GridSearch搜索范例
# 导⼊GridSearch模块
del_lection import GridSearchCV
# 创建xgb分类模型实例
model = xgb.XGBClassifier()
# 待搜索的参数列表空间
param_lst = {"max_depth": [3,5,7],
"min_child_weight" : [1,3,6],
东莞南博职业技术学院"n_estimators": [100,200,300],
"learning_rate": [0.01, 0.05, 0.1]
}
# 创建⽹格搜索
grid_arch = GridSearchCV(model, param_grid=param_lst, cv=3,
verbo=10, n_jobs=-1)
# 基于flights数据集执⾏搜索
grid_arch.fit(X_train, y_train)
# 输出搜索结果
print(grid_arch.best_estimator_)