在R中尝试预测类别概率时出现错误 - caret

30

我使用了caret来建立一个模型。训练完成后,我收到了以下警告:

警告信息: 在train.default(x, y, weights = w, ...)中: 至少有一个类别水平不是有效的R变量名称;如果生成类概率,这可能会导致错误,因为变量名称将被转换为:X0、X1

变量的名称如下:

      str(train)
'data.frame':   7395 obs. of  30 variables:
 $ alchemy_category              : Factor w/ 13 levels "arts_entertainment",..: 2 8 6 6 11 6 1 6 3 8 ...
 $ alchemy_category_score        : num  3737 2052 4801 3816 3179 ...
 $ avglinksize                   : num  2.06 3.68 2.38 1.54 2.68 ...
 $ commonlinkratio_1             : num  0.676 0.508 0.562 0.4 0.5 ...
 $ commonlinkratio_2             : num  0.206 0.289 0.322 0.1 0.222 ...
 $ commonlinkratio_3             : num  0.0471 0.2139 0.1202 0.0167 0.1235 ...
 $ commonlinkratio_4             : num  0.0235 0.1444 0.0426 0 0.0432 ...
 $ compression_ratio             : num  0.444 0.469 0.525 0.481 0.446 ...
 $ embed_ratio                   : num  0 0 0 0 0 0 0 0 0 0 ...
 $ frameTagRatio                 : num  0.0908 0.0987 0.0724 0.0959 0.0249 ...
 $ hasDomainLink                 : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
 $ html_ratio                    : num  0.246 0.203 0.226 0.266 0.229 ...
 $ image_ratio                   : num  0.00388 0.08865 0.12054 0.03534 0.05047 ...
 $ is_news                       : Factor w/ 2 levels "0","1": 2 2 2 2 2 1 2 1 2 1 ...
 $ lengthyLinkDomain             : Factor w/ 2 levels "0","1": 2 2 2 1 2 1 1 1 1 2 ...
 $ linkwordscore                 : num  24 40 55 24 14 12 21 5 17 14 ...
 $ news_front_page               : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
 $ non_markup_alphanum_characters: num  5424 4973 2240 2737 12032 ...
 $ numberOfLinks                 : num  170 187 258 120 162 55 93 132 194 326 ...
 $ numwords_in_url               : num  8 9 11 5 10 3 3 4 7 4 ...
 $ parametrizedLinkRatio         : num  0.1529 0.1818 0.1667 0.0417 0.0988 ...
 $ spelling_errors_ratio         : num  0.0791 0.1254 0.0576 0.1009 0.0826 ...
 $ label                         : Factor w/ 2 levels "0","1": 1 2 2 2 1 1 2 1 2 2 ...
 $ isVideo                       : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 1 1 ...
 $ isFashion                     : Factor w/ 2 levels "0","1": 1 1 1 1 2 1 2 1 2 1 ...
 $ isFood                        : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 2 2 ...
 $ hasComments                   : Factor w/ 2 levels "0","1": 1 2 2 2 2 1 2 2 1 2 ...
 $ hasGoogleAnalytics            : Factor w/ 2 levels "0","1": 1 1 1 1 2 1 2 2 2 1 ...
 $ hasInlineCSS                  : Factor w/ 2 levels "0","1": 1 2 2 2 1 1 2 1 2 2 ...
 $ noOfMetaTags                  : num  10 12 6 10 13 2 6 6 9 5 ...

我的代码如下:

ctrl <- trainControl(method = "CV",
                     number=10,
                     classProbs = TRUE,
                     allowParallel = TRUE,
                     summaryFunction = twoClassSummary)

set.seed(476)
rfFit <- train(formula,
               data=train,
               method = "rf",
               tuneGrid = expand.grid(.mtry = seq(4,20,by=2)),
               ntrees=1000,
               importance = TRUE,
               metric = "ROC",
               trControl = ctrl)


pred <- predict.train(rfFit, newdata = test, type = "prob") 

我遇到了错误:Error in [.data.frame(out, , obsLevels, drop = FALSE) : undefined columns selected

测试数据集中的变量名为:

str(test)
'data.frame':   3171 obs. of  29 variables:
 $ alchemy_category              : Factor w/ 13 levels "arts_entertainment",..: 8 4 12 4 10 12 12 8 1 2 ...
 $ alchemy_category_score        : num  5307 4825 1 6708 5416 ...
 $ avglinksize                   : num  2.56 3.77 2.27 2.52 1.85 ...
 $ commonlinkratio_1             : num  0.39 0.462 0.496 0.706 0.471 ...
 $ commonlinkratio_2             : num  0.257 0.205 0.385 0.346 0.161 ...
 $ commonlinkratio_3             : num  0.0441 0.0513 0.1709 0.123 0.0323 ...
 $ commonlinkratio_4             : num  0.0221 0 0.1709 0.0906 0 ...
 $ compression_ratio             : num  0.49 0.782 1.25 0.449 0.454 ...
 $ embed_ratio                   : num  0 0 0 0 0 0 0 0 0 0 ...
 $ frameTagRatio                 : num  0.0671 0.0429 0.0588 0.0581 0.093 ...
 $ hasDomainLink                 : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
 $ html_ratio                    : num  0.23 0.366 0.162 0.147 0.244 ...
 $ image_ratio                   : num  0.19944 0.08 10 0.00596 0.03571 ...
 $ is_news                       : Factor w/ 2 levels "0","1": 2 1 1 2 2 1 1 2 1 1 ...
 $ lengthyLinkDomain             : Factor w/ 2 levels "0","1": 2 2 2 2 1 2 2 1 1 1 ...
 $ linkwordscore                 : num  15 62 42 41 34 35 15 22 41 7 ...
 $ news_front_page               : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
 $ non_markup_alphanum_characters: num  5643 382 2420 5559 2209 ...
 $ numberOfLinks                 : num  136 39 117 309 155 266 55 145 110 1 ...
 $ numwords_in_url               : num  3 2 1 10 10 7 1 9 5 0 ...
 $ parametrizedLinkRatio         : num  0.2426 0.1282 0.5812 0.0388 0.0968 ...
 $ spelling_errors_ratio         : num  0.0806 0.1765 0.125 0.0631 0.0653 ...
 $ isVideo                       : Factor w/ 2 levels "0","1": 1 2 1 2 2 2 1 1 2 2 ...
 $ isFashion                     : Factor w/ 2 levels "0","1": 1 1 1 1 1 2 1 1 1 1 ...
 $ isFood                        : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 2 2 ...
 $ hasComments                   : Factor w/ 2 levels "0","1": 2 1 1 2 2 2 1 2 2 1 ...
 $ hasGoogleAnalytics            : Factor w/ 2 levels "0","1": 1 2 2 2 2 1 1 2 1 1 ...
 $ hasInlineCSS                  : Factor w/ 2 levels "0","1": 2 2 2 1 1 2 2 2 1 1 ...
 $ noOfMetaTags                  : num  3 6 5 9 16 22 6 9 7 0 ...

如果我省略type="prob"这一部分,则不会出现任何错误。

有什么想法吗?

可能是变量“alchemy_category”的长度问题,该变量附加了相应的因子水平,例如模型内的“alchemy_categoryarts_entertainment”?


这与变量的长度无关。我已经将它们缩短了,但问题仍然存在。 - Stergios
我删除了所有的因素(当然除了响应变量),但我仍然得到相同的错误!! - Stergios
1
trainControl 中设置 classProbs = FALSE - Enrique Pérez Herrero
5个回答

42
答案在您的帖子顶部,用粗体表示 =]
您正在建模什么?是`alchemy_category`吗?代码只显示`formula`,我们看不到它。
当您请求类别概率时,模型预测是一个数据框,每个类别/级别都有单独的列。如果`alchemy_category`没有有效列名的级别,`data.frame`会将其转换为有效名称。这会创建一个问题,因为代码正在寻找特定名称,但数据框具有不同(但有效)的名称。
例如,如果我有:
> test <- factor(c("level1", "level 2")) 
> levels(test)
[1] "level 2" "level1" 
> make.names(levels(test))
[1] "level.2" "level1"

这段代码会寻找 "level 2",但是实际上只有 "level.2"。


抱歉,我没有在这里包含我的公式。我对“标签”进行建模,因此是“0”或“1”。你说的“答案在我帖子的顶部以粗体显示=]”是什么意思?我不明白。 - Stergios
6
他的意思是,你所包含的警告信息解释了发生了什么问题。由于“0”和“1”不是有效的R变量名称,在生成类别概率时会出现错误。 - Steve Weston
10
很好的解释。我的课程是以0和1表示,因此一直失败并出现了上述错误信息。将它们更改为“否”和“是”解决了这个问题。 - xbsd
2
如果您预测一个逻辑结果,请注意TRUEFALSE不是可接受的列名。 - Sam Firke
在我的情况下,解决方案是删除因子levels中的空格。我的意思是,在将char列转换为factor之前,我做了类似于以下的操作:train_b <- train_a %>% mutate(state=recode(state,'Fully Paid'='FullyPaid')) - juanbretti

17

如上所述,类值必须是因子(factor)并且必须是有效名称。确保这一点的另一种方法是:

levels(all.dat$target) <- make.names(levels(factor(all.dat$target)))

这是否保留了数据集?因为我使用了这行代码,现在我的“y”变量是以0和1为结果的X0和X1的因子形式。 - Jack Armstrong

10

我在面对相似的问题时已经阅读了上面的回答。一个正式的解决方案是在训练和测试数据集上执行此操作。确保在特征名称中也包括响应变量。

feature.names=names(train)

for (f in feature.names) {
  if (class(train[[f]])=="factor") {
    levels <- unique(c(train[[f]]))
    train[[f]] <- factor(train[[f]],
                   labels=make.names(levels))
  }
}

这将为所有因子创建语法上正确的标签。


1

正如@Sam Firke在评论中指出的那样(但我忽略了它),TRUE/FALSE级别也无法工作。因此,我将它们转换为是/否。


0
根据上述示例,通常重构结果变量将解决问题。最好在将数据集分成训练和测试数据集之前更改原始数据集。 levels <- unique(data$outcome) data$outcome <- factor(data$outcome, labels=make.names(levels))
正如其他人早先指出的那样,这个问题只会在classProbs=TRUE时发生,这会导致train函数生成与结果类相关的额外统计信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接