跳到内容

根据 XGBoost 模型预测数据值。

用法

# S3 method for class 'xgb.Booster'
predict(
  object,
  newdata,
  missing = NA,
  outputmargin = FALSE,
  predleaf = FALSE,
  predcontrib = FALSE,
  approxcontrib = FALSE,
  predinteraction = FALSE,
  training = FALSE,
  iterationrange = NULL,
  strict_shape = FALSE,
  avoid_transpose = FALSE,
  validate_features = FALSE,
  base_margin = NULL,
  ...
)

参数

对象

xgb.Booster 类的对象。

newdata

接受 data.frame, matrix, dgCMatrix, dgRMatrix, dsparseVector, 本地数据文件或 xgb.DMatrix

对于稀疏数据上的单行预测,建议使用 CSR 格式。如果传递稀疏向量,它将作为行向量处理。

请注意,对于同一数据的重复预测,可能需要创建一个 DMatrix 以便此处传递,而不是传递矩阵或数据帧等 R 类型,因为在 DMatrix 上进行预测会更快。

如果 newdatadata.frame,请注意

  • 如果列不是数字类型,它们将被转换为数字,这可能会使操作比在等效的 matrix 对象中慢。

  • 除非传递 validate_features = TRUE(这不是默认值),否则列的顺序必须与模型拟合数据的顺序匹配(即,列不会通过其名称引用,仅通过它们在数据中的顺序引用)。

  • 如果模型拟合到具有分类列的数据,则这些列在此处必须是 factor 类型,并且必须使用相同的编码(即具有相同的级别)。

  • 如果 newdata 包含任何 factor 列,它们将转换为基于 0 的编码(与创建 DMatrix 期间相同)——因此,不应在训练期间具有不同类型的列下传递 factor

  • 任何类型不是 factor 的列都将被解释为数字。

缺失值

表示数据中缺失值的浮点值(例如,0 或其他极端值)。

newdataxgb.DMatrix 时,不使用此参数——在这种情况下,应将其作为参数传递给 DMatrix 构造函数。

outputmargin

预测是否应以提升迭代结果的原始未转换预测和的形式返回。例如,对于逻辑回归设置 outputmargin = TRUE 将返回对数几率而不是概率。

predleaf

是否预测每棵树的叶子索引。

predcontrib

是否返回特征对个体预测的贡献(详见“详细信息”)。

approxcontrib

是否使用快速近似方法计算特征贡献(详见“详细信息”)。

predinteraction

是否返回特征交互对个体预测的贡献(详见“详细信息”)。

training

预测结果是否用于训练。对于 dart booster,训练预测将执行 dropout。

iterationrange

用于预测的模型中的轮次/迭代序列,通过传递一个包含序列开始和结束数字的二维向量来指定(与 R 的 seq 格式相同 - 即,基于 1 索引,并包括两端)。

例如,传递 c(1,20) 将使用前二十次迭代进行预测,而传递 c(1,1) 将仅使用第一次迭代进行预测。

如果传递 NULL,如果模型使用了提前停止,则将停止在最佳迭代处,否则将使用所有迭代(轮次)。

如果传递“all”,将使用所有轮次,无论模型是否进行了提前停止。

不适用于 gblinear booster。

strict_shape

是否始终为给定的预测模式返回一个具有相同维度(无论模型类型如何)的数组——这意味着,例如,多分类和二分类模型都会生成具有相同维数的输出数组,其中“类”维度对于二分类模型的大小等于“1”。

如果传递 FALSE(默认值),维度将根据模型类型进行简化,例如,二分类模型将不会有多余的“类”维度。

有关每种预测模式的输出数组的确切形状,请参阅返回类型文档。

avoid_transpose

是否以 XGBoost 核心库生成预测时所用的相同内存布局输出结果预测,而不进行转置以匹配预期的输出形状。

在内部,XGBoost 使用行主序生成预测,而 R 数组使用列主序,因此需要对结果进行转置,以便在表示为 R 数组或矩阵时具有预期形状,这可能是一个缓慢的操作。

如果传递 TRUE,则结果的维度将是反向的——例如,行将是最后一个维度而不是第一个维度。

validate_features

当为 TRUE 时,验证 Booster 和 newdata 的 feature_names 是否匹配(仅当 objectnewdata 都有特征名称时适用)。

如果列名不同且 newdata 不是 xgb.DMatrix,则会尝试重新排序 newdata 中的列以匹配 booster 的列。

如果 booster 具有特征类型且 newdataxgb.DMatrixdata.frame,则会额外验证 newdata 中的分类列是否为正确类型,如果不匹配则会引发错误。

如果传递 FALSE,则假定特征名称和类型相同,并且与训练数据中的顺序相同。

请注意,此检查可能会为预测增加相当大的延迟,因此建议在对性能敏感的应用程序中禁用它。

基本边距

用于从现有模型进行提升的基准边距(独立于模型中的树,添加到所有观测值的原始分数)。

如果提供,应为长度等于 newdata 行数的向量(对于每个观测值产生单个分数的Objective),或行数与 newdata 行数匹配且列数与模型估计的分数数量(例如多类别分类的类别数量)匹配的矩阵。

请注意,如果 newdataxgb.DMatrix 对象,则此参数将被忽略,因为它需要添加到 DMatrix 中(例如,通过在其构造函数中将其作为参数传递,或通过调用 setinfo.xgb.DMatrix())。

...

未使用。

一个数值向量或数组,其相应维度取决于预测模式和参数 strict_shape,如下所示

如果传递 strict_shape=FALSE

  • 对于回归或二分类:长度为 nrows 的向量。

  • 对于多分类和多目标:维度为 [nrows, ngroups] 的矩阵。

    请注意,目标变体 multi:softmax 默认倾向于预测最可能的类别(一个 nrows 向量)而不是每个类别的概率。

  • 对于 predleaf:一个矩阵,每棵树一列。

    对于多类/多目标,它们将按以下方式排列:输出中的列将包含一个组的叶子,然后是另一组的叶子(例如,顺序将是 group1:feat1, group1:feat2, ..., group2:feat1, group2:feat2, ...)。

    如果存在多个并行树(例如随机森林),并行树将是结果顺序中的最后一个分组,并且仍然是 2D 的。

  • 对于 predcontrib:当不是多分类/多目标时,一个维度为 [nrows, nfeats+1] 的矩阵。最后一个“+1”列对应于基线值。

    对于多类和多目标,将是一个维度为 [nrows, ngroups, nfeats+1] 的数组。

    贡献值处于未转换边距的尺度(例如,对于二分类,这些值是与基线的对数几率偏差)。

  • 对于 predinteraction:当不是多分类/多目标时,输出是一个维度为 [nrows, nfeats+1, nfeats+1] 的 3D 数组。非对角线(在最后两个维度中)元素表示不同的特征交互贡献。该数组相对于最后两个维度是对称的。“+1”列对应于基线。沿最后一个维度对该数组求和应产生与 predcontrib = TRUE 几乎相同的结果。

    对于多类别和多目标,将是维度为 [nrows, ngroups, nfeats+1, nfeats+1] 的 4D 数组

如果传递 strict_shape=TRUE,结果始终是一个矩阵(如果是 2D)或数组(如果是 3D 或更高)

  • 对于正常预测,维度为 [nrows, ngroups]

  • 对于 predcontrib=TRUE,维度为 [nrows, ngroups, nfeats+1]

  • 对于 predinteraction=TRUE,维度为 [nrows, ngroups, nfeats+1, nfeats+1]

  • 对于 predleaf=TRUE,维度为 [nrows, niter, ngroups, num_parallel_tree]

如果传递 avoid_transpose=TRUE,则在所有情况下维度都将反向——例如,对于 predinteraction,它们将是 [nfeats+1, nfeats+1, ngroups, nrows] 而不是 [nrows, ngroups, nfeats+1, nfeats+1]

详细信息

请注意,iterationrange 目前对“gblinear”的预测不起作用,因为“gblinear”不保留其提升历史。

predleaf 选项的一个可能的实际应用是使用模型作为捕获非线性和交互的新特征的生成器,例如,在 xgb.create.features() 中实现。

设置 predcontrib = TRUE 允许计算每个特征对单个预测的贡献。对于“gblinear”booster,特征贡献只是线性项 (feature_beta * feature_value)。对于“gbtree”booster,特征贡献是 SHAP 值 (Lundberg 2017),它们之和等于模型预期输出与当前预测之间的差异(其中使用 Hessian 权重计算期望)。设置 approxcontrib = TRUE 根据 http://blog.datadive.net/interpreting-random-forests/ 中解释的思想近似这些值。

通过 predinteraction = TRUE,计算每对特征交互的 SHAP 贡献值。请注意,此操作在计算和内存方面可能相当昂贵。由于它与特征数量呈二次方关系,因此建议首先执行最重要的特征选择。有关返回结果的格式,请参阅下文。

predict() 方法使用 xgb.Booster 对象中定义的所有线程(默认情况下)。如果您想更改其数量,请使用 xgb.model.parameters<-() 将新数量分配给 nthread。请注意,将矩阵转换为 xgb.DMatrix() 也使用多个线程。

参考文献

  1. Scott M. Lundberg, Su-In Lee, "A Unified Approach to Interpreting Model Predictions", NIPS Proceedings 2017, https://arxiv.org/abs/1705.07874

  2. Scott M. Lundberg, Su-In Lee, "Consistent feature attribution for tree ensembles", https://arxiv.org/abs/1706.06060

另请参阅

示例

## binary classification:

data(agaricus.train, package = "xgboost")
data(agaricus.test, package = "xgboost")

## Keep the number of threads to 2 for examples
nthread <- 2
data.table::setDTthreads(nthread)

train <- agaricus.train
test <- agaricus.test

bst <- xgb.train(
  data = xgb.DMatrix(train$data, label = train$label, nthread = 1),
  nrounds = 5,
  params = xgb.params(
    max_depth = 2,
    nthread = nthread,
    objective = "binary:logistic"
  )
)

# use all trees by default
pred <- predict(bst, test$data)
# use only the 1st tree
pred1 <- predict(bst, test$data, iterationrange = c(1, 1))

# Predicting tree leafs:
# the result is an nsamples X ntrees matrix
pred_leaf <- predict(bst, test$data, predleaf = TRUE)
str(pred_leaf)

# Predicting feature contributions to predictions:
# the result is an nsamples X (nfeatures + 1) matrix
pred_contr <- predict(bst, test$data, predcontrib = TRUE)
str(pred_contr)
# verify that contributions' sums are equal to log-odds of predictions (up to float precision):
summary(rowSums(pred_contr) - qlogis(pred))
# for the 1st record, let's inspect its features that had non-zero contribution to prediction:
contr1 <- pred_contr[1,]
contr1 <- contr1[-length(contr1)]    # drop intercept
contr1 <- contr1[contr1 != 0]        # drop non-contributing features
contr1 <- contr1[order(abs(contr1))] # order by contribution magnitude
old_mar <- par("mar")
par(mar = old_mar + c(0,7,0,0))
barplot(contr1, horiz = TRUE, las = 2, xlab = "contribution to prediction in log-odds")
par(mar = old_mar)


## multiclass classification in iris dataset:

lb <- as.numeric(iris$Species) - 1
num_class <- 3

set.seed(11)

bst <- xgb.train(
  data = xgb.DMatrix(as.matrix(iris[, -5], nthread = 1), label = lb),
  nrounds = 10,
  params = xgb.params(
    max_depth = 4,
    nthread = 2,
    subsample = 0.5,
    objective = "multi:softprob",
    num_class = num_class
  )
)

# predict for softmax returns num_class probability numbers per case:
pred <- predict(bst, as.matrix(iris[, -5]))
str(pred)
# convert the probabilities to softmax labels
pred_labels <- max.col(pred) - 1
# the following should result in the same error as seen in the last iteration
sum(pred_labels != lb) / length(lb)

# compare with predictions from softmax:
set.seed(11)

bst <- xgb.train(
  data = xgb.DMatrix(as.matrix(iris[, -5], nthread = 1), label = lb),
  nrounds = 10,
  params = xgb.params(
    max_depth = 4,
    nthread = 2,
    subsample = 0.5,
    objective = "multi:softmax",
    num_class = num_class
  )
)

pred <- predict(bst, as.matrix(iris[, -5]))
str(pred)
all.equal(pred, pred_labels)
# prediction from using only 5 iterations should result
# in the same error as seen in iteration 5:
pred5 <- predict(bst, as.matrix(iris[, -5]), iterationrange = c(1, 5))
sum(pred5 != lb) / length(lb)