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或者AUC这些更细致的指标。
嗯,准确率这块就讲到这里。它在R里的实现确实没什么难度,难点在于你知不知道什么时候该用、什么时候该放手。我当年踩过的坑,希望你这次能绕过去。