You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多分类问题中Sklearn计算Precision、Recall、F1结果不符问题

多分类指标计算疑问:Sklearn结果与手动计算不符

我面临一个多分类问题,其中类别0为负类,类别1和2为正类。用Sklearn计算相关指标的代码如下:

import numpy as np
from sklearn.metrics import confusion_matrix
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.metrics import f1_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
import matplotlib.pyplot as plt  # 补充原代码缺失的导入

# 真实标签与预测标签
y_true = np.array((1, 2, 2, 0, 1, 0))
y_pred = np.array((1, 0, 0, 0, 0, 1))
# 计算各项指标
precision_macro = precision_score(y_true, y_pred, average='macro')
precision_weighted = precision_score(y_true, y_pred, average='weighted')
recall_macro = recall_score(y_true, y_pred, average='macro')
recall_weighted = recall_score(y_true, y_pred, average='weighted')
f1_macro = f1_score(y_true, y_pred, average='macro')
f1_weighted = f1_score(y_true, y_pred, average='weighted')
# 绘制混淆矩阵
cm = confusion_matrix(y_true, y_pred)
disp = ConfusionMatrixDisplay(confusion_matrix=cm)
disp.plot()
plt.show()

运行后得到的指标结果:

precision_macro = 0.25
precision_weighted = 0.25
recall_macro = 0.33333
recall_weighted = 0.33333
f1_macro = 0.27778
f1_weighted = 0.27778

对应的混淆矩阵:
混淆矩阵

我的手动计算过程:

  1. Precision计算(仅针对类别1和2)
Precision1 = TP1/(TP1+FP1) = 1/(1+1) = 0.5
Precision2 = TP2/(TP2+FP2) = 0/(0+0) = 0(符合Sklearn文档说明)
Precision_Macro = (Precision1 + Precision2)/2 = 0.25
Precision_Weighted = (2*Precision1 + 2*Precision2)/4 = 0.25
  1. Recall计算(仅针对类别1和2)
Recall1 = TP1/(TP1+FN1) = 1/(1+1) = 0.5
Recall2 = TP2/(TP2+FN2) = 0/(0+2) = 0
Recall_Macro = (Recall1+Recall2)/2 = (0.5+0)/2 = 0.25
Recall_Weighted = (2*Recall1+2*Recall2)/4 = (2*0.5+2*0)/4 = 0.25
  1. F1计算
F1_Macro = 2*(Precision_Macro*Recall_Macro)/(Precision_Macro+Recall_Macro) = 0.25
F1_Weighted = 2*(Precision_Weighted*Recall_Weighted)/(Precision_Weighted+Recall_Weighted) = 0.25

可以看到,手动计算的Precision与Sklearn结果一致,但Recall和F1结果存在差异。即使使用Sklearn给出的Precision(0.25)和Recall(0.3333)也无法得到F1值0.27778,请问我哪里出错了?


问题原因与正确计算方式

你的核心错误是:Sklearn在默认的多分类指标计算中,会包含所有类别(包括你定义的负类0),而你手动计算时只考虑了正类1和2。

1. 先明确混淆矩阵的各项数值(行=真实标签,列=预测标签)

预测0  预测1  预测2
真实0      1     1     0
真实1      1     1     0
真实2      2     0     0

2. 计算每个类别的Precision、Recall、F1

类别0:

  • TP0:真实0且预测0 → 1
  • FP0:预测0但真实不是0 → 1(真实1)+2(真实2)=3
  • FN0:真实0但预测不是0 →1(预测1)
  • Precision0 = TP0/(TP0+FP0) =1/(1+3)=0.25
  • Recall0 = TP0/(TP0+FN0)=1/(1+1)=0.5
  • F1_0 = 2*(0.25*0.5)/(0.25+0.5)= 0.3333

类别1:

  • Precision1=0.5,Recall1=0.5,F1_1=0.5

类别2:

  • Precision2=0,Recall2=0,F1_2=0(Sklearn中当TP+FP=0时Precision为0,TP+FN=0时Recall为0)

3. 重新计算Macro与Weighted指标

Macro平均(所有类别指标取算术平均):

  • Recall_Macro = (Recall0 + Recall1 + Recall2)/3 = (0.5 +0.5 +0)/3 = 1/3 ≈0.33333(与Sklearn结果一致)
  • F1_Macro = (F1_0 + F1_1 + F1_2)/3 = (0.3333 +0.5 +0)/3 ≈0.8333/3≈0.27778(与Sklearn结果一致)

Weighted平均(按每个类别的样本数加权):

样本数:类别0有2个,类别1有2个,类别2有2个,总样本6个。

  • Recall_Weighted = (20.5 +20.5 +2*0)/6 = (1+1+0)/6=2/6≈0.33333
  • F1_Weighted = (20.3333 +20.5 +2*0)/6 = (0.6666+1+0)/6≈1.6666/6≈0.27778

补充说明

如果你只想针对正类1和2计算指标,需要调整Sklearn的参数,限定计算的类别:

# 仅针对类别1和2计算Macro Recall
recall_macro_pos = recall_score(y_true, y_pred, average='macro', labels=[1,2])
# 结果会是0.25,和你的手动计算一致

内容的提问来源于stack exchange,提问作者Murilo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 17:24:53