2. 准确率(Accuracy):适用场景、陷阱与R实现

准确率,说白了就是模型猜对了多少。

它的计算公式很简单:

Accuracy = (TP + TN) / (TP + TN + FP + FN)

也就是所有预测正确的样本,除以总样本数。你想想看,这确实是最直观的评估方式。我刚入行那几年,也特别喜欢用准确率来汇报模型效果——老板一听就懂,客户也觉得靠谱。

但后来吃过几次亏,我才意识到这个指标远没有表面那么简单。

2.1 什么时候该用准确率?

准确率不是不能用,关键要看场景。我个人习惯先问自己三个问题:

  • 数据是否平衡? 正负样本比例接近1:1时,准确率是可靠的。
  • 各类错误的代价是否相同? 把好人错判成坏人,和把坏人放跑,如果代价一样,可以用准确率。
  • 业务上是否需要综合评估? 如果只是看模型整体表现,不关注单类细节,准确率够用。

举个实际例子。我在项目中做过一个「用户流失预警」模型,正样本(流失用户)占30%,负样本(留存用户)占70%。一开始客户只看准确率,模型做到85%他们就很满意。但我调出混淆矩阵一看——模型几乎把所有用户都判成了「留存」,流失用户一个都没抓住。这就是准确率在数据不平衡时的典型陷阱。

适用场景速查表:

场景 准确率是否适用 理由
垃圾邮件分类(平衡数据) ✅ 适用 正负样本接近,错误代价相当
银行欺诈检测(严重不平衡) ❌ 不适用 负样本极少,准确率会被多数类支配
医学疾病诊断(代价敏感) ❌ 不适用 漏诊的代价远高于误诊
商品分类(多类别均匀分布) ✅ 适用 各类样本量级接近,错误平等

2.2 准确率最常见的陷阱

陷阱一:数据不平衡时的「虚高」

这就是刚才说的用户流失案例。当正样本只占1%时,模型全部预测为负样本,准确率也能达到99%。这听起来很好看,但模型其实什么都没学到。

陷阱二:忽视错误代价

我曾经帮一家医院做「肺炎诊断模型」。模型准确率93%,看上去还不错。但仔细一分析,假阴性(漏诊肺炎)的比例很高。在医院场景下,漏掉一个肺炎患者可能导致病情恶化甚至死亡。这个代价,用准确率完全反映不出来。

陷阱三:多分类时的「平均幻觉」

很多初学者把多分类准确率理解成「平均每类的正确率」,这是错的。准确率是所有预测正确的样本数 / 总样本数。如果类别A和B的样本量差10倍,准确率会被大类别严重带偏。

避坑指南:

我曾经在项目汇报中被客户质疑「你们的模型准确率98%,为什么实际用起来一塌糊涂?」后来发现是因为测试集中90%都是正常样本,模型只需要猜「正常」就能拿高分。从那以后,我每次汇报准确率都一定会附上混淆矩阵和各类别样本占比。

2.3 用R计算准确率

在R里实现准确率非常方便。我最常用的是 caret 包,但自己手写也很快。

方法一:用 confusionMatrix()

library(caret)

# 假设我们有真实标签和预测标签
actual <- factor(c("Yes", "No", "Yes", "Yes", "No", "No", "Yes", "No"))
predicted <- factor(c("Yes", "No", "No", "Yes", "No", "Yes", "Yes", "No"))

# 计算混淆矩阵和所有指标
cm <- confusionMatrix(predicted, actual)
cm$overall["Accuracy"]

输出结果会直接告诉你准确率,还有置信区间和Kappa值。我个人习惯把 cm$byClass 也打出来,看看各类别的召回率和精确率。

方法二:手写准确率函数

# 手写准确率,方便自定义
calc_accuracy <- function(actual, predicted) {
    correct <- sum(actual == predicted)
    total <- length(actual)
    return(correct / total)
}

# 使用
calc_accuracy(actual, predicted)
# [1] 0.75

方法三:用 mlr3 生态

library(mlr3)
library(mlr3measures)

# 直接使用 measure
acc <- msr("classif.acc")
acc$score(truth = actual, response = predicted)
# 或者用性能度量
task <- TaskClassif$new(id = "example", backend = data.frame(x = 1:8, y = actual), target = "y")
prediction <- PredictionClassif$new(actual, predicted)
acc$score(prediction)

我个人更喜欢 caret 的方式,因为它一次性输出所有指标,方便我全面检查。

小技巧: 当你知道数据存在不平衡时,千万别只看准确率。在 confusionMatrix() 之后,立刻检查 cm$byClass[,"Sensitivity"](召回率)和 cm$byClass[,"Pos Pred Value"](精确率)。如果这两个值和准确率差距很大,说明模型可能只是「瞎猜最多的一类」。

2.4 准确率的适用逻辑图

我想呈现一下面对一个分类任务时,到底该不该用准确率的决策流程。我根据经验画了一张图,方便大家对照。

准确率适用性判断流程 分类任务开始评估 数据是否平衡? 是 → 继续 否 → 谨慎使用 错误代价是否相同? 是 → 继续 否 → 改用F1/召回率 只需整体评估? 是 → 可以使用准确率 否 → 结合混淆矩阵 准确率可用 ✅ 当三个判断都为「是」时 准确率是简单可靠的指标 否则请搭配其他指标使用

这张图的逻辑其实很简单:你要依次问自己三个问题——数据平衡吗?错误代价一样吗?只需要看整体表现吗?三个问题都走通,准确率才站得住脚。否则,我建议你立刻转向精确率、召回率、F1或者AUC这些更细致的指标。

嗯,准确率这块就讲到这里。它在R里的实现确实没什么难度,难点在于你知不知道什么时候该用、什么时候该放手。我当年踩过的坑,希望你这次能绕过去。