R Caret中随机森林的混淆矩阵

5

我有一个二分类的数据集,包含YES/NO的响应变量。使用下面的代码来运行随机森林模型。但是在获取混淆矩阵结果时遇到了问题。

 dataR <- read_excel("*:/*.xlsx")
 Train    <- createDataPartition(dataR$Class, p=0.7, list=FALSE)  
 training <- dataR[ Train, ]
 testing  <- dataR[ -Train, ]

model_rf  <- train(  Class~.,  tuneLength=3,  data = training, method = 
"rf",  importance=TRUE,  trControl = trainControl (method = "cv", number = 
5))

结果:

Random Forest 

3006 samples
82 predictor
2 classes: 'NO', 'YES' 

No pre-processing
Resampling: Cross-Validated (5 fold) 
Summary of sample sizes: 2405, 2406, 2405, 2404, 2404 
Addtional sampling using SMOTE

Resampling results across tuning parameters:

 mtry  Accuracy   Kappa    
  2    0.7870921  0.2750655
  44    0.7787721  0.2419762
 87    0.7767760  0.2524898

Accuracy was used to select the optimal model using  the largest value.
The final value used for the model was mtry = 2.

到目前为止还好,但是当我运行这段代码时:
# Apply threshold of 0.50: p_class
class_log <- ifelse(model_rf[,1] > 0.50, "YES", "NO")

# Create confusion matrix
p <-confusionMatrix(class_log, testing[["Class"]])

##gives the accuracy
p$overall[1]

我收到了这个错误信息:
 Error in model_rf[, 1] : incorrect number of dimensions

希望你们能帮我获取混淆矩阵结果。


model_rf[, 1] 打印到控制台并查看它。 - Samuel
如果您在问题中包含一个最小可重现示例,那么帮助您将更加容易。 - Samuel
4个回答

3

据我理解,您想在caret中获得交叉验证的混淆矩阵。

为此,您需要在trainControl中指定savePredictions。如果它设置为"final",则会保存最佳模型的预测结果。通过指定classProbs = T,每个类别的概率也将被保存。

data(iris)
iris_2 <- iris[iris$Species != "setosa",] #make a two class problem
iris_2$Species <- factor(iris_2$Species) #drop levels

library(caret)
model_rf  <- train(Species~., tuneLength = 3, data = iris_2, method = 
                       "rf", importance = TRUE,
                   trControl = trainControl(method = "cv",
                                            number = 5,
                                            savePredictions = "final",
                                            classProbs = T))

预测结果已出:
model_rf$pred

按照简历文件夹排序后,要按照原始数据框进行排序:
model_rf$pred[order(model_rf$pred$rowIndex),2]

获取混淆矩阵:

confusionMatrix(model_rf$pred[order(model_rf$pred$rowIndex),2], iris_2$Species)
#output
Confusion Matrix and Statistics

            Reference
Prediction   versicolor virginica
  versicolor         46         6
  virginica           4        44

               Accuracy : 0.9            
                 95% CI : (0.8238, 0.951)
    No Information Rate : 0.5            
    P-Value [Acc > NIR] : <2e-16         

                  Kappa : 0.8            
 Mcnemar's Test P-Value : 0.7518         

            Sensitivity : 0.9200         
            Specificity : 0.8800         
         Pos Pred Value : 0.8846         
         Neg Pred Value : 0.9167         
             Prevalence : 0.5000         
         Detection Rate : 0.4600         
   Detection Prevalence : 0.5200         
      Balanced Accuracy : 0.9000         

       'Positive' Class : versicolor 

在两类情况下,通常将0.5作为阈值概率来指定是次优的。在训练后,可以通过优化Kappa或Youden的J统计量(或任何其他首选统计量)作为概率函数来找到最佳阈值。以下是一个示例:
sapply(1:40/40, function(x){
  versicolor <- model_rf$pred[order(model_rf$pred$rowIndex),4]
  class <- ifelse(versicolor >=x, "versicolor", "virginica")
  mat <- confusionMatrix(class, iris_2$Species)
  kappa <- mat$overall[2]
  res <- data.frame(prob = x, kappa = kappa)
  return(res)
})

这里最高的kappa值并不是在threshold == 0.5时获得的,而是在0.1时。需要谨慎使用,因为可能会导致过度拟合。


谢谢。只有一个问题,在这段代码中,当我将train定义为数据集时,cm pred模型才能正常工作。我认为对于pred,我需要定义test数据集。但是当我编写test$Class时,会出现以下错误:Error in table(data, reference, dnn = dnn, ...) : 所有参数必须具有相同的长度。 - Mike
这段代码可以在caret中生成交叉验证折叠的混淆矩阵。由于交叉验证是在训练集上进行的,因此仅适用于训练集。要在测试集上获得混淆矩阵,必须首先预测测试集样本的类别,并通过“confusionMatrix”函数将其与真实类别进行比较。 - missuse

1
你可以尝试使用此方法创建混淆矩阵并检查准确性。
m <- table(class_log, testing[["Class"]])
m   #confusion table

#Accuracy
(sum(diag(m)))/nrow(testing)

谢谢,但是当我运行class_log部分时出现了错误。我已经编辑了我的问题。 - Mike

0

代码片段 class_log <- ifelse(model_rf[,1] > 0.50, "YES", "NO") 是一个if-else语句,执行以下测试:

model_rf的第一列中,如果数字大于0.50,则返回“YES”,否则返回“NO”,并将结果保存在对象class_log中。

因此,该代码基本上根据数字向量创建了一个字符向量的类标签,“YES”和“NO”。


0

你需要将你的模型应用到测试集上。

prediction.rf <- predict(model_rf, testing, type = "prob")

然后执行 class_log <- ifelse(prediction.rf > 0.50, "是", "否")


class_log代码适用于二元(是/否)响应类吗?谢谢。 - Mike
prediction.rf将具有实值(注意 type = "prob")。您也可以使用 type = "raw" 直接获得二进制值,但这不允许您控制阈值。请参见 ?predict.train - Victor Kostyuk

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