在 R 中计算精度和召回率

机器算法验证 r 精确召回
2022-03-17 18:41:16

假设我正在构建一个逻辑回归分类器来预测某人是已婚还是单身。(1 = 已婚,0 = 单身)我想在 Precision-recall 曲线上选择一个点,该点给我至少 75% 的准确率,所以我想选择阈值12, 以便:

  • 如果我的分类器的输出大于1,我输出“已婚”。
  • 如果输出低于2,我输出“单”。
  • 如果输出介于两者之间,则输出“我不知道”。

几个问题:

  1. 我认为在精确度的标准定义下,精确度将单独衡量已婚类的精确度(即精确度=我正确预测已婚的#次/我预测已婚的总#次)。但是,我真正想做的是测量整体精度(即,我正确预测已婚或单身的总 # 次/我预测已婚或单身的总 # 次)。这是一件好事吗?如果没有,我该怎么办?
  2. 有没有办法在 R 中计算这个“整体”精度/召回曲线(例如,使用 ROCR 包或其他一些库)?我目前正在使用 ROCR 包,但它似乎只给我一次单一类的精度/召回。
2个回答

为此,我根据《Data Mining with R》一书中的练习编写了一个函数:

# Function: evaluation metrics
    ## True positives (TP) - Correctly idd as success
    ## True negatives (TN) - Correctly idd as failure
    ## False positives (FP) - success incorrectly idd as failure
    ## False negatives (FN) - failure incorrectly idd as success
    ## Precision - P = TP/(TP+FP) how many idd actually success/failure
    ## Recall - R = TP/(TP+FN) how many of the successes correctly idd
    ## F-score - F = (2 * P * R)/(P + R) harm mean of precision and recall
prf <- function(predAct){
    ## predAct is two col dataframe of pred,act
    preds = predAct[,1]
    trues = predAct[,2]
    xTab <- table(preds, trues)
    clss <- as.character(sort(unique(preds)))
    r <- matrix(NA, ncol = 7, nrow = 1, 
        dimnames = list(c(),c('Acc',
        paste("P",clss[1],sep='_'), 
        paste("R",clss[1],sep='_'), 
        paste("F",clss[1],sep='_'), 
        paste("P",clss[2],sep='_'), 
        paste("R",clss[2],sep='_'), 
        paste("F",clss[2],sep='_'))))
    r[1,1] <- sum(xTab[1,1],xTab[2,2])/sum(xTab) # Accuracy
    r[1,2] <- xTab[1,1]/sum(xTab[,1]) # Miss Precision
    r[1,3] <- xTab[1,1]/sum(xTab[1,]) # Miss Recall
    r[1,4] <- (2*r[1,2]*r[1,3])/sum(r[1,2],r[1,3]) # Miss F
    r[1,5] <- xTab[2,2]/sum(xTab[,2]) # Hit Precision
    r[1,6] <- xTab[2,2]/sum(xTab[2,]) # Hit Recall
    r[1,7] <- (2*r[1,5]*r[1,6])/sum(r[1,5],r[1,6]) # Hit F
    r}

对于任何二元分类任务,这将返回每个分类的精度、召回率和 F-stat 以及整体精度,如下所示:

> pred <- rbinom(100,1,.7)
> act <- rbinom(100,1,.7)
> predAct <- data.frame(pred,act)
> prf(predAct)
      Acc     P_0       R_0       F_0       P_1       R_1       F_1
[1,] 0.63 0.34375 0.4074074 0.3728814 0.7647059 0.7123288 0.7375887

像这样计算每个班级的 P、R 和 F 可以让您了解一个或另一个是否给您带来更多困难,然后很容易计算整体 P、R、F 统计数据。我没有使用 ROCR 包,但是您可以通过在某个参数的范围内训练分类器并在该范围内的点处调用分类器的函数来轻松得出相同的 ROC 曲线。

正如罗伯特所说的那样,准确性是要走的路。我只想补充一点,可以使用 ROCR 进行计算。查看帮助(性能)以选择不同的度量。

例如,在 ROCR 中,仅使用一个决策阈值,称为cutoff以下代码绘制了准确度与截止值的关系图,并提取了截止值以获得最大准确度。

require(ROCR)

# Prepare data for plotting
data(ROCR.simple)
pred <- with(ROCR.simple, prediction(predictions, labels))
perf <- performance(pred, measure="acc", x.measure="cutoff")

# Get the cutoff for the best accuracy
bestAccInd <- which.max(perf@"y.values"[[1]])
bestMsg <- paste("best accuracy=", perf@"y.values"[[1]][bestAccInd], 
              " at cutoff=", round(perf@"x.values"[[1]][bestAccInd], 4))

plot(perf, sub=bestMsg)

这导致

在此处输入图像描述

使用两个阈值操作以创建不确定的中间区域(如果情况/目标应用程序允许,这是一种有效的方法),可以使用 ROCR 创建两个性能对象

  1. 截止与真阳性率(tpr),也就是阳性类的精度
  2. 截止与真负率(tnr),即负类的精度

从性能向量中选择一个合适的截止值(使用 R 方法)并将它们组合以达到所需的平衡。这应该很简单,因此我将其作为练习留给读者。

最后一点:两个类的准确度和计算精度之间有什么区别,例如将它们组合成一个(加权)平均值?

准确性计算加权平均值,其中 c 类的权重等于 c 类的实例数。这意味着,如果您遭受严重的类偏差(例如 98% 的负数),则可以通过为所有实例设置预测标签负数来简单地“优化”准确性。在这种情况下,两个类精度的非加权普通平均值会阻止度量的博弈。在平衡类的情况下,两种计算方法当然会导致相同的结果。