插入符号中的AUPRC与PRROC之间的区别

问题描述 投票:2回答:1

我正在处理一个非常不平衡的分类问题,我正在使用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,来自caret prSummary的值为0.8714607。在我的不平衡情况下,差异更大(AUPRC = 0.1688446,SMOTE重新采样 - 通过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

正如您在最后一行中所看到的,“正面”类是“否定”,我认为错误将正类视为“pos”,因此我们有不同的指标。此外,当您打印经过训练的射频时,结果也与预期的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插入/ 0.01429 PRROC。这可能是因为在不平衡的情况下,不同实施下的数字差异会加强吗?如果实现中存在数字差异,那么它们在测试集中是如何相同的0.8714607

r r-caret precision-recall
1个回答
1
投票

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

首先,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))

enter image description here

当使用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.curveMLmetrics::PRAUC获得)不匹配

然而曲线

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

enter image description here

看起来就像上面使用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)

enter image description here

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

可以通过查看以下内容来检查这些实现:

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.
© www.soinside.com 2019 - 2024. All rights reserved.