在应用 varImp 函数时使用带插入符号的 xgbTree 方法和目标变量的权重时出现非树模型错误

问题描述 投票:0回答:1

当我使用 Caret 包中的“train”函数创建模型以使用权重进行梯度提升时,在使用“varImp”函数时出现错误,表示它没有检测到树模型。但是当我去掉重量时它就起作用了。

下面的代码会产生错误:

set.seed(123)

model_weights <- ifelse(modelo_df_sseg$FATALIDADES == 1,
                        yes = (1/table(modelo_df_sseg$FATALIDADES)[2]) * 0.5,
                        no = (1/table(modelo_df_sseg$FATALIDADES)[1]) * 0.5
                        )

model <- train(
  as.factor(FATALIDADES) ~.,
  data = modelo_df_sseg, 
  method = "xgbTree",
  trControl = trainControl("cv", number = 10),
  weights = model_weights
  )

varImp(model)

但是如果我不施加重量,它就会起作用。

为什么 varImp 无法识别我的树?

编辑 2020 年 9 月 4 日

评论部分的missuse建议使用wts代替权重。现在我收到以下错误:

Error in nominalTrainWorkflow(x = x, y = y, wts = weights, info = trainInfo, : formal argument 'wts' matched by multiple actual arguments

我用 R 内置数据集编写了一个小代码,以便您可以自己测试:

set.seed(123)

basex <- Arrests

model_weights <- ifelse(basex$released == 2,
                        yes = (1/table(basex$released)[2]) * 0.5,
                        no = (1/table(basex$released)[1]) * 0.5
                        )

y = basex$released
x = basex
tc = trainControl("cv", number = 10)

mtd = "xgbTree"
model <- train(
  x, 
  y, 
  method = mtd,
  trControl = tc, 
  wts = model_weights,
  verbose = TRUE
  )

也许我创建的权重向量是错误的。但我找不到任何有关“wts”参数的文档。

machine-learning tree xgboost r-caret
1个回答
5
投票

示例代码有几个问题。

在插入符号中应用权重的正确方法是使用

weights
参数到
train

我在评论中错误地建议使用参数

wts
。我的错误是由于 xgbTree 源,特别是行:

if (!is.null(wts))
    xgboost::setinfo(x, 'weight', wts)

这表明

wts
可能是正确答案。

让我们看一下示例并解决所有问题

library(caret)
library(car) #for the data set
library(tidyverse) #because I like to use it

data(Arrests)
basex <- Arrests


table(basex$released) #released is the outcome class

  No  Yes 
 892 4334 

在这里我们看到“是”结果比“否”结果更频繁。这将扭曲预测的概率并有利于倾向于预测“是”的模型。解决这个问题的一种方法是给予“否”观察更高的权重。 “否”观察的有意义的权重将是“是”类的比例,“是”观察的有意义的权重将是“否”类的比例:

model_weights <- ifelse(basex$released == "Yes",
                        table(basex$released)[1]/nrow(basex),
                        table(basex$released)[2]/nrow(basex))

权重之和为1

head(data.frame(basex,
                weights = model_weights))
  released colour year age    sex employed citizen checks  weights
1      Yes  White 2002  21   Male      Yes     Yes      3 0.170685
2       No  Black 1999  17   Male      Yes     Yes      3 0.829315
3      Yes  White 2000  24   Male      Yes     Yes      3 0.170685
4       No  Black 2000  46   Male      Yes     Yes      1 0.829315
5      Yes  Black 1999  27 Female      Yes     Yes      1 0.170685
6      Yes  Black 1998  16 Female      Yes     Yes      0 0.170685

“是”更频繁,因此我们给予它的权重较小。

从上面可以看出数据框有几个分类预测变量(如颜色、性别......)。

xgbTree
无法处理它们,因此您需要在建模之前将它们转换为数字。将分类预测变量转换为数字的一种方法是虚拟编码。还有其他方法,但这不在本答案的范围内。

使用虚拟编码:

dummies <- dummyVars(released ~ ., data = basex)
x <- predict(dummies, newdata = basex)
head(x)
colour.Black colour.White year age sex.Female sex.Male employed.No employed.Yes citizen.No citizen.Yes checks
1            0            1 2002  21          0        1           0            1          0           1      3
2            1            0 1999  17          0        1           0            1          0           1      3
3            0            1 2000  24          0        1           0            1          0           1      3
4            1            0 2000  46          0        1           0            1          0           1      1
5            1            0 1999  27          1        0           0            1          0           1      1
6            1            0 1998  16          1        0           0            1          0           1      0

y <- basex$released

现在我们有了权重 x 和 y

由于我将适合下面的几个模型,因此我将首先创建重采样折叠并在每次调用中使用它们来训练,因此它们没有不同。

folds <- createFolds(basex$released, 10)

由于类别频率存在不平衡,我将使用

twoClassSummary
,这样我们就可以看到训练模型的敏感性和特异性

tc <- trainControl(method = "cv",
                   number = 10,
                   summaryFunction = twoClassSummary,
                   index = folds, #predefined folds
                   classProbs = TRUE) #needed for twoClassSummary

mtd <- "xgbTree"

model <- train(x = x, 
               y = y, 
               method = mtd,
               trControl = tc, 
               weights = model_weights,
               verbose = TRUE,
               metric = "ROC")

#没有错误

model$results %>%
  filter(ROC == max(ROC))
  eta max_depth gamma colsample_bytree min_child_weight subsample nrounds       ROC      Sens     Spec       ROCSD     SensSD     SpecSD
1 0.3         1     0              0.8                1         1      50 0.7031076 0.6185944 0.693945 0.009074758 0.03516597 0.01536701

在这里我们看到,如果我们使用模型权重,则具有最高 AUC 的模型的敏感性为 0.6185944,特异性为 0.693945。

没有配重

model2 <- train(x = x, 
               y = y, 
               method = mtd,
               trControl = tc, 
               verbose = TRUE,
               metric = "ROC")

#没有错误

model2$results %>%
  filter(ROC == max(ROC))
  eta max_depth gamma colsample_bytree min_child_weight subsample nrounds      ROC      Sens      Spec     ROCSD     SensSD     SpecSD
1 0.3         1     0              0.8                1      0.75      50 0.701109 0.1000325 0.9713885 0.0101395 0.03343579 0.01236701

没有权重的模型的灵敏度为 0.1000325,特异性为 0.9713885。

因此,有意义的权重参数固定了模型始终预测“是”的趋势。

© www.soinside.com 2019 - 2024. All rights reserved.