我正在处理一个非常不平衡的分类问题,并且我将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。在我的不平衡情况下,差异更大(使用control$sampling <- "smote"
-通过SMOTE重采样,APRRC = 0.1688446;使用PRROC,使用0.01429,AUPRC = 0.01688)。
是因为这些软件包中计算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
正如您在最后一行看到的那样,“正”类为“负”,我认为 missuse 将正类视为“ 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
怎么一样?
答案 0 :(得分: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))
当使用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.