【问题标题】:Error when calculating variable importance with categorical variables using the caret package (varImp)使用 caret 包 (varImp) 计算具有分类变量的变量重要性时出错
【发布时间】:2021-03-01 23:08:34
【问题描述】:

我一直在尝试使用 caret 包中的 varImp 函数计算具有混合比例特征的模型的变量重要性。我尝试了多种方法,包括以数字方式重命名和编码我的关卡。在每种情况下,我都会收到以下错误:

Error in auc3_(actual, predicted, ranks) : 
  Not compatible with requested type: [type=character; target=double].

以下虚拟示例应说明我的观点(已编辑以反映@StupidWolf 的更正):

library(caret)

#create small dummy dataset
set.seed(124)
dummy_data = data.frame(Label = factor(sample(c("a","b"),40, replace = TRUE)))
dummy_data$pred1 = ifelse(dummy_data$Label=="a",rnorm(40,-.5,2),rnorm(40,.5,2))
dummy_data$pred2 = factor(ifelse(dummy_data$Label=="a",rbinom(40,1,0.3),rbinom(40,1,0.7)))


# check varImp
control.lvq <- caret::trainControl(method="repeatedcv", number=10, repeats=3)
model.lvq <- caret::train(Label~., data=dummy_data, 
                          method="lvq", preProcess="scale", trControl=control.lvq)
varImp.lvq <- caret::varImp(model.lvq, scale=FALSE)                       

使用不同的模型(如 randomForest 和 SVM)时问题仍然存在。

如果有人知道解决方案或可以告诉我出了什么问题,我将不胜感激。

谢谢!

【问题讨论】:

    标签: r r-caret feature-selection


    【解决方案1】:

    当您在 lvq 上调用 varImp 时,它默认为 filterVarImp(),因为此模型没有特定的变量重要性。现在如果你检查help page:

    对于两类问题,对 预测类的预测数据。敏感性和特异性 计算每个截止值并计算 ROC 曲线。

    现在,如果您阅读将数据输入filterVarImp()source code of varImp.train() ,它是原始数据帧,而不是来自预处理的任何内容。

    这意味着在原始数据中,如果你有一个变量是一个因素,它不能切割变量,它会抛出这样的错误:

    filterVarImp(data.frame(dummy_data$pred2),dummy_data$Label)
    Error in auc3_(actual, predicted, ranks) : 
      Not compatible with requested type: [type=character; target=double].
    

    因此,使用我的示例,就像您指出的那样,您需要对其进行 onehot 编码:

    set.seed(111)
    dummy_data = data.frame(Label = rep(c("a","b"),each=20))
    dummy_data$pred1 = rnorm(40,rep(c(-0.5,0.5),each=20),2)
    dummy_data$pred2 = rbinom(40,1,rep(c(0.3,0.7),each=20))
    dummy_data$pred2 = factor(dummy_data$pred2)
    
    control.lvq <- caret::trainControl(method="repeatedcv", number=10, repeats=3)
    
    ohe_data = data.frame(
                Label = dummy_data$Label,
                model.matrix(Label ~ 0+.,data=dummy_data))
    
    model.lvq <- caret::train(Label~., data=ohe_data, 
                              method="lvq", preProcess="scale",
                           trControl=control.lvq)
    
    caret::varImp(model.lvq, scale=FALSE)  
    
    ROC curve variable importance
    
           Importance
    pred1      0.6575
    pred20     0.6000
    pred21     0.6000
    

    如果您使用的模型没有特定的变量重要性方法,那么一种选择是您可以先计算变量重要性,然后再运行模型。

    【讨论】:

    • 感谢@StupidWolf 指出预测变量的问题。我跑了你的例子。但是,我仍然收到一条错误消息:``` Error in y - mean(y, rm.na = TRUE) : non-numeric argument to binary operator 另外:警告消息:在 mean.default(y, rm. na = TRUE) :参数不是数字或逻辑:返回 NA ``` 既然它似乎对你有用,可能是版本问题吗?我在 R 版本 4.0.3 上运行,插入符号在版本 6.0-86 上。将 Label 和 pred2 设置为因子后,我得到了与原始帖子中描述的相同的错误。
    • 与R版本无关..下次检查你在做什么@hanibal
    • 好的。我希望插入符号能够在内部处理分类变量并计算分类特征的单个变量重要性。感谢您澄清这似乎并非如此。我在我发布的答案中详细说明了这一点——也许因为它被推下而不太清楚;-)。感谢您的链接。
    • 我不知道 preProcess 也适用于分类数据。实际上,在删除 caret::train 中的 preProcess 参数后,问题似乎仍然存在(至少没有先对分类数据进行编码)。
    • 是的,你是对的.. 好的,我必须详细阅读代码。 caret::varImp 使用的 AUC 函数无法处理因子
    【解决方案2】:

    请注意,可以通过将序数特征(具有 d 级别)替换为其 (d-1) 维指示符编码来规避此问题:

    model.matrix(~dummy_data$pred2-1)[,1:(length(levels(dummy_data$pred2)-1)]
    

    但是,为什么 varImp 不能自动处理这个问题?此外,这样做的缺点是它会为每个 d-1 指标生成一个重要性分数,而不是为原始特征生成一个统一的重要性分数。

    【讨论】:

      猜你喜欢
      • 2016-09-29
      • 1970-01-01
      • 2021-05-24
      • 2017-12-18
      • 2021-02-14
      • 1970-01-01
      • 2013-09-05
      • 1970-01-01
      • 2018-06-11
      相关资源
      最近更新 更多