关于Scikit-learn中precision与recall计算矛盾的技术咨询
关于Scikit-learn中Precision与Recall的核心疑问解答
首先要明确一个关键前提:计算Precision和Recall时,必须先确定哪个类别是我们关注的“阳性(Positive)”。在医疗检测场景中,我们默认关注的是“检测出患病”,因此**“患病”是阳性类别**,“健康”是阴性类别——这是你之前计算错误的核心原因。
先重新明确四个基础指标的定义(以“患病”为阳性):
- tp(真阳性):实际患病,被判定为患病
- fp(假阳性):实际健康,被判定为患病
- fn(假阴性):实际患病,被判定为健康
- tn(真阴性):实际健康,被判定为健康
例1:分类器判定所有人健康
此时各项指标为:
- tp=0(没有患病者被正确识别)
- fp=0(没有健康者被误判为患病)
- fn=1(唯一的患病者被漏判为健康)
- tn=99(所有健康者被正确识别)
针对“患病”阳性类别的计算:
- Precision:公式为
tp/(tp+fp),这里tp+fp=0(没有任何样本被预测为阳性),Scikit-learn中会将这种情况的Precision定义为1(因为没有错误的阳性预测,相当于所有预测的阳性都是正确的——虽然没有预测阳性) - Recall:公式为
tp/(tp+fn),代入得0/(0+1)=0(唯一的患病者没被检测出来,召回率为0)
这和你提到的书籍结论完全一致。
例2:分类器判定所有人患病
此时各项指标为:
- tp=1(唯一的患病者被正确识别)
- fp=99(99名健康者被误判为患病)
- fn=0(没有患病者被漏判)
- tn=0(没有健康者被正确识别)
针对“患病”阳性类别的计算:
- Precision:
1/(1+99)=0.01,正好等于患病者占总人数的比例(1/100) - Recall:
1/(1+0)=1(所有患病者都被检测出来,召回率为1)
这也和书籍结论一致。
你之前计算错误的原因
你之前误将“健康”作为阳性类别,计算的是“识别健康者”的Precision和Recall,而非“识别患病者”的指标。比如你例1中计算的99/(99+1)=0.9,其实是“健康”作为阳性时的Precision,99/(99+0)=1是“健康”作为阳性时的Recall——这和书籍讨论的“检测患病”任务完全是两个不同的评估维度。
Scikit-learn对无定义情况的处理
当tp+fp=0(无阳性预测)时,Scikit-learn默认将Precision设为1;当tp+fn=0(无实际阳性样本)时,默认将Recall设为1。这是工程上的约定,避免出现数学上的无定义情况,同时符合实际评估逻辑:没有错误的阳性预测,就相当于阳性预测的准确率是100%;没有实际阳性样本,就相当于所有阳性样本都被召回了(因为没有需要召回的)。
内容的提问来源于stack exchange,提问作者Mackie
相关产品推荐
相关产品推荐

