XGBoost重要参数(调参使⽤)
XGBoost 重要参数(调参使⽤)
数据⽐赛Kaggle,天池中最常见的就是XGBoost和LightGBM。
模型是在数据⽐赛中尤为重要的,但是实际上,在⽐赛的过程中,⼤部分朋友在模型上花的时间却是相对较少的,⼤家都倾向于将宝贵的时间留在特征提取与模型融合这些⽅⾯。在实战中,我们会先做⼀个baseline的demo,尽可能快尽可能多的挖掘出模型的潜⼒,以便后期将精⼒花在特征和模型融合上。这⾥就需要⼀些调参功底。
本⽂从这两种模型的⼀共百余参数中选取重要的⼗余个进⾏探讨研究。并给⼤家展⽰快速轻量级的调参⽅式。当然,有更⾼⼀步要求的朋友,还是得戳和这两个官⽅⽂档链接。
XGBoost 的重要参数
XGBoost的参数⼀共分为三类:
1. 通⽤参数:宏观函数控制。
2. Booster参数:控制每⼀步的booster(tree/regression)。booster参数⼀般可以调控模型的效果和计算代价。我们所说的调参,很这是⼤
程度上都是在调整booster参数。
3. 学习⽬标参数:控制训练⽬标的表现。我们对于问题的划分主要体现在学习⽬标参数上。⽐如我们要做分类还是回归,做⼆分类还是
多分类,这都是⽬标参数所提供的。
通⽤参数
1. booster:我们有两种参数选择,gbtree和gblinear。gbtree是采⽤树的结构来运⾏数据,⽽gblinear是基于线性模型。
2. silent:静默模式,为1时模型运⾏不输出。
3. nthread: 使⽤线程数,⼀般我们设置成-1,使⽤所有线程。如果有需要,我们设置成多少就是⽤多少线程。
Booster参数
1. n_estimator: 也作num_boosting_rounds
这是⽣成的最⼤树的数⽬,也是最⼤的迭代次数。
2. learning_rate: 有时也叫作eta,系统默认值为0.3,。
每⼀步迭代的步长,很重要。太⼤了运⾏准确率不⾼,太⼩了运⾏速度慢。我们⼀般使⽤⽐默认值⼩⼀点,0.1左右就很好。
3. gamma:系统默认为0,我们也常⽤0。
在节点分裂时,只有分裂后损失函数的值下降了,才会分裂这个节点。gamma指定了节点分裂所需的最⼩损失函数下降值。这个参数的值越⼤,算法越保守。因为gamma值越⼤的时候,损失函数下降更多才可以分裂节点。所以树⽣成的时候更不容易分裂节点。范围: [0,∞]
4. subsample:系统默认为1。
这个参数控制对于每棵树,随机采样的⽐例。减⼩这个参数的值,算法会更加保守,避免过拟合。但是,如果这个值设置得过⼩,它可能会导致⽋拟合。典型值:0.5-1,0.5代表平均采样,防⽌过拟合. 范围: (0,1],注意不可取0
5. colsample_bytree:系统默认值为1。我们⼀般设置成0.8左右。
⽤来控制每棵随机采样的列数的占⽐(每⼀列是⼀个特征)。典型值:0.5-1范围: (0,1]
6. colsample_bylevel:默认为1,我们也设置为1.
这个就相⽐于前⼀个更加细致了,它指的是每棵树每次节点分裂的时候列采样的⽐例
7. max_depth:系统默认值为6
我们常⽤3-10之间的数字。这个值为树的最⼤深度。这个值是⽤来控制过拟合的。max_depth越⼤,模型学习的更加具体。设置为0代表没有限制,范围: [0,∞]
8. max_delta_step:默认0,我们常⽤0.
这个参数限制了每棵树权重改变的最⼤步长,如果这个参数的值为0,则意味着没有约束。如果他被赋
予了某⼀个正值,则是这个算法更加保守。通常,这个参数我们不需要设置,但是当个类别的样本极不平衡的时候,这个参数对逻辑回归优化器是很有帮助的。
9. lambda:也称reg_lambda,默认值为0。
权重的L2正则化项。(和Ridge regression类似)。这个参数是⽤来控制XGBoost的正则化部分的。这个参数在减少过拟合上很有帮助。
10. alpha:也称reg_alpha默认为0,
权重的L1正则化项。(和Lasso regression类似)。可以应⽤在很⾼维度的情况下,使得算法的速度更快。
11. scale_pos_weight:默认为1
在各类别样本⼗分不平衡时,把这个参数设定为⼀个正值,可以使算法更快收敛。通常可以将其设置为负样本的数⽬与正样本数⽬的⽐值。
学习⽬标参数
objective [缺省值=reg:linear]
reg:linear– 线性回归
reg:logistic – 逻辑回归
binary:logistic – ⼆分类逻辑回归,输出为概率
binary:logitraw – ⼆分类逻辑回归,输出的结果为wTx
count:poisson – 计数问题的poisson回归,输出结果为poisson分布。在poisson回归中,max_delta_step的缺省值为0.7 (used to
safeguard optimization)
multi:softmax – 设置 XGBoost 使⽤softmax⽬标函数做多分类,需要设置参数num_class(类别个数)
multi:softprob – 如同softmax,但是输出结果为ndata*nclass的向量,其中的值是每个数据分为每个类的概率。
eval_metric [缺省值=通过⽬标函数选择]
rmse: 均⽅根误差
mae: 平均绝对值误差
logloss: negative log-likelihood
error: ⼆分类错误率。其值通过错误分类数⽬与全部分类数⽬⽐值得到。对于预测,预测值⼤于0.5被认为是正类,其它归为负类。
error@t: 不同的划分阈值可以通过 ‘t’进⾏设置
merror: 多分类错误率,计算公式为(wrong cases)/(all cases)
mlogloss: 多分类log损失
auc: 曲线下的⾯积
ndcg: Normalized Discounted Cumulative Gain
map: 平均正确率
⼀般来说,我们都会使⽤ain(params, dtrain)函数来训练我们的模型。这⾥的params指的是booster参数。
两种基本的实例
我们要注意的是,在xgboost中想要进⾏⼆分类处理的时候,我们仅仅在objective中设置成binary,会发现输出仍然是⼀堆连续的值。这是因为它输出的是模型预测的所有概率中最⼤的那个值。我们可以后续对这些概率进⾏条件处理得到最终类别,或者直接调⽤xgboost中
的XGBClassifier()类,但这两种函数的写法不太⼀样。⼤家看我下⾯的例⼦。
from numpy import loadtxt
from xgboost import XGBClassifierround函数有几个参数
del_selection import train_test_split
ics import accuracy_score
# 导⼊数据
dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",")
# split data into X and y
X = dataset[:, 0:8]
Y = dataset[:, 8]
# split data into train and test sets
seed = 7
test_size = 0.33
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=test_size, random_state=seed)
# 设置参数
model = XGBClassifier(max_depth=15,
learning_rate=0.1,
n_estimators=2000,
min_child_weight=5,
max_delta_step=0,
subsample=0.8,
colsample_bytree=0.7,
reg_alpha=0,
reg_lambda=0.4,
scale_pos_weight=0.8,
silent=True,
objective='binary:logistic',
missing=None,
eval_metric='auc',
seed=1440,
gamma=0)
model.fit(X_train, y_train)
# 进⾏预测
y_pred = model.predict(X_test)
predictions = [round(value) for value in y_pred]
# 查看准确率
accuracy = accuracy_score(y_test, predictions)
print("Accuracy: %.2f%%" % (accuracy * 100.0))
以上是ain()写法,这是xgboost最原始的封装函数。这样训练我们预测输出的是⼀串连续值,是xgboost在这⼏个类别上概率最⼤的概率值。我们如果想要得到我们的分类结果,还需要进⾏其他操作。
幸运的是,xgboost为了贴合sklearn的使⽤,⽐如gridsearch这些实⽤⼯具,⼜开发了XGBoostClassifie
r()和XGBoostRegression()两个函数。可以更加简单快捷的进⾏分类和回归处理。注意xgboost的sklearn包没有feature_importance这个量度,但是get_fscore()函数有相同的功能。当然,为了和sklearn保持⼀致,写法也发⽣变化,具体请看下⾯代码:
import xgboost as xgb
del_selection import train_test_split
ics import roc_auc_score
from sklearn.datasets import load_breast_cancer
# ⼆分类解决乳腺癌
cancer = load_breast_cancer()
x = cancer.data
y = cancer.target
train_x, valid_x, train_y, valid_y = train_test_split(x, y, test_size=0.333, random_state=0) # 分训练集和
验证集
# 这⾥不需要Dmatrix
xlf = xgb.XGBClassifier(max_depth=10,
learning_rate=0.01,
n_estimators=2000,
silent=True,
objective='binary:logistic',
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)
xlf.fit(train_x, train_y, eval_metric='error', verbose=True, eval_set=[(valid_x, valid_y)], early_stopping_rounds=30)
# 这个verbose主要是调节系统输出的,如果设置成10,便是每迭代10次就有输出。
# 注意我们这⾥eval_metric=‘error’便是准确率。这⾥⾯并没有accuracy命名的函数,⽹上⼤多例⼦为auc,我这⾥特意放了个error。
y_pred = xlf.predict(valid_x, ntree_limit=xlf.best_ntree_limit)
auc_score = roc_auc_score(valid_y, y_pred)
y_pred = xlf.predict(valid_x, ntree_limit=xlf.best_ntree_limit)
# xgboost没有直接使⽤效果最好的树作为模型的机制,这⾥采⽤最⼤树深限制的⽅法,⽬的是获取刚刚early_stopping效果最好的,实测性能可以
auc_score = roc_auc_score(valid_y, y_pred) # 算⼀下预测结果的roc值
那么我们介绍了这么多,重点就来了:如何⼜快⼜好的调参?⾸先我们需要了解grid search是个什么原理。
GridSearch 简介
这是⼀种调参⼿段;穷举搜索:在所有候选的参数选择中,通过循环遍历,尝试每⼀种可能性,表现最
好的参数就是最终的结果。其原理就像是在数组⾥最⼤值。(为什么叫⽹格搜索?以有两个参数的模型为例,参数a有3种可能,参数b有4种可能,把所有可能性列出来,可以表⽰成⼀个3*4的表格,其中每个cell就是⼀个⽹格,循环过程就像是在每个⽹格⾥遍历、搜索,所以叫grid search)
其实这个就跟我们常⽤的遍历是⼀样的。建议⼤家使⽤sklearn⾥⾯的GridSearch函数,简洁速度快。
import xgboost as xgb
del_selection import train_test_split
from sklearn.datasets import load_breast_cancer
del_selection import GridSearchCV
cancer = load_breast_cancer()
x = cancer.data[:50]
y = cancer.target[:50]
train_x, valid_x, train_y, valid_y = train_test_split(x, y, test_size=0.333, random_state=0) # 分训练集和
验证集
# 这⾥不需要Dmatrix
parameters = {
'max_depth': [5, 10, 15, 20, 25],
'learning_rate': [0.01, 0.02, 0.05, 0.1, 0.15],
'n_estimators': [50, 100, 200, 300, 500],
'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]
}
xlf = xgb.XGBClassifier(max_depth=10,
learning_rate=0.01,
n_estimators=2000,
silent=True,
objective='binary:logistic',
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函数
gsearch = GridSearchCV(xlf, param_grid=parameters, scoring='accuracy', cv=3)
gsearch.fit(train_x, train_y)
print("Best score: %0.3f" % gsearch.best_score_)
print("Best parameters set:")
best_parameters = gsearch.best_estimator_.get_params()
for param_name in sorted(parameters.keys()):
print("\t%s: %r" % (param_name, best_parameters[param_name]))
#极其耗费时间,电脑没执⾏完
我们需要注意的是,Grid Search 需要交叉验证⽀持的。这⾥的cv=3,是个int数,就代表3-折验证。实际上cv可以是⼀个对象,也可以是其他类型。分别代表不同的⽅式验证。具体的⼤家可看下⾯这段表述。
Possible inputs for cv are:
None, to use the default 3-fold cross-validation,
integer, to specify the number of folds.
An object to be used as a cross-validation generator.
An iterable yielding train/test splits.
cv的可能输⼊包括:
None,使⽤默认的3倍交叉验证,
整数,⽤来指定折叠的次数。
⽤作交叉验证⽣成器的对象。
⼀个可迭代的训练/测试序列进⾏分割。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论