XGBoost学习笔记
来源:互联网 发布:圆周率网络 编辑:程序博客网 时间:2024/06/06 19:07
XGBoost是Kaggle上非常火的一种模型,很多项目用它拿到了第一。
python库安装
python的pip上还没有1,mac上略有麻烦,参见Installing XGBoost on Mac OSX
Mac上,CC, CXX的version应该是7
export CC = gcc-7export CXX = g++-7
参数的说明
对于xgboost,有很多参数可以设置,这些参数的详细说明在这里,有几个重要的如下:
- 一般参数,设置选择哪个booster算法
- booster: 可以选择gbtree,dart和gblinear。gbtree, dart使用基于树的模型进行提升计算,gblinear使用线性模型进行提升计算。缺省值为gbtree
- silent: 取0时表示打印出运行时信息,取1时表示以缄默方式运行,不打印运行时信息。缺省值为0
- nthread: XGBoost运行时的线程数。缺省值是当前系统可以获得的最大线程数
- num_pbuffer: 预测缓冲区大小,通常设置为训练实例的数目。缓冲用于保存最后一步提升的预测结果,无需人为设置。
- num_feature: Boosting过程中用到的特征维数,设置为特征个数。XGBoost会自动设置,无需人为设置。
使用的booster算法的参数
gbtree参数设置
- eta(学习率): 为了防止过拟合,更新过程中用到的收缩步长。在每次提升计算之后,算法会直接获得新特征的权重。 eta通过缩减特征的权重使提升计算过程更加保守。缺省值为0.3。取值范围为:[0,1] 在 Scikit-Learn中,这个参数名是learning_rate
- gamma(最小扩展损失): 决定树的节点是否扩展为区域的最小损失。如多一个节点split的时候,对于loss function带来的降低量大于gamma时,则进行split。值越大,算法越保守。==需要调参==。缺省值是0,取值范围是[0,∞]
- max_depth:树的深度,越大模型越复杂,也越可能过拟合。0表示没限制,默认值是6。==需要调参==,一般在3到10之间。
- min_child_weight: 子节点中最小的样本权重和。如果一个叶子节点的样本权重和小于min_child_weight则拆分过程结束。在现行回归模型中,这个参数是指建立每个模型所需要的最小样本数。值越大,算法越保守conservative,但太大会导致模型欠拟合,==需要调参==。默认值是1,取值范围为:[0,∞]
- max_delta_step: 我们允许每个树的权重被估计的最大值。如果它的值被设置为0,意味着没有约束;如果它被设置为一个正值,它能够使得更新的步骤更加保守。通常无需设置该参数,但是如果在逻辑回归中极其不平衡时它可能会有帮助。把它范围设置为1-10之间也许能控制更新。默认值是0,取值范围为:[0,∞]
- subsample: 用于训练模型的子样本占整个样本集合的比例。如果设置为0.5则意味着XGBoost将随机的从整个样本集合中随机的抽取出50%的子样本建立树模型,这能够防止过拟合,但取值太小可能欠拟合。一般在[0.5, 1]之间比较合适,允许的取值范围为:(0,1]
- colsample_bytree: 在建立树时对特征采样的比例。缺省值为1,取值范围为:(0,1]
- colsample_bylevel: 在建立树时,split时,对于每一层的特征采样比例。缺省值为1,取值范围为:(0,1]
- alpha: L1 正则的惩罚系数,值越大越不容易过拟合,缺省值为0,增加这个值会让算法更保守。在 Scikit-Learn中,这个参数名是reg_alpha
- lambda: L2 正则的惩罚系数,值越大越不容易过拟合,缺省值为1,增加这个值会让算法更保守。在 Scikit-Learn中,这个参数名是reg_lambda
- scale_pos_weight: 当分类很不平衡的时候,把它设置为正值,可以加快收敛。默认值是1。
还有很多,感觉不是特别重要,就没写上来
学习任务的参数
objective: 定义学习目标,可选的目标函数如下:
- “reg:linear” —— 线性回归。
- “reg:logistic”—— 逻辑回归。
- “binary:logistic”—— 二分类的逻辑回归问题,输出为概率。
- “binary:logitraw”—— 二分类的逻辑回归问题,输出的结果为逻辑变换前的分值。
- “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的向量,可以将该向量reshape成ndata行nclass列的矩阵。每行数据表示样本所属于每个类别的概率。
- “rank:pairwise” –设置XGBoost使用最小化pairwise损失做排名。
- “reg:gamma”
- “reg:tweedie”
base_score: 所有实例的初始化预测分数,全局的偏差值; 只要经历足够多的迭代次数,这个值对最终结果将不会有太大的影响。初始化为0.5
eval_metric: 校验数据所需要的评价指标,不同的目标函数将会有缺省的评价指标(rmse for regression, and error for classification, mean average precision for ranking),用户可以添加多种评价指标,对于Python用户要以list传递参数对给程序,而不是dict,否则后面的参数会覆盖之前。参数选择有
- rmse: root mean square error
- mae: mean absolute error
- logloss: negative log-likelihood
- error: Binary classification error rate (超过 0.5 threshold,认为是positive),就是
wrong casesall cases - error@t
- merror: Multiclass classification error rate
- mlogloss: Multiclass logloss
- auc: Area under the curve
- ndcg: normalized discounted cumulative gain
- map: mean average precision
- ndcg@n, map@n
- “ndcg-“,”map-“,”ndcg@n-“,”map@n-”
seed: 随机数的种子。缺省值为0
- num_round: boosting的轮数
- save_period: 保存模型中间模型,如果是0,则只保存最终模型
命令行参数
参数的优化
调参
可以使用hyperopt来遍历查找合适的参数配置。参见Hyperopt的使用
传统的方式可以通过 sklearn.model_selection 下面的 GridSearchCV 和 RandomizedSearchCV
- GridSearchCV: paramters 有对应的list,然后就是笛卡尔积的遍历。所有的组合都会遍历,所以这个特别慢!
cv = StratifiedKFold(y, n_folds=10, shuffle=True, random_state=seed)# 变量params_grid = { 'max_depth': [1, 2, 3], 'n_estimators': [5, 10, 25, 50], 'learning_rate': np.linspace(1e-16, 1, 3)}# 不变量params_fixed = { 'objective': 'binary:logistic', 'silent': 1}bst_grid = GridSearchCV( estimator=XGBClassifier(**params_fixed, seed=seed), param_grid=params_grid, cv=cv, scoring='accuracy')# 训练,漫长的等待bst_grid.fit(X, y)# 得到最佳参数print(bst_grid.best_params_.items())
- RandomizedSearchCV: paramters 有对应的list,然后随机取数,最多试指定的次数(n_iter)就结束。
# 随机的范围params_dist_grid = { 'max_depth': [1, 2, 3, 4], 'gamma': [0, 0.5, 1], 'n_estimators': randint(1, 1001), # uniform discrete random distribution 'learning_rate': uniform(), # gaussian distribution 'subsample': uniform(), # gaussian distribution 'colsample_bytree': uniform() # gaussian distribution}# 与 GridSearchCV 类似rs_grid = RandomizedSearchCV( estimator=XGBClassifier(**params_fixed, seed=seed), param_distributions=params_dist_grid, n_iter=10, cv=cv, scoring='accuracy', random_state=seed)rs_grid.fit(X, y)# 得到最佳参数print(rs_grid.best_params_)
Feature的预处理
对于xgboost,不需要做 feature 的 normalization。
如果存在某些训练数据数值缺失,换言之,提供的是sparse feature matrix,xgboost也能处理好。不过,gblinear booster把missing values设置为0,安全起见,missing values 一开始都设置为 np.nan 吧。
模型训练后,可以通过实例的 get_fscore() 知道哪些feature比较重要,或者 xgb.plot_importance(bst)
[bst为训练好的实例]
拟合度调优
使用 early_stopping_rounds 防止过拟合
为了防止过拟合,fit 函数有一个 early_stopping_rounds 的参数,表示当模型训练 early_stopping_rounds 轮之后,模型的 loss 并没有变优,则停止训练过程。
# 采用error作为loss functionparams['eval_metric'] = 'error'num_rounds = 1500bst = xgb.train(params, dtrain, num_rounds, watchlist, early_stopping_rounds=10)
需要注意到是,上面例子中的bst返回的是最后一天iteration,而不是最佳匹配的那个。 需要用 bst.best_ntree_limit 获取正确的值
调整合适的 n_estimators 数量
当 n_estimators 数量太大的时候,容易产生过拟合。这时,可以通过测试集的匹配程度来找到合适的值。
以下内容参考之 http://education.parrotprediction.teachable.com/courses/78878/lectures/1137866
先使用 cross_validation 来划分测试集合与训练集合
cv = StratifiedKFold(y, n_folds=10, shuffle=True, random_state=seed)
定义 estimator 的数量列表,这里是1到200,10为步长的正整数。然后通过 validation_curve 得到所有的情况下的训练得分与测试得分。
default_params = { 'objective': 'binary:logistic', 'max_depth': 1, 'learning_rate': 0.3, 'silent': 1.0}# 定义了列表 n_estimators_range = np.linspace(1, 200, 10).astype('int')train_scores, test_scores = validation_curve( XGBClassifier(**default_params), X, y, param_name = 'n_estimators', param_range = n_estimators_range, cv=cv, scoring='accuracy')
假设这些数值属于正态分布,那么可以得到测试集合结果与训练集合结果的平均值和标准偏差
σ ,通过绘图看它们的曲线情况。看elbow的拐弯点在什么地方。同时,测试集结果最好的情况是在什么地方。train_scores_mean = np.mean(train_scores, axis=1)train_scores_std = np.std(train_scores, axis=1)test_scores_mean = np.mean(test_scores, axis=1)test_scores_std = np.std(test_scores, axis=1)fig = plt.figure(figsize=(10, 6), dpi=100)plt.title("Validation Curve with XGBoost (eta = 0.3)")plt.xlabel("number of trees")plt.ylabel("Accuracy")plt.ylim(0.7, 1.1)plt.plot(n_estimators_range, train_scores_mean, label="Training score", color="r")plt.plot(n_estimators_range, test_scores_mean, label="Cross-validation score", color="g")plt.fill_between(n_estimators_range, train_scores_mean - train_scores_std, train_scores_mean + train_scores_std, alpha=0.2, color="r")plt.fill_between(n_estimators_range, test_scores_mean - test_scores_std, test_scores_mean + test_scores_std, alpha=0.2, color="g")plt.axhline(y=1, color='k', ls='dashed')plt.legend(loc="best")plt.show()i = np.argmax(test_scores_mean)print("Best cross-validation result ({0:.2f}) obtained for {1} trees".format(test_scores_mean[i], n_estimators_range[i]))
获取到如下图,可以看到,elbow的拐点在25个estimator,同时,log显示89个estimator的时候,测试的mean最大,为0.90。所以,可以取一个权衡的值,比如,50个左右。
High Variance(过拟合)的处理方式
- 减少树的最大深度 max_depth
- 增加 min_child_weight 的值
- 增加 gamma 的值
- 对
subsample
,colsample_bytree
采用随机值,即不用默认1 - 增加
lambda
和alpha
High Bias(欠拟合)的处理方式
这个与 High Variance 的方式有些取反
- 增加树的最大深度 max_depth
- 减少 min_child_weight 的值
- 减少 gamma 的值
- 减少
lambda
和alpha
自定义 evaluation metric
自定义函数需要接收两个参数,预测的可能性与训练的数据。另,xgb.train 里面需要指定maximize的值,它如果是 False ,表示自定义函数返回的值越小越好,否则就是 True。
def misclassified(pred_probs, dtrain): labels = dtrain.get_label() # obtain true labels preds = pred_probs > 0.5 # obtain predicted values return 'misclassified', np.sum(labels != preds)watchlist = [(dtest,'test'), (dtrain,'train')]# 因为 eval_metric 的默认参数是 error ,pred_probs > 0.5 是error比较多,故这个sum希望越小越好,maximize 设置为 False bst = xgb.train(params, dtrain, num_rounds, watchlist, feval=misclassified, maximize=False)
也可以通过定义一个空的dict,保存每次训练的loss返回值
evals_result = {}bst = xgb.train(params, dtrain, num_rounds, watchlist, feval=misclassified, maximize=False, evals_result=evals_result)print(evals_result)
处理失衡的数据集
对于classification类问题,假设有2种分类,90%的数据是分类1,10%的数据是分类2,这就是原始数据失衡。它会导致预测在测试集上看起来accuracy很高(但是recall会比较低),但实际上对于分类1可能过拟合,对于分类2可能欠拟合。对于这些问题,一般处理的策略有
- 收集更多的数据
- 使用更好的衡量函数,而不是默认的 error,比如 AUC,
F1 Score, Kappa 等 - 增加(oversampling) 数据量少的分类的数据,减少(undersampling) 数据量多的分类的数据
- python 可以采用类库imbalanced-learn来实现
对于xgboost算法,同时可以有如下做法:
- 将 min_child_weight 设置得小一点,这样分类2可以有多一些节点
- 初始化 DMatrix 时,对分类2的数据设置更高的权重
- 通过 scale_pos_weight 控制平衡
- 使用 AUC 来衡量最后结果
DMatrix的权重设置
可以根据分类的值,假设分类2的值是1,分类1的值是0,如下方式可以提高分类2的权重
weights = np.zeros(len(y_train))weights[y_train == 0] = 1 # 分类1weights[y_train == 1] = 5 # 分类2# 分类2的权重是分类1的5倍dtrain = xgb.DMatrix(X_train, label=y_train, weight=weights)dtest = xgb.DMatrix(X_test)
这样做,可以增加分类2的预测准确性,但是整体的accuracy和precision会降低,需要对weight放到多少调整到一个合适的值。
使用 scale_pos_weight 参数
思路就是如果分类1和2比例失调,那scale的比例取相同的值,以”纠正”这种失调
dtrain = xgb.DMatrix(X_train, label=y_train)dtest = xgb.DMatrix(X_test)train_labels = dtrain.get_label()# 失调的比例 分类1数量 / 分类2数量ratio = float(np.sum(train_labels == 0)) / np.sum(train_labels == 1)params['scale_pos_weight'] = ratiobst = xgb.train(params, dtrain, num_rounds)y_test_preds = (bst.predict(dtest) > 0.5).astype('int')pd.crosstab( pd.Series(y_test, name='Actual'), pd.Series(y_test_preds, name='Predicted'), margins=True)
scale_pos_weight的效果一般会比DMatrix权重效果好,注意的是,这个方法如果和DMatrix权重的方法一起用,需要小心配置参数,否则容易用力过猛,矫枉过正。
参考列表
- Practical XGBoost in Python
- 官方文档
- 接口的api定义
- 现在pip应该能安装了,直接
pip install xgboost
即可 ↩
- XGboost文献学习笔记
- XGBoost学习笔记
- 机器学习----xgboost学习笔记
- 学习笔记:XGBoost原理解析
- xgboost学习笔记(1):安装
- CSDN机器学习笔记十 Xgboost
- 决策树、CART、GBDT、Xgboost学习笔记
- xgboost笔记
- XGBoost笔记
- XGBoost笔记
- xgboost学习
- XGBoost学习
- XGBoost学习
- xgboost学习
- 王小草【机器学习】笔记--提升之XGBoost工具的应用
- 【R机器学习笔记】XGBoost——XGBboost包
- 笔记-GBDT&Xgboost
- XGBoost学习日记1
- AOJ 0118: Property Distribution (简单DFS)
- 爬虫Scrapy-避免被禁止
- ECharts属性设置
- jsp的include动作和forward动作遇到的问题
- 每天一道LeetCode-----找到给定数组的连续子数组,使这个子数组的和最大,要求复杂度为O(n)
- XGBoost学习笔记
- matlab中关于函数文件和脚本文件使用实例
- 关于linux下的定时
- centos 7 双网卡绑定配置
- Spring Boot 学习笔记(一)
- spring-cloud【Feign】
- Vue.js解析(一)【Vue.js响应式原理】
- Java开发规范
- 基于easyui 框架,通过读取json 文件实现省市区三联动的效果