开始前,会这些就够了
- 理解百分比
遇到不熟悉的词,先看这 2 个解释
- 基准率
- 在指定样本或场景中,目标类别本来占多大比例。它描述任务面对的人群或数据构成,而不是模型的识别能力;解释预测结果时,不能把这个比例忽略。
- 精确率与召回率
- 先约定要找的目标类别。精确率看“判为目标的里面,有多少真的符合”;召回率看“实际符合的里面,有多少被找出”。两者分母不同,需要结合误报和漏报代价判断。
设想一千张练习工单中,只有二十张需要紧急处理。一个程序把所有工单都判成“不紧急”,也能得到百分之九十八的准确率,却一张紧急工单都没找出来。这里的数字完全是自拟数据,用来说明高总分可能掩盖你最关心的那一类错误。
基准率是某类情况在目标人群或数据中本来就有的比例。本例中紧急工单占百分之二。评价一个分类器之前,先看这个比例,再看它到底把哪些样本判对、把哪些判错。
模型标出来的,多少真的符合条件?
| 真实情况 | 标为紧急 | 标为普通 |
|---|---|---|
| 确实紧急 | 18 | 2 |
| 实际上普通 | 49 | 931 |
- 标为紧急的工单中,确实紧急的比例
- 26.9%
先只改变紧急工单占比,保持识别能力不动,观察这个比例为什么会变化。
用 1,000 张假设工单观察分类,正类表示“确实需要紧急处理”。按比例计算的是期望数量,表格四舍五入显示;这些输入是教学假设,不是某个产品的准确率。
先数四格,再谈模型好不好
把紧急工单称为正类,可以画出四格:真正紧急且报了警是真正例;普通工单却报警是假正例,也就是误报;紧急工单没报警是假负例,也就是漏报;普通工单没报警是真负例。准确率把两种判对的数量相加,再除以全部工单,所以数量庞大的普通工单会强烈影响它。
召回率只看真正紧急的工单,有多少被找了出来;精确率只看已经报警的工单,有多少真的紧急。两者的分母不同,不能互换。“总共判对多少”和“每次报警多值得相信”也不是同一个问题。若根本没有报警,精确率的分母为零,应明确说明未定义或所用约定,不能悄悄写成满分。
保持两种识别率,改变工单比例
下面构造两组各一千张的计数,假设对紧急工单都找回九成,对普通工单都误报百分之五。第一组有二十张紧急工单,第二组有二百张。代码只做四则运算,没有训练模型,也没有声称现实中换一批数据后,这两种条件识别率仍会保持不变。
第一组中,数量很多的普通工单即使只有一小部分被误报,也能产生不少假警报。第二组的紧急工单更多,报警结果里真紧急的比例便不同。观察输出时,把真正例和假正例一起看,便能理解为什么同一个“找回九成”的说法,还不足以回答“报警后多大比例是真的”。
cases = {
"always-normal": (0, 0, 980, 20),
"rare": (18, 49, 931, 2),
"more-common": (180, 40, 760, 20),
}
for name, (tp, fp, tn, fn) in cases.items():
accuracy = (tp + tn) / (tp + fp + tn + fn)
recall = tp / (tp + fn)
precision = f"{tp / (tp + fp):.3f}" if tp + fp else "undefined"
print(name, f"accuracy={accuracy:.3f}",
f"recall={recall:.3f}", f"precision={precision}")
怎样运行:Python 3.10+;保存为 classification_counts.py,在该目录运行 python classification_counts.py。只用标准库,无需联网。
运行后对照结果
always-normal accuracy=0.980 recall=0.000 precision=undefined
rare accuracy=0.949 recall=0.900 precision=0.269
more-common accuracy=0.940 recall=0.900 precision=0.818先确定要解决哪种错误
不看输入、始终预测最常见类别,可以作为一个简单基线。它不是有用模型的上限,而是提醒你:复杂模型的成绩需要和合理的起点比较。scikit-learn 的 DummyClassifier 就提供这类基线;实际评估时,基线的选择应来自训练资料,不能先翻看测试答案再挑最有利的规则。
接着把错误接到真实流程:误报会占用多少人工复查时间,漏报会遗漏什么工作。根据这些代价选择阈值,并同时报告样本量、类别比例和关键指标。不能只把准确率下降当成模型变差:一个开始找出紧急工单的模型,可能在增加误报的同时减少漏报,是否值得需要具体判断。
若线上工单的类别比例或内容变化,应重新检查这些计数。这里固定条件识别率只为隔离一个变量;真实系统可能同时发生用词变化、标签规则变化和模型能力变化。单看一个百分比,无法分清是比例变了、阈值变了,还是模型对某类样本的识别变了。
记住这三点
- 准确率汇总所有样本,可能掩盖少数类的全部漏报。
- 召回率从实际正类出发,精确率从预测正类出发。
- 报告基准率、四格计数和错误代价,才能解释分数的用途。
别把例子用过头
- 一千张工单是自拟计数,不是任何模型的线上准确率。
- 固定召回率和误报率只是单变量演示,实际分布变化时需要重新测量。
- 上方代码的三组计数均有正类;没有预测正类时,明确显示精确率未定义。
自己试一小步
同样高的准确率,能否对应不同的人工复查负担?
- 自行构造两张总量相同的四格计数表,写清正类含义。
- 分别计算准确率、召回率、精确率和报警总量。
- 为误报与漏报设置不同的虚构处理成本,再比较两种方案。
做到这些,就算完成
- 四格数量都是非负整数且能加回总量。
- 没有把误报率与一减精确率混为一谈。
- 结论说明了类别比例和成本假设。
查原始资料
想确认一个细节,先看这份资料对应的部分,不必从头读完所有文档。
- Google 机器学习速成课:准确率、召回率、精确率 (新标签页)↗
四格计数、准确率与精确率/召回率的不同分母,以及类别不平衡时的解释边界。
- scikit-learn:DummyClassifier (新标签页)↗
忽略输入特征的基线,以及按训练标签中最常见类别预测的行为。
找一份资料继续练
先选一项,按下面的范围继续学;不必从头读完整门课程。
机器学习速成课程:用图和小练习理解模型 (新标签页)↗
只选分类模块的混淆矩阵与评估指标,把普通工单和紧急工单分开数,检查高总正确率漏掉了谁。
查看学习准备与访问说明 →Cleanlab:把可疑标签找出来,再由人核对 (新标签页)↗
从问题表挑三项,写下需要什么原始材料才能复核参考标签,不因模型不同意就改标签。
查看学习准备与访问说明 →