💡专注R语言在🩺生物医学中的使用
设为“星标”,精彩不错过
xgboost(Extreme Gradient Boosting),极限梯度提升,是基于梯度提升树(gradient boosting decision tree,GBDT)实现的集成(ensemble)算法,本质上还是一种提升(boosting)算法,但是把速度和效率提升到最强,所以加了Extreme。XGBoost是陈天奇等人开源的一个机器学习项目,CatBoost和XGBoost、LightGBM并称为GBDT的三大主流神器,都是在GBDT算法框架下的一种改进实现。
xgboost的一些特性包括:
速度快效率高:默认会借助OpenMP进行并行计算核心代码使用C++实现,速度快,易分享;正则化:可以使用正则化技术避免过度拟合;交叉验证:内部会进行交叉验证;缺失值处理:可以处理缺失值,不需要提前插补;适用于多种任务类型:支持回归分类排序等,还支持用户自定义的目标函数;关于更多它的背景知识,建议大家自己学习,我们看看它在R语言中的实现。
本文目录:
准备数据
拟合模型
预测
控制输出日志
变量重要性
查看树的信息
保存加载模型
参考资料
准备数据先用自带数据演示一下简单的使用方法。
首先是加载数据,这是一个二分类数据,其中label是结果变量,使用0和1表示,其余是预测变量。
library(xgboost)rm(list = ls())# load datadata(agaricus.train, package='xgboost')data(agaricus.test, package='xgboost')train <- agaricus.traintest <- agaricus.teststr(train)## List of 2## $ data :Formal class 'dgCMatrix' [package "Matrix"] with 6 slots## .. ..@ i : int [1:143286] 2 6 8 11 18 20 21 24 28 32 ...## .. ..@ p : int [1:127] 0 369 372 3306 5845 6489 6513 8380 8384 10991 ...## .. ..@ Dim : int [1:2] 6513 126## .. ..@ Dimnames:List of 2## .. .. ..$ : NULL## .. .. ..$ : chr [1:126] "cap-shape=bell" "cap-shape=conical" "cap-shape=convex" "cap-shape=flat" ...## .. ..@ x : num [1:143286] 1 1 1 1 1 1 1 1 1 1 ...## .. ..@ factors : list()## $ label: num [1:6513] 1 0 0 1 0 0 0 1 0 0 ...str(test)## List of 2## $ data :Formal class 'dgCMatrix' [package "Matrix"] with 6 slots## .. ..@ i : int [1:35442] 0 2 7 11 13 16 20 22 27 31 ...## .. ..@ p : int [1:127] 0 83 84 806 1419 1603 1611 2064 2064 2701 ...## .. ..@ Dim : int [1:2] 1611 126## .. ..@ Dimnames:List of 2## .. .. ..$ : NULL## .. .. ..$ : chr [1:126] "cap-shape=bell" "cap-shape=conical" "cap-shape=convex" "cap-shape=flat" ...## .. ..@ x : num [1:35442] 1 1 1 1 1 1 1 1 1 1 ...## .. ..@ factors : list()## $ label: num [1:1611] 0 1 0 0 0 0 1 0 1 0 ...class(train$data)## [1] "dgCMatrix"## attr(,"package")## [1] "Matrix"
xgboost对数据格式是有要求的,可以看到train和test都是列表,其中包含了预测变量data和结果变量label,其中label是使用0和1表示的。data部分是稀疏矩阵的形式(dgCMatrix)。
# 查看数据维度,6513行,126列dim(train$data)## [1] 6513 126table(train$label)## ## 0 1 ## 3373 3140拟合模型
接下来就是使用训练数据拟合模型:
model <- xgboost(data = train$data, label = train$label, max.depth = 2, # 树的最大深度 eta = 1, # 学习率 nrounds = 2, nthread = 2, # 使用的CPU线程数 objective = "binary:logistic")## [1] train-logloss:0.233376 ## [2] train-logloss:0.136658
其中的参数nround在这里表示最终模型中树的数量,objective是目标函数。
除了使用列表传入数据,也支持R语言中的密集矩阵(matrix),比如:
model <- xgboost(data = as.matrix(train$data), label = train$label, max.depth = 2, eta = 1, nrounds = 2, nthread = 2, objective = "binary:logistic")
## [1] train-logloss:0.233376 ## [2] train-logloss:0.136658
开发者最推荐的格式还是特别为xgboost设计的xgb.DMatrix格式。
# 建立xgb.DMatrixdtrain <- xgb.DMatrix(data = train$data, label = train$label)xx <- xgboost(data = dtrain, # 这样就不用单独传入label了 max.depth = 2, eta = 1, nrounds = 2, nthread = 2, objective = "binary:logistic" )
## [1] train-logloss:0.233376 ## [2] train-logloss:0.136658
这个格式也是xgboost特别设计的,有助于更好更快的进行计算,还可以支持更多的信息传入。可以通过getinfo获取其中的元素:
head(getinfo(dtrain, "label"))
## [1] 1 0 0 1 0 0预测
拟合模型后,就可以对新数据进行预测了:
# predictpred <- predict(model, test$data)head(pred)## [1] 0.28583017 0.92392391 0.28583017 0.28583017 0.05169873 0.92392391range(pred)## [1] 0.01072847 0.92392391
我们的任务是一个二分类的,但是xgboost的预测结果是概率,并不是直接的类别。我们需要自己转换一下,比如规定概率大于0.5就是类别1,小于等于0.5就是类别0(这其实也可以当做超参数调整的)。
pred_label <- ifelse(pred > 0.5,1,0)table(pred_label)## pred_label## 0 1 ## 826 785# 混淆矩阵table(test$label, pred_label)## pred_label## 0 1## 0 813 22## 1 13 763
全对,准确率100%。
除此之外还提供一个xgb.cv()用于实现交叉验证的建模,使用方法与xgboost()一致:
cv.res <- xgb.cv(data = train$data, label = train$label, nrounds = 2, objective = "binary:logistic", nfold = 10 # 交叉验证的折数 )## [1] train-logloss:0.439723+0.000182 test-logloss:0.439976+0.000908 ## [2] train-logloss:0.299610+0.000125 test-logloss:0.299913+0.001478
min(cv.res$evaluation_log)
## [1] 0.0001254714控制输出日志
xgboost()和xgb.train()有参数verbose可以控制输出日志的多少,默认是verbose = 1,输出性能指标结果。xgboost()是xgb.train()的简单封装,xgb.train()是训练xgboost模型的高级接口。
如果是0,则是没有任何输出:
xx <- xgboost(data = train$data, label = train$label, objective = "binary:logistic" ,nrounds = 2 ,verbose = 0 )
如果是2,会输出性能指标结果和其他信息(这里没显示):
xx <- xgboost(data = train$data, label = train$label, objective = "binary:logistic" ,nrounds = 2 ,verbose = 2 )
## [1] train-logloss:0.439409 ## [2] train-logloss:0.299260
xgb.cv()的verbose参数只有TRUE和FALSE。
变量重要性xgboost中变量的重要性是这样计算的:
我们如何在xgboost中定义特性的重要性?在xgboost中,每次分割都试图找到最佳特征和分割点(splitting point)来优化目标。我们可以计算每个节点上的增益,它是所选特征的贡献。最后,我们对所有的树进行研究,总结每个特征的贡献,并将其视为重要性。如果特征的数量很大,我们也可以在绘制图之前对特征进行聚类。
查看变量重要性:
importance_matrix <- xgb.importance(model = model)importance_matrix
## Feature Gain Cover Frequency## 1: odor=none 0.67615470 0.4978746 0.4## 2: stalk-root=club 0.17135376 0.1920543 0.2## 3: stalk-root=rooted 0.12317236 0.1638750 0.2## 4: spore-print-color=green 0.02931918 0.1461960 0.2
可视化变量重要性:
xgb.plot.importance(importance_matrix)
图片
plot of chunk unnamed-chunk-14或者ggplot2版本:
xgb.ggplot.importance(importance_matrix)
图片
查看树的信息可以把学习好的树打印出来,查看具体情况:
xgb.dump(model, with_stats = T)
## [1] "booster[0]" ## [2] "0:[f28<0.5] yes=1,no=2,missing=1,gain=4000.53101,cover=1628.25" ## [3] "1:[f55<0.5] yes=3,no=4,missing=3,gain=1158.21204,cover=924.5" ## [4] "3:leaf=1.71217716,cover=812" ## [5] "4:leaf=-1.70044053,cover=112.5" ## [6] "2:[f108<0.5] yes=5,no=6,missing=5,gain=198.173828,cover=703.75" ## [7] "5:leaf=-1.94070864,cover=690.5" ## [8] "6:leaf=1.85964918,cover=13.25" ## [9] "booster[1]" ## [10] "0:[f59<0.5] yes=1,no=2,missing=1,gain=832.544983,cover=788.852051"## [11] "1:[f28<0.5] yes=3,no=4,missing=3,gain=569.725098,cover=768.389709"## [12] "3:leaf=0.78471756,cover=458.936859" ## [13] "4:leaf=-0.968530357,cover=309.45282" ## [14] "2:leaf=-6.23624468,cover=20.462389"
还可以可视化树:
xgb.plot.tree(model = model)
图片
这个图展示了2棵树的分支过程,因为我们设置了nround=2,所以结果就是只有2棵树。
如果树的数量非常多的时候,这样每棵树看过来并不是很直观,通常xgboost虽然不如随机森林需要的树多,但是几十棵总是要的,所以xgboost提供了一种能把所有的树结合在一起展示的方法。
# 多棵树展示在一起xgb.plot.multi.trees(model = model,fill=TRUE)
图片
这幅图就是把上面那张图的信息整合到了一起,大家仔细对比下图中的数字就会发现信息是一样的哦。
除了以上方法可以检查树的信息外,还可以通过查看树的深度来检查树的结构。
bst <- xgboost(data = train$data, label = train$label, max.depth = 15, eta = 1, nthread = 2, nround = 30, objective = "binary:logistic", min_child_weight = 50,verbose = 0)xgb.plot.deepness(model = bst)
图片
plot of chunk unnamed-chunk-19这两幅图的横坐标都是树的深度,上面的图纵坐标是叶子的数量,展示了每层深度中的叶子数量。下面的图纵坐标是每片叶子的归一化之后的加权覆盖。
从图中可以看出树的深度在5之后,叶子的数量就很少了,这提示我们为了防止过拟合,可以把树的深度控制在5以内。
保存加载模型保存加载训练好的模型:
# 保存xgb.save(model, "xgboost.model")# 加载xgb.load("xgboost.model")aa <- predict(model, test$data)
在R语言中除了直接使用xgboost这个R包实现之外,还有许多综合性的R包都可以实现xgboost算法,并支持超参数调优等更多任务,比如caret、tidymodels、mlr3。
参考资料官方文档:https://xgboost.readthedocs.io/en/latest/R-package/xgboostPresentation.htmlhttps://www.r-bloggers.com/2016/03/an-introduction-to-xgboost-r-package/联系我们,关注我们
免费QQ交流群1:613637742(已满)免费QQ交流群2:608720452公众号消息界面关于作者获取联系方式知乎、CSDN、简书同名账号哔哩哔哩:阿越就是我 本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报。