作者: Quan Chen
XGBoost算法可以给预测模型带来能力的提升。它具有很多优势:
正则化
并行处理
高度的灵活性
缺失值处理
剪枝
当分裂时遇到一个负损失时,GBM会停止分裂。因此GBM实际上是一个贪心算法。
XGBoost会一直分裂到指定的最大深度(max_depth),然后回过头来剪枝。如果某个节点之后不再有正值,它会去除这个分裂。这种做法的优点,当一个负损失(如-2)后面有个正损失(如+10)的时候,就显现出来了。GBM会在-2处停下来,因为它遇到了一个负值。但是XGBoost会继续分裂,然后发现这两个分裂综合起来会得到+8,因此会保留这两个分裂。
内置交叉验证
在已有的模型基础上继续
总的来说GBM的参数可以被归为三类:
树参数: 调节模型中每个决定树的性质
Boosting参数: 调节模型中boosting的操作
其他模型参数: 调节模型总体的各项运作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tIK610iJ-1572667377607)(img/tree-infographic.png)]
图 决策树的一般结构
宏观参数
booster[默认gbtree]
选择每次迭代的模型,有两种选择:
gbtree:基于树的模型
gbliner:基于线性的模型
silent[默认0]
nthread[默认值为最大可能的线程数]
提升器(Booster)参数:在每一步中引导单个的加速器(Booster)(树/回归)
尽管有两种booster可供选择,我这里只介绍
tree booster
,因为它的表现远远胜过linear booster
,所以linear booster很少用到。
num_boosting_rounds
learning_rate(或eta)[默认0.3]
min_child_weight[默认1]
max_depth[默认6]
max_leaf_nodes
gamma[默认0]
max_delta_step[默认0]
subsample[默认1]
colsample_bytree[默认1]
colsample_bylevel[默认1]
lambda[默认1]
alpha[默认1]
scale_pos_weight[默认1]
学习目标参数
这个参数用来控制理想的优化目标和每一步结果的度量方法。
objective[默认reg:linear]
这个参数定义需要被最小化的损失函数。最常用的值有:
binary:logistic 二分类的逻辑回归,返回预测的概率(不是类别)。
multi:softmax 使用softmax的多分类器,返回预测的类别(不是概率)。
在这种情况下,你还需要多设一个参数:num_class(类别数目)。
multi:softprob 和multi:softmax参数一样,但是返回的是每个数据属于各个类别的概率。
eval_metric[默认值取决于objective参数的取值]
对于有效数据的度量方法。
对于回归问题,默认值是rmse,对于分类问题,默认值是error。
典型值有:
rmse 均方根误差
mae 平均绝对误差
logloss 负对数似然函数值
二分类错误率(阈值为0.5)
merror 多分类错误率
mlogloss 多分类logloss损失函数
auc 曲线下面积
seed(默认0)
随机数的种子
设置它可以复现随机数据的结果,也可以用于调整参数
如果你之前用的是Scikit-learn,你可能不太熟悉这些参数。但是有个好消息,python的XGBoost模块有一个sklearn包,XGBClassifier。这个包中的参数是按sklearn风格命名的。会改变的函数名是:
调优步骤
我们会使用和GBM中相似的方法。需要进行如下步骤:
选择较高的学习速率(learning rate)。一般情况下,学习速率的值为0.1。但是,对于不同的问题,理想的学习速率有时候会在0.05到0.3之间波动。选择对应于此学习速率的理想决策树数量。XGBoost有一个很有用的函数“cv”,这个函数可以在每一次迭代中使用交叉验证,并返回理想的决策树数量。
对于给定的学习速率和决策树数量,进行决策树特定参数调优(max_depth, min_child_weight, gamma, subsample, colsample_bytree)。在确定一棵树的过程中,我们可以选择不同的参数,待会儿我会举例说明。
xgboost的正则化参数的调优。(lambda, alpha)。这些参数可以降低模型的复杂度,从而提高模型的表现。
降低学习速率,确定理想参数。
import xgboost as xgb
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score,regression
X =....
y =....
train_X, valid_X, train_y, valid_y = train_test_split(X, y, test_size=0.333, random_state=2019) # 分训练集和验证集
regre= xgb.XGBRegressor(max_depth=10,
learning_rate=0.01,
n_estimators=2000,
silent=True,
objective='reg:squarederror',
nthread=-1,
gamma=0,
min_child_weight=1,
max_delta_step=0,
subsample=0.85,
colsample_bytree=0.7,
colsample_bylevel=1,
reg_alpha=0,
reg_lambda=1,
scale_pos_weight=1,
seed=2019,
missing=None)
regre.fit(train_X, train_y, eval_metric='r2', verbose=True, eval_set=[(valid_X, valid_y)], early_stopping_rounds=30)
# 这个verbose主要是调节系统输出的,如果设置成10,便是每迭代10次就有输出。
# 注意我们这里eval_metric=‘error’便是准确率。这里面并没有accuracy命名的函数,网上大多例子为auc,我这里特意放了个error。 xgboost没有直接使用效果最好的树作为模型的机制,这里采用最大树深限制的方法,目的是获取刚刚early_stopping效果最好的,实测性能可以
y_pred = xlf.predict(valid_X, ntree_limit=regre.best_ntree_limit)
auc_score = r2_score(valid_y, y_pred)# 计算R^2
这是一种调参手段;穷举搜索:在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果。其原理就像是在数组里找最大值。(为什么叫网格搜索?以有两个参数的模型为例,参数a有3种可能,参数b有4种可能,把所有可能性列出来,可以表示成一个3*4的表格,其中每个cell就是一个网格,循环过程就像是在每个网格里遍历、搜索,所以叫grid search)
其实这个就跟我们常用的遍历是一样的。建议大家使用sklearn里面的GridSearch函数,简洁速度快。
parameters = {
'max_depth': [5, 10, 15, 20, 25],
'learning_rate': [0.01, 0.02, 0.05, 0.1, 0.15],
'n_estimators': [500, 1000, 2000, 3000, 5000],
'min_child_weight': [0, 2, 5, 10, 20],
'max_delta_step': [0, 0.2, 0.6, 1, 2],
'subsample': [0.6, 0.7, 0.8, 0.85, 0.95],
'colsample_bytree': [0.5, 0.6, 0.7, 0.8, 0.9],
'reg_alpha': [0, 0.25, 0.5, 0.75, 1],
'reg_lambda': [0.2, 0.4, 0.6, 0.8, 1],
'scale_pos_weight': [0.2, 0.4, 0.6, 0.8, 1]
}
regre = xgb.XGBRegressor(max_depth=10,
learning_rate=0.01,
n_estimators=2000,
silent=True,
objective='reg:squarederror',
nthread=-1,
gamma=0,
min_child_weight=1,
max_delta_step=0,
subsample=0.85,
colsample_bytree=0.7,
colsample_bylevel=1,
reg_alpha=0,
reg_lambda=1,
scale_pos_weight=1,
seed=1440,
missing=None)
# 有了gridsearch我们便不需要fit函数
gsearchCV = GridSearchCV(regre, param_grid=parameters, scoring='r2', cv=3)
gsearchCV.fit(train_X, train_y)
print("Best score: %0.3f" % gsearchCV.best_score_)
print("Best parameters set:")
best_parameters = gsearchCV.best_estimator_.get_params()
for param_name in sorted(parameters.keys()):
print("\t%s: %r" % (param_name, best_parameters[param_name]))
This is an open source AI organization from China. Welcome friends who are interested in AI to join.
QQ Group: 584399282
Github:https://github.com/opensourceai
如有侵权,请发送邮箱至[email protected]