XGBoost R 教程 1:介绍 XGBoost 在 R 中的使用

「写在前面」

学习一个软件最好的方法就是啃它的官方文档。本着自己学习、分享他人的态度,分享官方文档的中文教程。软件可能随时更新,建议配合官方文档一起阅读。


目录

  • 1 介绍
  • 2 安装
  • 3 学习
  • 4 使用 XGBoost 进行基础训练
  • 5 使用 XGBoost 进行基础预测
  • 6 高级功能

官网教程:https://xgboost.readthedocs.io/en/stable/R-package/xgboostPresentation.html

1 介绍

「XGBoost」 是 e「X」treme 「G」radient 「Boost」ing package 的简称.

这一小节的目的是向您展示如何使用 「XGBoost」 来构建模型和进行预测。

它是由 @friedman2000additive 和 @friedman2001greedy 实现的梯度增强框架的高效且可扩展的实现。包括两个解算器:

  • linear model;
  • tree learning algorithm.

它支持各种目标函数,包括 regression、classification、ranking。该软件包具有可扩展性,因此用户也可以轻松定义自己的目标函数。

它已被用于赢得多项 Kaggle 比赛。

它有几个特点:

  • 「速度」:它可以使用 OpenMP 在 Windows 和 Linux 上自动进行并行计算。它通常比经典的 gbm 快 10 倍以上。
  • 「输入类型」:它需要几种类型的输入数据:
    • Dense Matrix: R 的稠密矩阵,即 matrix
    • Sparse Matrix: R 的稀疏矩阵,即 Matrix::dgCMatrix
    • Data File: 本地数据文件;
    • xgb.DMatrix: 它自己的类(推荐)。
  • 「稀疏性」:它接受 tree booster 和 linear booster 的稀疏输入,并针对稀疏输入进行了优化;
  • 「自定义」:支持自定义目标函数和评价函数。

2 安装

GitHub version

对于每周更新的版本(强烈推荐),从 GitHub 安装:

install.packages("drat", repos="https://cran.rstudio.com")
drat:::addRepo("dmlc")
install.packages("xgboost", repos="http://dmlc.ml/drat/", type = "source")

Windows 用户需要先安装 Rtools

CRAN version

下面代码安装的是 CRAN 上的 1.7.5.1 版本:

install.packages("xgboost", version = "1.7.5.1")

以前可用的版本可以从 CRAN archive 中获得

3 学习

出于本教程的目的,我们将加载 「XGBoost」 包。

require(xgboost)

数据集介绍

在这个例子中,我们的目标是预测蘑菇是否可以吃(就像在许多教程中一样,示例数据与您将在日常生活中使用的相同:-)。

Mushroom 数据引用自 UCI Machine Learning Repository. @Bache+Lichman:2013.

数据集加载

我们将加载包中嵌入的 agaricus 数据集,并将它们链接到变量。

数据集已经拆分为:

  • train: 将用于构建模型;
  • test: 将用于评估我们模型的质量。

为什么将数据集分成两部分?

在第一部分中,我们将构建我们的模型。在第二部分中,我们将要对其进行测试并评估其质量。在不划分数据集的情况下,我们将在算法已经看到的数据上测试模型。

data(agaricus.train, package='xgboost')
data(agaricus.test, package='xgboost')
train <- agaricus.train
test <- agaricus.test

在现实世界中,由您来划分训 traintest 数据。执行此操作的方法超出了本文的范围,但是 caret 包可能会有所帮助。

每个变量都是一个包含两件事的 listlabeldata

str(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 ...

label 是我们数据集的结果,这意味着它是我们将尝试预测的 binary classification。

让我们发现数据集的维度。

dim(train$data)
## [1] 6513 126
dim(test$data)
## [1] 1611 126

这个数据集非常小,不会让 R 包太重,但是 XGBoost 的构建是为了非常有效地管理巨大的数据集。

如下所示,data 存储在 dgCMatrix 中,它是一个稀疏矩阵,label 向量是一个 numeric 向量 ({0,1}):

class(train$data)[1]
## [1] "dgCMatrix"
class(train$label)
## [1] "numeric"

4 使用 XGBoost 进行基础训练

这一步是我们模型质量过程中最关键的部分。

基础训练

我们正在使用 train 数据。如上所述,datalabel 都存储在 list 中。

在稀疏矩阵中,包含 0 的单元格不存储在内存中。因此,在主要由 0 组成的数据集中,内存大小会减少。拥有这样的数据集是很常见的。

我们将使用以下参数训练 decision tree model:

  • objective = "binary:logistic": 我们将训练一个 binary classification model;
  • max.depth = 2: trees 不会很深,因为我们的案例很简单;
  • nthread = 2: 我们将要使用的 CPU 线程数;
  • nrounds = 2: 将对数据进行两次传递,第二次传递将通过进一步减少 ground truth 和 prediction 之间的差异来增强模型。
bstSparse <- xgboost(data = train$data, 
label = train$label,
max.depth = 2,
eta = 1,
nthread = 2,
nrounds = 2,
objective = "binary:logistic")

您的特征和 label 之间的关系越复杂,您需要的遍数就越多。

参数变化

Dense matrix

或者,您可以将数据集放在一个 dense matrix 中,即一个基本的 R 矩阵。

bstDense <- xgboost(data = as.matrix(train$data), label = train$label, max.depth = 2, eta = 1, nthread = 2, nrounds = 2, objective = "binary:logistic")
xgb.DMatrix

XGBoost 提供了一种将它们分组在一个 xgb.DMatrix 中的方法。您甚至可以在其中添加其他 meta data。这对于我们稍后会发现的最高级功能很有用。

dtrain <- xgb.DMatrix(data = train$data, label = train$label)
bstDMatrix <- xgboost(data = dtrain, max.depth = 2, eta = 1, nthread = 2, nrounds = 2, objective = "binary:logistic")

verbose 选项

XGBoost 有几个功能可以帮助您在内部查看学习进度。目的是帮助您设置最佳参数,这是模型质量的关键。

查看训练进度的最简单方法之一是设置 verbose 选项(请参阅下文了解更高级的技术)。

# verbose = 0, no message
bst <- xgboost(data = dtrain, max.depth = 2, eta = 1, nthread = 2, nrounds = 2, objective = "binary:logistic", verbose = 0)
# verbose = 1, print evaluation metric
bst <- xgboost(data = dtrain, max.depth = 2, eta = 1, nthread = 2, nrounds = 2, objective = "binary:logistic", verbose = 1)
## [0] train-error:0.046522
## [1] train-error:0.022263
# verbose = 2, also print information about tree
bst <- xgboost(data = dtrain, max.depth = 2, eta = 1, nthread = 2, nrounds = 2, objective = "binary:logistic", verbose = 2)
## [11:41:01] amalgamation/../src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 6 extra nodes, 0 pruned nodes, max_depth=2
## [0] train-error:0.046522
## [11:41:01] amalgamation/../src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 4 extra nodes, 0 pruned nodes, max_depth=2
## [1] train-error:0.022263

5 使用 XGBoost 进行基础预测

执行预测

我们建立的模型的目的是对新数据进行分类。如前所述,我们将在此步骤中使用 test 数据集。

pred <- predict(bst, test$data)

# size of the prediction vector
print(length(pred))
## [1] 1611
# limit display of predictions to the first 10
print(head(pred))
## [1] 0.28583017 0.92392391 0.28583017 0.28583017 0.05169873 0.92392391

这些数字看起来不像 binary classification {0,1}。在能够使用这些结果之前,我们需要执行一个简单的转换。

将回归转换为二分类

XGBoost 做的唯一的事情就是回归。XGBoost 正在使用 label 向量来构建其回归模型。

我们如何使用回归模型来执行 binary classification?

如果我们考虑将回归应用于我们的数据的意义,我们得到的数字是数据被分类为 1 的概率。因此,我们将设置规则,如果特定数据的概率 > 0.5,则观察被分类为 1(否则为 0)。

prediction <- as.numeric(pred > 0.5)
print(head(prediction))
## [1] 0 1 0 0 0 1

测量模型性能

为了测量模型性能,我们将计算一个简单的指标,即平均误差。

err <- mean(as.numeric(pred > 0.5) != test$label)
print(paste("test-error=", err))
## [1] "test-error= 0.0217256362507759"

请注意,该算法在模型构建期间没有看到 test 数据。

步骤说明:

  1. as.numeric(pred > 0.5) 应用我们的规则,即当概率(<=> regression <=> prediction) > 0.5 时,观察值被分类为 1,否则为 0
  2. probabilityVectorPreviouslyComputed != test$label 计算真实数据和计算概率之间的误差向量;
  3. mean(vectorOfErrors) 计算平均误差本身。

最重要的是要记住,要进行分类,您只需对 label 进行回归,然后应用一个阈值。

Multiclass classification 以类似的方式工作。

这个指标是 0.02 并且非常低:我们的美味蘑菇模型运行良好!

6 高级功能

下面的大部分功能已经实现,以帮助您通过更好地理解模型的内容来改进模型。

数据集准备

对于以下高级功能,我们需要将数据放在 xgb.DMatrix 中,如上所述。

dtrain <- xgb.DMatrix(data = train$data, label=train$label)
dtest <- xgb.DMatrix(data = test$data, label=test$label)

使用 xgb.train 衡量学习进度

xgboost(simple) 和 xgb.train(advanced) 函数都可以训练模型。

xgb.train 的一个特殊功能是能够在每一轮之后跟踪学习进度。由于 boosting 的工作方式,有时轮次过多会导致过拟合。您可以将此功能视为交叉验证方法的近亲。以下技术将帮助您避免过拟合或优化学习时间以尽快停止它。

衡量模型学习进度的一种方法是向 XGBoost 提供第二个已经分类的数据集。因此它可以在第一个数据集上学习并在第二个数据集上测试它的模型。在学习过程中的每一轮之后都会测量一些指标。

在某种程度上,它类似于我们上面对平均误差所做的。主要区别在于上面是在构建模型之后,现在是在构建过程中我们测量错误。

出于本示例的目的,我们使用 watchlist 参数。它是 xgb.DMatrix 的列表,每个都标有名称。

watchlist <- list(train=dtrain, test=dtest)

bst <- xgb.train(data=dtrain, max.depth=2, eta=1, nthread = 2, nrounds=2, watchlist=watchlist, objective = "binary:logistic")
## [0] train-error:0.046522 test-error:0.042831
## [1] train-error:0.022263 test-error:0.021726

XGBoost 在每一轮都计算了上面看到的相同的平均误差指标(我们将 nrounds 设置为 2,这就是我们有两条线的原因)。显然,train-error 数与训练数据集(算法从中学习的数据集)有关,而test-error数与测试数据集有关。

训练和测试错误相关的指标非常相似,在某种程度上,这是有道理的:我们从训练数据集中学到的东西与测试数据集中的观察结果相匹配。

如果您自己的数据集没有这样的结果,您应该考虑如何在训练和测试中划分数据集。可能有什么要解决的。同样,caret包可能会有所帮助。

为了更好地理解学习进程,您可能希望有一些特定的指标,甚至使用多个评估指标。

bst <- xgb.train(data=dtrain, max.depth=2, eta=1, nthread = 2, nrounds=2, watchlist=watchlist, eval.metric = "error", eval.metric = "logloss", objective = "binary:logistic")
## [0] train-error:0.046522 train-logloss:0.233376 test-error:0.042831 test-logloss:0.226686
## [1] train-error:0.022263 train-logloss:0.136658 test-error:0.021726 test-logloss:0.137874

eval.metric 允许我们监控每一轮的两个新指标,loglosserror

Linear boosting

到目前为止,我们进行的所有学习都是基于 boosting trees。XGBoost 实现了第二种基于 linear boosting 的算法。与前一个命令的唯一区别是 booster = "gblinear" 参数(并删除了 eta 参数)。

bst <- xgb.train(data=dtrain, booster = "gblinear", nthread = 2, nrounds=2, watchlist=watchlist, eval.metric = "error", eval.metric = "logloss", objective = "binary:logistic")
## [0] train-error:0.024720 train-logloss:0.184616 test-error:0.022967 test-logloss:0.184234
## [1] train-error:0.004146 train-logloss:0.069885 test-error:0.003724 test-logloss:0.068081

在这种特定情况下,linear boosting 比基于 boosting trees 的算法获得更好的性能指标。

在简单的情况下,会发生这种情况,因为没有什么比线性算法更适合捕获线性链接了。但是,决策树可以更好地捕捉预测变量和结果之间的非线性联系。因为没有灵丹妙药,我们建议您使用自己的数据集检查这两种算法,以了解使用什么。

操作 xgb.DMatrix

Save / Load

与保存模型一样,xgb.DMatrix 对象(对数据集和结果进行分组)也可以使用 xgb.DMatrix.save 函数保存。

xgb.DMatrix.save(dtrain, "dtrain.buffer")
## [1] TRUE
# to load it in, simply call xgb.DMatrix
dtrain2 <- xgb.DMatrix("dtrain.buffer")
## [11:41:01] 6513x126 matrix with 143286 entries loaded from dtrain.buffer
bst <- xgb.train(data=dtrain2, max.depth=2, eta=1, nthread = 2, nrounds=2, watchlist=watchlist, objective = "binary:logistic")
## [0] train-error:0.046522 test-error:0.042831
## [1] train-error:0.022263 test-error:0.021726
Information extraction

可以使用 getinfo 函数从 xgb.DMatrix 中提取信息。此后我们将提取 label 数据。

label = getinfo(dtest, "label")
pred <- predict(bst, dtest)
err <- as.numeric(sum(as.integer(pred > 0.5) != label))/length(label)
print(paste("test-error=", err))
## [1] "test-error= 0.0217256362507759"

查看学习模型中的特征重要性/影响

特征重要性类似于 R gbm 包的相对影响(rel.inf)。

importance_matrix <- xgb.importance(model = bst)
print(importance_matrix)
xgb.plot.importance(importance_matrix = importance_matrix)

从模型中查看 trees

您可以使用 xgb.dump 将学习的 tree 转储到文本文件中。

xgb.dump(bst, with_stats = TRUE)
## [1] "booster[0]"
## [2] "0:[f28<-1.00136e-05] yes=1,no=2,missing=1,gain=4000.53,cover=1628.25"
## [3] "1:[f55<-1.00136e-05] yes=3,no=4,missing=3,gain=1158.21,cover=924.5"
## [4] "3:leaf=1.71218,cover=812"
## [5] "4:leaf=-1.70044,cover=112.5"
## [6] "2:[f108<-1.00136e-05] yes=5,no=6,missing=5,gain=198.174,cover=703.75"
## [7] "5:leaf=-1.94071,cover=690.5"
## [8] "6:leaf=1.85965,cover=13.25"
## [9] "booster[1]"
## [10] "0:[f59<-1.00136e-05] yes=1,no=2,missing=1,gain=832.545,cover=788.852"
## [11] "1:[f28<-1.00136e-05] yes=3,no=4,missing=3,gain=569.725,cover=768.39"
## [12] "3:leaf=0.784718,cover=458.937"
## [13] "4:leaf=-0.96853,cover=309.453"
## [14] "2:leaf=-6.23624,cover=20.4624"

您可以使用 xgb.plot.tree 从您的模型中绘制 trees

xgb.plot.tree(model = bst)

如果您提供 fname 参数的路径,您可以将 trees 保存到您的硬盘驱动器。

保存和加载模型

也许您的数据集很大,并且在其上训练模型需要时间?也许您不喜欢浪费时间一次又一次地重做相同的任务?在这些非常罕见的情况下,您会希望保存模型并在需要时加载它。

XGBoost 实现了此类功能,对您很有帮助。

# save model to binary local file
xgb.save(bst, "xgboost.model")
## [1] TRUE

如果一切顺利,xgb.save 函数应该返回 TRUE,否则会崩溃。

要了解我们保存的模型与原始模型的相同程度,一项有趣的测试是比较这两个预测。

# load binary model to R
bst2 <- xgb.load("xgboost.model")
pred2 <- predict(bst2, test$data)

# And now the test
print(paste("sum(abs(pred2-pred))=", sum(abs(pred2-pred))))
## [1] "sum(abs(pred2-pred))= 0"

result is 0? We are good!

在某些非常特殊的情况下,例如当您想从 caret 包中试用 XGBoost 时,您会希望将模型保存为 R 二进制向量。请参阅下文如何操作。

# save model to R's raw vector
rawVec <- xgb.save.raw(bst)

# print class
print(class(rawVec))
## [1] "raw"
# load binary model to R
bst3 <- xgb.load(rawVec)
pred3 <- predict(bst3, test$data)

# pred3 should be identical to pred
print(paste("sum(abs(pred3-pred))=", sum(abs(pred3-pred))))
## [1] "sum(abs(pred3-pred))= 0"

Again 0? It seems that XGBoost works pretty well!


「结束」
alt

本文由 mdnice 多平台发布

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值