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

多分类任务中基于Top5预测标签构建混淆矩阵及计算TP等指标的技术问询

针对Top5预测结果构建混淆矩阵与计算TP/TN/FP/FN的解决方案

你的核心问题是:常规的confusion_matrix要求每个样本对应单个预测标签,但你的模型输出的是每个样本的Top5预测类别列表,直接传入会因为维度不匹配报错。下面根据不同的需求场景,给出具体的实现方案:

先修正Top5预测类别的获取代码

首先先把获取每个样本Top5预测类别的代码优化得更简洁易读:

from sklearn.metrics import confusion_matrix
from sklearn.tree import DecisionTreeClassifier
import numpy as np

# 假设你的X(特征)、y(真实标签)、clas(所有类别列表)已定义
DTC = DecisionTreeClassifier()
DTC.fit(X, y)
y_proba = DTC.predict_proba(X)

# 获取每个样本概率最高的Top5类别索引,再转成对应的类别标签
top5_indices = [np.argsort(prob)[::-1][:5] for prob in y_proba]
top5_classes = [[clas[idx] for idx in indices] for indices in top5_indices]

场景1:判断真实类别是否在Top5中(全局二分类指标)

如果你关心的是「模型是否把真实类别排在了Top5预测里」,可以把问题转化为二分类任务:

  • 正例:真实类别出现在该样本的Top5预测中
  • 负例:真实类别未出现在Top5预测中

代码实现:

# 生成二分类预测标签:1表示命中,0表示未命中
y_pred_binary = [1 if true_label in top5 else 0 for true_label, top5 in zip(y, top5_classes)]
# 真实标签:所有样本的真实情况都是「需要命中自己的类别」,所以全为1
y_true_binary = np.ones_like(y_pred_binary)

# 计算二分类的TN/FP/FN/TP
tn, fp, fn, tp = confusion_matrix(y_true_binary, y_pred_binary).ravel()

print(f"全局命中统计:")
print(f"TP(命中真实类别): {tp}")
print(f"FN(未命中真实类别): {fn}")
# 注:这里的TN和FP针对「非真实类别命中」,全局统计意义不大,更适合按单个类别计算

场景2:针对每个类别单独计算二分类指标

如果需要对每个类别单独统计「是否被正确预测在Top5」,可以这样做:

for class_label in clas:
    # 真实标签:1表示样本真实类别是当前类别,0表示不是
    y_true = np.where(y == class_label, 1, 0)
    # 预测标签:1表示当前类别出现在该样本的Top5中,0表示不在
    y_pred = np.array([1 if class_label in top5 else 0 for top5 in top5_classes])
    
    tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
    print(f"类别 {class_label} 的统计:")
    print(f"TP(真实是该类,且Top5包含该类): {tp}")
    print(f"FN(真实是该类,但Top5不包含该类): {fn}")
    print(f"FP(真实不是该类,但Top5包含该类): {fp}")
    print(f"TN(真实不是该类,且Top5不包含该类): {tn}")
    print("-"*30)

场景3:基于Top1预测构建常规多分类混淆矩阵

如果你只是想先取概率最高的Top1预测标签,构建标准的多分类混淆矩阵,代码会更简单:

# 获取每个样本概率最高的Top1预测类别
y_pred_top1 = [clas[np.argmax(prob)] for prob in y_proba]

# 构建多分类混淆矩阵
conf_mat = confusion_matrix(y, y_pred_top1)
print("多分类混淆矩阵(基于Top1预测):")
print(conf_mat)

# 从混淆矩阵中提取每个类别的TP/TN/FP/FN
for i, class_label in enumerate(clas):
    tp = conf_mat[i, i]  # 对角线元素是该类的真阳性
    fn = conf_mat[i, :].sum() - tp  # 该类真实样本中被错误预测的数量
    fp = conf_mat[:, i].sum() - tp  # 被错误预测为该类的其他样本数量
    tn = conf_mat.sum() - tp - fn - fp  # 既不是该类也没被预测为该类的样本数量
    
    print(f"类别 {class_label} 的统计:")
    print(f"TP: {tp}, TN: {tn}, FP: {fp}, FN: {fn}")
    print("-"*30)

为什么你的原有代码会报错?

你原来的代码中,ans是每个样本对应5个类别的二维列表,但confusion_matrix要求输入的y和y_pred都是一维数组(每个样本对应一个标签),维度不匹配就会触发错误,这是你需要先解决的核心问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:21:28