常规操作,先吹一下XGBoost:
XGBoost的核心思想是不断地添加树,不断地进行特征分裂来生长一棵树,每次添加一个树,其实是学习一个新函数f(x),去拟合上次预测的残差。当我们训练完成得到k棵树,我们要预测一个样本的分数,其实就是根据这个样本的特征,在每棵树中会落到对应的一个叶子节点,每个叶子节点就对应一个分数。最后只需要将每棵树对应的分数加起来就是该样本的预测值。
XGBoost对GBDT进行了一系列优化,比如损失函数进行了二阶泰勒展开、目标函数加入正则项、支持并行和默认缺失值处理等,在可扩展性和训练速度上有了巨大的提升,但其核心思想没有大的变化。
XGBoost官方文档:传送门
目录
一、Xgboost的优势
二、Xgboost的参数
三、Xgboost参数调优实例
一、Xgboost的优势
1、Regularization(正则化)
2、Parallel Processing(并行处理):
3、High Flexibility(高度灵活)
4、Handling Missing Values(处理缺失值)值,并作为参数传递。
5、Tree Pruning(树剪枝)
6、Built-in Cross-Validation(内置的交叉验证)
7、Continue on Existing Model(继续现有模型)
二、Xgboost的参数
Xgboost将工具分成了三大类:
-- General Parameters(通用参数):设置整体功能,宏观函数控制
-- Booster Parameters(提升参数):选择你每一步的booster(tree/regression),booster参数一般可以调控模型的效果和计算代价。我们所说的调参,很这是大程度上都是在调整booster参数。
-- Learning Task Parameters(学习目标参数):指导优化任务的执行,控制训练目标的表现。我们对于问题的划分主要体现在学习目标参数上。比如我们要做分类还是回归,做二分类还是多分类,这都是目标参数所提供的。
1、通用参数
--booster [default=gbtree]
选择每次迭代过程中需要运行的模型,一共有两种选择:
gbtree: tree-based models,采用树的结构来运行数据;
gblinear:基于线性模型;
--silent [default=0]
设置模型是否有logo打印:
0:有打印
1:无打印
--nthread [default to maximum number of threads available if not set]
这个主要用于并行处理的,如果不指定值,工具会自动检测。一般我们设置成-1,使用所有线程。
剩余两个参数是Xgboost自动指定的,无需设置
2、提升参数
虽然有两种类型的booster,但是我们这里只介绍tree。因为tree的性能比线性回归好得多,因此我们很少用线性回归。
--eta [default=0.3, alias: learning_rate]
学习率,可以缩减每一步的权重值,使得模型更加健壮:
典型值一般设置为:0.01-0.2
--min_child_weight [default=1]
定义了一个子集的所有观察值的最小权重和。
这个可以用来减少过拟合,但是过高的值也会导致欠拟合,因此可以通过CV来调整min_child_weight。
--max_depth [default=6]
树的最大深度,值越大,树越复杂。
这个可以用来控制过拟合,典型值是3-10。
--gamma [default=0, alias: min_split_loss]
这个指定了一个结点被分割时,所需要的最小损失函数减小的大小。
这个值一般来说需要根据损失函数来调整。
--max_delta_step(默认= 0)
这个参数通常并不需要。
--subsample [default=1]
样本的采样率,如果设置成0.5,那么Xgboost会随机选择一半的样本作为训练集。
--colsample_bytree [default=1]
构造每棵树时,列采样率(一般是特征采样率)。
--colsample_bylevel [default=1]
每执行一次分裂,列采样率。这个一般很少用,有subsample、colsample_bytree 就可以。
--lambda [default=1, alias: reg_lambda]
L2正则化(与岭回归中的正则化类似:传送门)这个其实用的很少。
--alpha [default=0, alias: reg_alpha]
L1正则化(与lasso回归中的正则化类似:传送门)这个主要是用在数据维度很高的情况下,可以提高运行速度。
--scale_pos_weight, [default=1]
在类别高度不平衡的情况下,将参数设置大于0,可以加快收敛。
3、学习任务参数
这类参数主要用来明确学习任务和相应的学习目标的
--objective [default=reg:linear]
这个主要是指定学习目标的:而分类,还是多分类or回归
“reg:linear” –linear regression:回归
“binary:logistic”:二分类
“multi:softmax” :多分类,这个需要指定类别个数
--eval_metric [default according to objective]
*评估方法,主要用来验证数据,根据一个学习目标会默认分配一个评估指标
“rmse”:均方根误差(回归任务)
“error”:分类任务
“map”:Mean average precision(平均准确率,排名任务)
--seed [default=0]
随机数种子,可以用来生成可复制性的结果,也可用来调参
三、Xgboost参数调优实例
调参的通用方法:
-- 选择一个相对较高的学习率。通常来说学习率设置为0.1。但是对于不同的问题可以讲学习率设置在0.05-0.3。通过交叉验证来寻找符合学习率的最佳树的个数。
-- 当确定好学习率与最佳树的个数时,调整树的某些特定参数。比如:max_depth, min_child_weight, gamma, subsample, colsample_bytree
-- 调整正则化参数 ,比如: lambda, alpha。这个主要是为了减少模型复杂度和提高运行速度的。适当地减少过拟合。
1、首先我们设置一些参数的初始值(你可以设置不同的值):
#Choose all predictors except target & IDcols
predictors = [x for x in train.columns if x not in [target, IDcol]]
xgb1 = XGBClassifier(
learning_rate =0.1,
n_estimators=20,
max_depth=5,
min_child_weight=1,
gamma=0,
subsample=0.8,
colsample_bytree=0.8,
objective= 'binary:logistic',
nthread=4,
scale_pos_weight=1,
seed=27)
modelfit(xgb1, train, predictors)
2、调整max_depth 和min_child_weight
我们调整这两个参数是因为这两个参数对输出结果的影响很大。我们首先将这两个参数设置为较大的数,然后通过迭代的方式不断修正,缩小范围。
param_test1 = {
'max_depth':list(range(3,10,2)),
'min_child_weight':list(range(1,6,2))
}
gsearch1 = GridSearchCV(estimator = XGBClassifier( learning_rate =0.1, n_estimators=20, max_depth=5,
min_child_weight=1, gamma=0, subsample=0.8, colsample_bytree=0.8,
objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27),
param_grid = param_test1, scoring='roc_auc',n_jobs=4,iid=False, cv=5)
gsearch1.fit(train[predictors],train[target])
gsearch1.grid_scores_, gsearch1.best_params_, gsearch1.best_score_
接下来缩小范围,将两个序列范围约束在[8,9,10];[1,2,3]
param_test2 = {
'max_depth':[8,9,10],
'min_child_weight':[1,2,3]
}
gsearch2 = GridSearchCV(estimator = XGBClassifier( learning_rate=0.1, n_estimators=20, max_depth=5,
min_child_weight=2, gamma=0, subsample=0.8, colsample_bytree=0.8,
objective= 'binary:logistic', nthread=4, scale_pos_weight=1,seed=27),
param_grid = param_test2, scoring='roc_auc',n_jobs=4,iid=False, cv=5)
gsearch2.fit(train[predictors],train[target])
gsearch2.grid_scores_, gsearch2.best_params_, gsearch2.best_score_
3、调整gamma
param_test3 = {
'gamma':[i/10.0 for i in range(0,5)]
}
gsearch3 = GridSearchCV(estimator = XGBClassifier( learning_rate =0.1, n_estimators=20, max_depth=10,
min_child_weight=1, gamma=0, subsample=0.8, colsample_bytree=0.8,
objective= 'binary:logistic', nthread=4, scale_pos_weight=1,seed=27),
param_grid = param_test3, scoring='roc_auc',n_jobs=4,iid=False, cv=5)
gsearch3.fit(train[predictors],train[target])
gsearch3.grid_scores_, gsearch3.best_params_, gsearch3.best_score_
这里gamma已经从我们前面默认的0,变成了0.2了。
最后我们用最优参数再次运行一下程序:
xgb1 = XGBClassifier(
learning_rate =0.1,
n_estimators=20,
max_depth=10,
min_child_weight=1,
gamma=0.2,
subsample=0.8,
colsample_bytree=0.8,
objective= 'binary:logistic',
nthread=4,
scale_pos_weight=1,
seed=27)
modelfit(xgb1, train, predictors)
4、调整subsample 和colsample_bytree
param_test5 = {
'subsample':[i/100.0 for i in range(75,90,5)],
'colsample_bytree':[i/100.0 for i in range(75,90,5)]
}
gsearch5 = GridSearchCV(estimator = XGBClassifier( learning_rate =0.1, n_estimators=20, max_depth=10,
min_child_weight=1, gamma=0.2, subsample=0.8, colsample_bytree=0.8,
objective= 'binary:logistic', nthread=4, scale_pos_weight=1,seed=27),
param_grid = param_test5, scoring='roc_auc',n_jobs=4,iid=False, cv=5)
gsearch5.fit(train[predictors],train[target])
gsearch5.grid_scores_, gsearch5.best_params_, gsearch5.best_score_
5、调整正则化参数
param_test6 = {
'reg_alpha':[1e-5, 1e-2, 0.1, 1, 100]
}
gsearch6 = GridSearchCV(estimator = XGBClassifier( learning_rate =0.1, n_estimators=20, max_depth=10,
min_child_weight=1, gamma=0.2, subsample=0.8, colsample_bytree=0.8,
objective= 'binary:logistic', nthread=4, scale_pos_weight=1,seed=27),
param_grid = param_test6, scoring='roc_auc',n_jobs=4,iid=False, cv=5)
gsearch6.fit(train[predictors],train[target])
gsearch6.grid_scores_, gsearch6.best_params_, gsearch6.best_score_
6、减小学习率
param_test6 = {
'reg_alpha':[1e-5, 1e-2, 0.1, 1, 100]
}
gsearch6 = GridSearchCV(estimator = XGBClassifier( learning_rate =0.1, n_estimators=20, max_depth=10,
min_child_weight=1, gamma=0.2, subsample=0.8, colsample_bytree=0.8,
objective= 'binary:logistic', nthread=4, scale_pos_weight=1,seed=27),
param_grid = param_test6, scoring='roc_auc',n_jobs=4,iid=False, cv=5)
gsearch6.fit(train[predictors],train[target])
gsearch6.grid_scores_, gsearch6.best_params_, gsearch6.best_score_
最后补充的是:
数据和特征工程决定了模型效果的上限,而模型的调参只是逼近这个上限。
特征工程传送门在此。