使用Caret包和xgbTree方法对目标变量应用权重时,varImp函数出现非树模型错误

当我使用Caret包中的’train’函数创建一个带有权重的梯度提升模型时,在使用’varImp’函数时会出现错误,提示未检测到树模型。但当我移除权重后,’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日

在评论区,有人建议使用wts而不是weights。现在我得到了下面的错误:

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

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

set.seed(123)basex <- Arrestsmodel_weights <- ifelse(basex$released == 2,                        yes = (1/table(basex$released)[2]) * 0.5,                        no = (1/table(basex$released)[1]) * 0.5                        )y = basex$releasedx = basextc = trainControl("cv", number = 10)mtd = "xgbTree"model <- train(  x,   y,   method = mtd,  trControl = tc,   wts = model_weights,  verbose = TRUE  )

也许我创建权重向量的方式不对。但我找不到关于’wts’参数的任何文档。


回答:

示例代码存在多个问题。

在caret中应用权重的正确方法是使用train函数的weights参数。

我在评论中推荐使用wts参数是错误的。我的错误源于xgbTree源码,特别是以下这行代码:

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

这表明wts可能是正确的答案。

让我们逐步审查示例并修复所有问题

library(caret)library(car) #用于数据集library(tidyverse) #因为我喜欢使用它data(Arrests)basex <- Arreststable(basex$released) #released是结果类别  No  Yes  892 4334 

在这里我们看到”Yes”结果的频率远高于”No”结果。这将导致预测概率偏向于倾向于预测”Yes”的模型。一种解决方法是给”No”观测值更高的权重。给”No”观测值一个有意义的权重应该是”Yes”类别的比例,而给”Yes”观测值一个有意义的权重应该是”No”类别的比例:

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  weights1      Yes  White 2002  21   Male      Yes     Yes      3 0.1706852       No  Black 1999  17   Male      Yes     Yes      3 0.8293153      Yes  White 2000  24   Male      Yes     Yes      3 0.1706854       No  Black 2000  46   Male      Yes     Yes      1 0.8293155      Yes  Black 1999  27 Female      Yes     Yes      1 0.1706856      Yes  Black 1998  16 Female      Yes     Yes      0 0.170685

“Yes”更频繁,所以我们给它一个较低的权重。

从上面的数据框中可以看出,有几个分类预测变量(如颜色、性别等)。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 checks1            0            1 2002  21          0        1           0            1          0           1      32            1            0 1999  17          0        1           0            1          0           1      33            0            1 2000  24          0        1           0            1          0           1      34            1            0 2000  46          0        1           0            1          0           1      15            1            0 1999  27          1        0           0            1          0           1      16            1            0 1998  16          1        0           0            1          0           1      0y <- basex$released

现在我们有了权重、x和y

由于我将要拟合多个模型,我将首先创建重采样折叠,并在每个train调用中使用它们,这样它们就不会不同。

folds <- createFolds(basex$released, 10)

由于类别频率不平衡,我将使用twoClassSummary,这样我们可以看到训练模型的敏感性和特异性

tc <- trainControl(method = "cv",                   number = 10,                   summaryFunction = twoClassSummary,                   index = folds, #预定义折叠                   classProbs = TRUE) #需要twoClassSummarymtd <- "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     SpecSD1 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     SpecSD1 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的特异性。

所以有意义的权重参数修正了模型总是预测”Yes”的倾向。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注