为什么我的 ROC 图和 AUC 值看起来不错,而我的随机森林混淆矩阵显示该模型不擅长预测疾病?

Why do my ROC plots and AUC value look good, when my confusion matrix from Random Forests shows that the model is not good at predicting disease?

我正在使用 R 中的 randomForest 包创建一个模型,将病例分类为疾病 (1) 或无病 (0):

classify_BV_100t <- randomForest(bv.disease~., data=RF_input_BV_clean, ntree = 100, localImp = TRUE)

print(classify_BV_100t)

Call:
 randomForest(formula = bv.disease ~ ., data = RF_input_BV_clean,      ntree = 100, localImp = TRUE) 
           Type of random forest: classification
                 Number of trees: 100
No. of variables tried at each split: 53

    OOB estimate of  error rate: 8.04%
Confusion matrix:
    0  1 class.error
0 510  7  0.01353965
1  39 16  0.70909091

我的混淆矩阵显示该模型擅长分类 0(无疾病),但在分类 1(疾病)时非常糟糕。

但是当我绘制 ROC 图时,给人的印象是模型非常好。

以下是我绘制 ROC 的两种不同方式:

  1. (使用https://stats.stackexchange.com/questions/188616/how-can-we-calculate-roc-auc-for-classification-algorithm-such-as-random-forest

    library(pROC)
    rf.roc<-roc(RF_input_BV_clean$bv.disease, classify_BV_100t$votes[,2])
    plot(rf.roc)
    auc(rf.roc)
    
  2. (使用

    library(ROCR)
    predictions <- as.vector(classify_BV_100t$votes[,2])
    pred <- prediction(predictions, RF_input_BV_clean$bv.disease)
    
    perf_AUC <- performance(pred,"auc") #Calculate the AUC value
    AUC <- perf_AUC@y.values[[1]]
    
    perf_ROC <- performance(pred,"tpr","fpr") #plot the actual ROC curve
    plot(perf_ROC, main="ROC plot")
    text(0.5,0.5,paste("AUC = ",format(AUC, digits=5, scientific=FALSE)))
    

这些是 1 和 2 的 ROC 图:

这两种方法给我的 AUC 都是 0.8621593。

有谁知道为什么随机森林混淆矩阵的结果似乎与 ROC/AUC 不一致?

我认为您的 ROC 图没有任何问题,您对差异的评估是正确的。

高 AUC 值是真阴性率非常高的产物。 ROC 考虑了敏感性;主要是衡量真正的积极价值和特异性;真负值的度量。 因为您的特异性非常高,该指标有效地承载了模型的较低灵敏度值,这使您的 AUC 保持相对较高。是的,它的 AUC 很高,但正如您提到的,该模型只擅长预测负数。

我建议计算其他指标(灵敏度、特异性、真阳性率、假阳性率...)并在评估模型时评估所有这些指标的组合。 AUC 是一个质量指标,但它背后还有其他指标意味着更多。

要添加到@DanCarver 的答案中,您还可以将预测结果的截止概率更改为 01。默认情况下,randomForest 中的概率阈值对于双 class 问题都是 0.5。但是,如果假阴性(0 的错误预测)比假阳性(1 的错误预测)成本更高,则可以使用较低的截止概率来预测 class 1

这是一个使用 BreastCancer 数据的示例:

library(randomForest)
library(mlbench)
data(BreastCancer)
library(caret)

# Limit data frame to complete cases
d = BreastCancer[complete.cases(BreastCancer),]

# Run random forest model
set.seed(10)
m1 = randomForest(Class ~ Bare.nuclei + Marg.adhesion, data=d)
m1

# Generate data frame of predictions
pred = data.frame(predict(m1, type="prob"), 
                  actual=d$Class, 
                  thresh0.5=predict(m1))

# Add prediction if we set probability threshold of 0.3 (instead of 0.5) 
# for classifying a prediction as "malignant"
pred$thresh0.3 = factor(ifelse(pred$malignant > 0.3, "malignant", "benign"))

# Look at confusion matrix for each probability threshold    
confusionMatrix(pred$thresh0.5, pred$actual)
confusionMatrix(pred$thresh0.3, pred$actual)

下面是 confusionMatrix 函数输出的一部分。请注意,使用较低的阈值,我们捕获了更多的真阳性(220 而不是 214),但代价是也获得了更多的假阳性(28 而不是 20)。如果假阴性比假阳性成本更高,这可能是一个很好的权衡。 This article 讨论调整 randomForest 模型以优化概率阈值。

预测恶性的阈值概率0.5

           Reference
Prediction  benign malignant
  benign       424        25
  malignant     20       214

预测恶性的阈值概率0.3

           Reference
Prediction  benign malignant
  benign       416        19
  malignant     28       220