【问题标题】:Confusion matrix for random forest in R CaretR Caret中随机森林的混淆矩阵
【发布时间】:2018-03-30 16:21:35
【问题描述】:

我有二进制 YES/NO 类响应的数据。使用以下代码运行 RF 模型。我在获取混淆矩阵结果时遇到问题。

 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]打印到控制台查看一下。
  • 如果您在问题中包含minimal reproducible example,它会更容易为您提供帮助。

标签: r random-forest r-caret confusion-matrix


【解决方案1】:

据我了解,您希望获得用于插入符号交叉验证的混淆矩阵。

为此,您需要在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

按照CV fos排序,按照原始数据框排序:

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's 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。这应该小心使用,因为它可能导致过度拟合。

【讨论】:

  • 谢谢。只有一个问题,在此代码中,cm pred 模型仅在我将 train 定义为数据集时才有效。我认为对于 pred 我需要定义测试数据集。当我对 test$Class 进行编码时,它给出了这个错误:表中的错误(数据,参考,dnn = dnn,...):所有参数必须具有相同的长度
  • 此代码导致插入符号中交叉验证折叠的混淆矩阵。由于交叉验证是在训练集上完成的,因此只对训练集有用。要获得测试集上的混淆矩阵,必须首先预测测试集样本的类别,并通过confusionMatrix 函数将其与真实类别进行比较。
【解决方案2】:

你可以试试这个来创建混淆矩阵并检查准确性

m <- table(class_log, testing[["Class"]])
m   #confusion table

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

【讨论】:

  • 谢谢,但在运行 class_log 部分时出现错误。我编辑了我的问题
【解决方案3】:

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

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

因此,代码本质上是基于数字向量创建一个由类标签“YES”和“NO”组成的字符向量。

【讨论】:

    【解决方案4】:

    您需要将模型应用到测试集。

    prediction.rf &lt;- predict(model_rf, testing, type = "prob")

    那就class_log &lt;- ifelse(prediction.rf &gt; 0.50, "YES", "NO")

    【讨论】:

    • 谢谢。 class_log 代码适用于二进制 Y/N 响应类吗?
    • prediction.rf 将具有实际值(注意type = "prob")。您也可以使用type = "raw" 立即获取二进制文件,但这并不能让您控制阈值。见?predict.train
    猜你喜欢
    • 2020-06-01
    • 1970-01-01
    • 2021-07-08
    • 2016-05-07
    • 2020-11-17
    • 2018-03-11
    • 2018-02-18
    • 2014-07-08
    • 2015-02-26
    相关资源
    最近更新 更多