在R中计算精度、召回率和F1得分的简单方法

28

我正在使用R中的rpart分类器。问题是 - 我想要在测试数据上测试已训练好的分类器。这很简单 - 我可以使用predict.rpart函数。

但我还想计算精度、召回率和F1分数。

我的问题是 - 我是否需要自己编写这些函数,还是R或任何CRAN库中有这样的函数?

8个回答

30

使用 caret包:

library(caret)

y <- ... # factor of positive / negative cases
predictions <- ... # factor of predictions

precision <- posPredValue(predictions, y, positive="1")
recall <- sensitivity(predictions, y, positive="1")

F1 <- (2 * precision * recall) / (precision + recall)

一个适用于二分类和多分类的通用函数,不使用任何包,如下所示:

f1_score <- function(predicted, expected, positive.class="1") {
    predicted <- factor(as.character(predicted), levels=unique(as.character(expected)))
    expected  <- as.factor(expected)
    cm = as.matrix(table(expected, predicted))

    precision <- diag(cm) / colSums(cm)
    recall <- diag(cm) / rowSums(cm)
    f1 <-  ifelse(precision + recall == 0, 0, 2 * precision * recall / (precision + recall))

    #Assuming that F1 is zero when it's not possible compute it
    f1[is.na(f1)] <- 0

    #Binary F1 or Multi-class macro-averaged F1
    ifelse(nlevels(expected) == 2, f1[positive.class], mean(f1))
}

函数的一些注释:

  • 假设F1 = NA时为0
  • positive.class 仅用于二元F1
  • 对于多类问题,计算宏平均F1
  • 如果predictedexpected具有不同的级别,则predicted将接收expected级别

1
嗨,谢谢。我注意到当一个类别从未被预测时会出现警告。您认为计算仍然有效吗? - agenis
1
谢谢,你是对的。我进行了一些小改进来解决这个问题。现在在这种情况下它可以正常工作了。 - Adriano Rivolli

25

ROCR库可以计算这些指标以及更多内容(另请参见http://rocr.bioinf.mpi-sb.mpg.de):

library (ROCR);
...

y <- ... # logical array of positive / negative cases
predictions <- ... # array of predictions

pred <- prediction(predictions, y);

# Recall-Precision curve             
RP.perf <- performance(pred, "prec", "rec");

plot (RP.perf);

# ROC curve
ROC.perf <- performance(pred, "tpr", "fpr");
plot (ROC.perf);

# ROC area under the curve
auc.tmp <- performance(pred,"auc");
auc <- as.numeric(auc.tmp@y.values)

...

7
对于 F1 分数,performance(pred,"f") 返回一个 F1 分数向量。 - smci
1
我猜测预测结果也必须包含每个预测的置信度或概率分数? - peschü
1
只是为了澄清:Performance使用从每个案例的分数(predictions)和标签(y)构建的prediction对象。没有其他数字(如置信度等)。 - Itamar
1
@itamar,你能帮我计算精确率召回率曲线下的面积吗?我的问题在这里(http://stackoverflow.com/questions/39508831/precision-recall-curve-computation-by-prroc-package-in-r)。谢谢。 - Newbie
2
如果问题中有超过两个类需要预测,ROCR将无法工作。 - Matias
1
@peschü似乎是正确的。ROCR期望预测结果是置信度值,以便可以调整截断阈值,从而计算ROC曲线。但是,如果由于分类器的性质而没有置信度值,则输出结果会非常混乱。可能可以提取原始F1分数,但不清楚如何实现。 - Migwell

15

我来更新一下,因为我现在遇到了这个线程,caret包中的confusionMatrix函数可以自动计算所有这些内容。

cm <- confusionMatrix(prediction, reference = test_set$label)

# extract F1 score for all classes
cm[["byClass"]][ , "F1"] #for multiclass classification problems
您可以将以下任何内容替换为“F1”以提取相关值: "敏感性"、"特异性"、"阳性预测值"、"阴性预测值"、"精确度"、"召回率"、"F1"、"流行率"、"检测率"、"检测流行率"、"平衡准确度"。我认为当您只进行二元分类问题时,它的表现略有不同,但在这两种情况下,当您查看混淆矩阵对象下的$ byClass时,所有这些值都会为您计算出来。

7

caret 包中的 confusionMatrix() 函数可与适当的可选字段 "Positive" 一起使用,指定应将哪个因子视为正因子。

confusionMatrix(predicted, Funded, mode = "prec_recall", positive="1")

这段代码还会提供其他数值,如F统计量、准确度等。


或者您可以使用 (mode = "everything") 打印所有统计信息。 - Zawir Amin

4

我注意到有关二元分类需要F1得分的评论。我认为通常确实需要。但是,一段时间以前,我写了这个代码,其中我对几个用数字表示的组进行了分类。这可能对您有用...

calcF1Scores=function(act,prd){
  #treats the vectors like classes
  #act and prd must be whole numbers
  df=data.frame(act=act,prd=prd);
  scores=list();
  for(i in seq(min(act),max(act))){
    tp=nrow(df[df$prd==i & df$act==i,]);        
    fp=nrow(df[df$prd==i & df$act!=i,]);
    fn=nrow(df[df$prd!=i & df$act==i,]);
    f1=(2*tp)/(2*tp+fp+fn)
    scores[[i]]=f1;
  }      
  print(scores)
  return(scores);
}

print(mean(unlist(calcF1Scores(c(1,1,3,4,5),c(1,2,3,4,5)))))
print(mean(unlist(calcF1Scores(c(1,2,3,4,5),c(1,2,3,4,5)))))

3
我们可以直接从caret的confusionMatrix函数中获取F1值。
result <- confusionMatrix(Prediction, Lable)

# View confusion matrix overall
result 

# F1 value
result$byClass[7] 

2
这不是 F1 值。 - Siddhu

1
您还可以使用由caret包提供的confusionMatrix()。输出包括,除其他外,灵敏度(也称为召回率)和Pos Pred Value(也称为精确度)。然后可以轻松地计算F1,如上所述,即:F1 <-(2 * precision * recall) / (precision + recall)

0

使用库(caret)

结果 <- confusionMatrix(预测, 标签)

#这显示了所有必要的度量,包括精确率、召回率和F1

结果$byClass


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接