r - 插入符号中的 AUPRC 和 PRROC 之间的区别

标签 r r-caret precision-recall

我正在处理一个非常不平衡的分类问题,并且我使用 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 重采样 - 通过 control$sampling <- "smote" - 和 0.01429 使用 PRROC。)

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

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

当你这样做时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

正如您在最后一行中看到的,“Positive”类是“neg”,我认为 missuse 正在将正类视为“pos”,因此我们有不同的指标。而且,当你打印训练好的 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在测试集中?

最佳答案

我相信您在代码中犯了一些错误。

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

关于r - 插入符号中的 AUPRC 和 PRROC 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53301729/

相关文章:

r - 如何从 caret::predict() 获得类概率和预测?

python - Precision-Recall 曲线或 ROC 曲线是否可能是一条水平线?

r - row.names() 和 attributes$row.names 有什么区别?

r - 在 R 中调整 XGboost 参数

r - 关于 ggplot 中内部变量的文档,尤其是。控制板

r - 使用插入符训练的二项式 GLM

tensorflow - 用于在 keras 中调用的自定义宏

machine-learning - TensorFlow PR曲线插件: pr_curve_streaming_op

r - R中条形图中的文本

r - 如何使用 ggproto 扩展 ggplot2 boxplot?