qinghuan
← 回到知识探索

AI 直觉 / 动手实验

把警报门槛调高,就一定更准吗?

用同一组虚构工单移动一道分数线,亲眼看见误报、漏报和待处理数量怎样变化。

展开本文目录
  1. 先动手看看
  2. “选中的对多少”和“该选的找到多少”
  3. 分数不动,只移动那条线
  4. 零条警报,不等于完美识别
  5. 先定目标,再用独立样本选门槛
  6. 记住这三点
  7. 别把例子用过头
  8. 自己试一小步
  9. 查原始资料
  10. 找一份资料继续练
开始前,会这些就够了
  • 知道百分比怎样计算
遇到不熟悉的词,先看这 3 个解释
精确率与召回率
先约定要找的目标类别。精确率看“判为目标的里面,有多少真的符合”;召回率看“实际符合的里面,有多少被找出”。两者分母不同,需要结合误报和漏报代价判断。
分类阈值
把连续分数变成行动的一条分界线。例如约定分数大于或等于 0.5 才进入优先队列。调整分界线改变选中哪些对象,不会改变模型已经给出的分数。
F1 的三种平均
micro 先合并各类计数,macro 先算各类 F1 再等份平均,weighted 按各类真实数量加权。
打开完整术语小抄 ↗

假设客服助手会给工单打一个“需要优先处理”的分数。分数已经排好,值班同学接下来还得决定:从多少分开始进入优先队列?这条分数线叫阈值。调它会改变谁被选中,却不会让原来的排序自动变聪明。

下面七张工单和它们的分数都是虚构的。标签1表示人工核实确实需要优先处理,0表示不需要。我们故意把最高分设成一次误报,好观察一个容易被忽略的现象:门槛越高,精确率未必一路上升。

名单缩短了,留下的就一定更准吗?

七张虚构工单的分数保持不变。标签 1 表示人工核实确实需要优先处理;分数大于等于阈值,才进入优先名单。

分数、真实标签和这次的决策分开看
工单分数真实标签进入名单结果
A0.950是误报
B0.901是符合标签
C0.801是符合标签
D0.700是误报
E0.601是符合标签
F0.401否漏报
G0.200否符合标签

名单中确实需要处理的:3 / 5,精确率 60.0%。

四张实际需要处理的工单,找回 3 张:召回率 75.0%。

误报 2 张,漏报 1 张。

最高分 A 被故意设成误报,用来反驳“阈值越高,每一步都越准”。只提高阈值时,固定数据上的召回率不会上升,精确率却可能上下变化;这里没有训练模型,也没有替真实业务选择阈值。

“选中的对多少”和“该选的找到多少”

精确率问的是:进入优先队列的工单里,有多少确实该优先?如果选中五张,其中三张该优先,就是三除以五。召回率换了分母:所有确实该优先的四张里,找到了三张,就是三除以四。两者回答的是不同问题。

代码里 TP 是选对的数量,FP 是误报数量,FN 是漏掉的数量。标签来自人工核实,不能拿模型自己的判断同时当答案。分数这里只用于排序和比较大小;看到0.8,也不能直接读成“这张有八成概率该优先”。

分数不动,只移动那条线

约定分数大于或等于阈值就选中。阈值从0.5升到0.75时,一部分工单退出队列;从0.75升到0.92时,只剩最高分的那次误报。此时门槛很严格,精确率却掉到零,提醒我们高分也会出错。

在同一批固定分数上,阈值升高只会移除工单,不会补回被漏掉的真阳性,所以召回率不会上升。但精确率是两个变化数量的比值,移除的是误报还是选对的工单,决定了它可能升也可能降。

小实验 · python
samples = [(0.95, 0), (0.90, 1), (0.80, 1), (0.70, 0),
           (0.60, 1), (0.40, 1), (0.20, 0)]
positive = sum(label for _, label in samples)

for threshold in [0, 0.5, 0.75, 0.92, 1.0]:
    selected = [label for score, label in samples if score >= threshold]
    tp = sum(selected)
    fp = len(selected) - tp
    fn = positive - tp
    precision = tp / len(selected) if selected else None
    recall = tp / positive
    shown = f'{precision:.1%}' if precision is not None else 'undefined'
    print(f't={threshold:.2f} TP={tp} FP={fp} FN={fn} P={shown} R={recall:.1%}')

怎样运行:保存为 threshold_queue.py,用 Python 3.10 或更新版本运行:python threshold_queue.py。仅用标准库,不联网。

运行后对照结果
t=0.00 TP=4 FP=3 FN=0 P=57.1% R=100.0%
t=0.50 TP=3 FP=2 FN=1 P=60.0% R=75.0%
t=0.75 TP=2 FP=1 FN=2 P=66.7% R=50.0%
t=0.92 TP=0 FP=1 FN=4 P=0.0% R=0.0%
t=1.00 TP=0 FP=0 FN=4 P=undefined R=0.0%

零条警报,不等于完美识别

阈值升到1时,队列空了,也没有误报,但四张需要优先的工单全被漏掉。精确率的分母此时是零,本文显示为“未定义”。某些绘图工具会约定一个端点数值方便画线,那是展示规则,不能拿来宣布系统达到了完美精确率。

队列长度也应该一起看。假设每天只能人工复核几十张,即使某个阈值召回很高,排进几千张也可能处理不过来。反过来,为了少干活而把门槛拉得很高,会把更多漏报留给后续流程。这里需要明确实际代价,而不是迷信某个漂亮百分比。

先定目标,再用独立样本选门槛

选阈值前,先说清漏掉一张和多查一张分别意味着什么,再用验证数据比较方案;最后在未参与选择的测试数据上报告结果。训练模型、挑门槛和检验最终效果,各自需要合适的数据分工,不能反复盯着同一份结果挑最好看的数。

继续阅读 scikit-learn 的阈值指南时,重点看“相同分数、不同标签”的图,以及验证数据的说明。然后给本例再加一张高分误报,重新观察五个门槛。你练习的是决策规则,不是在证明一个真实客服模型能达到这些指标。

记住这三点

  • 精确率看选中的对象里,真正该选的占多少;召回率看所有该选对象中,找回的占多少。
  • 固定样本上提高阈值不会提高召回率,精确率却不保证单调上升。
  • 门槛应结合漏报代价、误报代价和复核容量,并用独立数据检验。

别把例子用过头

  • 分数不天然等于经过检验的概率;0.5也不是通用最佳门槛。
  • 无预测命中时,精确率没有可计算的分母;绘图库的端点约定不是业务成绩。

自己试一小步

如果复核队列最多容纳三张工单,你会怎样展示门槛选择的代价?

  1. 给每个门槛补上队列长度。
  2. 另设两组误报和漏报代价,比较选择是否变化。
  3. 加入一条高分误报再计算,不改原有标签。

做到这些,就算完成

  • 是否明确使用“大于等于”的边界规则?
  • 是否同时显示精确率、召回率和队列长度?
  • 是否把虚构样本结果与真实业务效果分开?

查原始资料

想确认一个细节,先看这份资料对应的部分,不必从头读完所有文档。

找一份资料继续练

先选一项,按下面的范围继续学;不必从头读完整门课程。