首页 > 解决方案 > 插入符号中的 AUPRC 和 PRROC 之间的区别

问题描述

我正在处理一个非常不平衡的分类问题,并且我使用 AUPRC 作为插入符号中的度量。我从插入符号的 AUPRC 和包 PRROC 的 AUPRC 中得到了非常不同的测试结果。

为了简单起见,可重现的示例使用来自包 mlbench 的 PimaIndiansDiabetes 数据集:

rm(list=ls())
library(caret)
library(mlbench)
library(PRROC)

#load data, renaming it to 'datos'
data(PimaIndiansDiabetes)
datos=PimaIndiansDiabetes[,1:9]

# training and test
set.seed(998)
inTraining <- createDataPartition(datos[,9], p = .8, list = FALSE)
training <-datos[ inTraining,]
testing <- datos[ -inTraining,]

#training

 control=trainControl(method = "cv",summaryFunction = prSummary,
 classProbs = TRUE)
 set.seed(998)
 rf.tune <-train(training[,1:8],training[,9],method ="rf",   
 trControl=control,metric="AUC")

#evaluating AUPRC in test set

 matriz=cbind(testing[,9],predict(rf.tune,testing[,1:8],type="prob"),
 predict(rf.tune,testing[,1:8]))
 names(matriz)=c("obs",levels(testing[,9]),"pred")
 prSummary(matriz,levels(testing[,9]))


 #calculating AUPRC through pr.curve

#checking positive class
 confusionMatrix(predict(rf.tune,testing[,1:8]),testing[,9],
 mode  = "prec_recall")#'Positive' Class : neg 

#preparing data for pr.curve
indice_POS=which(testing[,9]=="neg")
indice_NEG=which(testing[,9]=="pos")

#the classification scores of  only the data points belonging to the 
#positive class
 clas_score_POS=predict(rf.tune,testing[,1:8],type="prob")[indice_POS,1]

 #the classification scores of  only the data points belonging to the 
 #negative class
 clas_score_NEG=predict(rf.tune,testing[,1:8],type="prob")[indice_NEG,2]

 pr.curve(clas_score_POS,clas_score_NEG)

PRROC 的值为 0.9053432,插入符号 prSummary 的值为 0.8714607。在我不平衡的情况下,差异更广泛(AUPRC= 0.1688446 与 SMOTE 重采样 -via control$sampling <- "smote"- 和 0.01429 与 PRROC。)

这是因为在这些包中计算 AUPRC 的方法不同还是我做错了什么?

更新:我在我的代码中找不到错误。在误用答案之后,我想发表一些评论:

prSummary(matriz,levels(testing[,9]))你得到

 AUC      Precision    Recall         F 
0.8714607 0.7894737 0.9000000 0.8411215

这与

confusionMatrix(predict(rf.tune,testing[,1:8]),testing[,9],mode  = "prec_recall")
Confusion Matrix and Statistics

          Reference
Prediction neg pos
       neg  90  23
       pos  10  30

               Accuracy : 0.7843          
                 95% CI : (0.7106, 0.8466)
    No Information Rate : 0.6536          
    P-Value [Acc > NIR] : 0.0003018       

                  Kappa : 0.4945          
 Mcnemar's Test P-Value : 0.0367139       

              Precision : 0.7965          
                 Recall : 0.9000          
                     F1 : 0.8451          
             Prevalence : 0.6536          
         Detection Rate : 0.5882          
   Detection Prevalence : 0.7386          
      Balanced Accuracy : 0.7330          

       'Positive' Class : neg  

与:

> MLmetrics::PRAUC(y_pred = matriz$neg, y_true = ifelse(matriz$obs == "neg", 1, 0))
[1] 0.8714607

正如您在最后一行中看到的,“正”类是“负”,我认为误用是将正类视为“正”,因此我们有不同的指标。此外,当您打印经过训练的 rf 时,结果也与预期的 AUC~0.87 一致:

> rf.tune
Random Forest 

615 samples
  8 predictor
  2 classes: 'neg', 'pos' 

No pre-processing
Resampling: Cross-Validated (10 fold) 
Summary of sample sizes: 554, 553, 553, 554, 554, 554, ... 
Resampling results across tuning parameters:

  mtry  AUC        Precision  Recall  F        
  2     0.8794965  0.7958683  0.8525  0.8214760
  5     0.8786427  0.8048463  0.8325  0.8163032
  8     0.8528028  0.8110820  0.8325  0.8192225

在这种情况下,我并不担心 0.87caret-0.9PRROC 的差异,但在不平衡的情况下,我非常担心 0.1688446 caret/0.01429 PRROC。这可能是因为在不平衡的情况下,不同实现下的数值差异得到了加强?如果实现中存在数值差异,那么它们0.8714607在测试集中如何相同?

标签: rr-caretprecision-recall

解决方案


我相信您在代码中犯了几个错误。

首先caret::prSummary用于MLmetrics::PRAUC计算 AUPRC。它应该这样定义:

MLmetrics::PRAUC(y_pred = matriz$pos, y_true = ifelse(matriz$obs == "pos", 1, 0))

#output
0.7066323

使用正类概率和真实类的数字 0/1 向量(1 表示正类)

使用以下方法获得相同的结果:

caret::prSummary(matriz, levels(testing[,9])[2])

MLmetrics::PRAUC用于ROCR::prediction构造曲线:

pred_obj <- ROCR::prediction(matriz$pos, ifelse(matriz$obs == "pos", 1, 0))
perf_obj <- ROCR::performance(pred_obj, measure = "prec", 
                              x.measure = "rec")

曲线看起来像:

ROCR::plot(perf_obj, ylim = c(0,1))

在此处输入图像描述

当一个人使用时PRROC::pr.curve,有几种方法来定义输入。一种是为正面观察提供正面类的概率向量,为负面观察提供正面类的概率向量:

preds <- predict(rf.tune,
                 testing[,1:8],
                 type="prob")[,2] #prob of positive class
preds_pos <- preds[testing[,9]=="pos"] #preds for true positive class
preds_neg <- preds[testing[,9]=="neg"] #preds for true negative class

PRROC::pr.curve(preds_pos, preds_neg)
#truncated output
0.7254904

这两个数字(由PRROC::pr.curve和获得MLmetrics::PRAUC)不匹配

然而曲线

plot(PRROC::pr.curve(preds_pos, preds_neg, curve = TRUE))

在此处输入图像描述

看起来就像上面使用ROCR::plot.

去检查:

res <- PRROC::pr.curve(preds_pos, preds_neg, curve = TRUE)

ROCR::plot(perf_obj, ylim = c(0,1), lty = 2, lwd = 2)
lines(res$curve[,1], res$curve[,2], col = "red", lty = 5)

在此处输入图像描述

他们是一样的。因此,获得区域的差异是由于上述包中的不同实现。

这些实现可以通过查看源代码来检查:

MLmetrics:::Area_Under_Curve #this one looks pretty straight forward 
PRROC:::compute.pr #haven't the time to study this one but if I had to bet I'd say this one is more accurate for step like curves.

推荐阅读