图像Precision/Recall报错:指标不支持multilabel-indicator与multiclass混合目标
问题根因排查
- 直接触发报错的原因:
sklearn的分类指标函数不支持混合传入multiclass和multilabel-indicator两类目标类型,两类输入的形状规则完全不兼容。- 你在指标函数内部对传入的输出值执行了
torch.max(op, dim=1)操作,将原本[768,1024]的二维矩阵压缩为长度768的一维向量,被sklearn识别为multiclass类型 - 你传入的标签值仍保持[768,1024]的二维矩阵形状,被
sklearn识别为multilabel-indicator类型 - 你虽然在图像加载环节将两个原始张量调整为相同的二维形状,但函数内部的维度操作导致最终传入指标函数的输入形状不匹配,因此即使视觉上形状对齐仍会报错。
- 你在指标函数内部对传入的输出值执行了
- 深层逻辑错误:
- 维度操作适用场景错误:
- 原函数中
torch.max(op, dim=1)的维度选择错误:若输入是无batch维的[C, H, W]格式模型输出,类别通道维是dim=0而非dim=1,沿着高度/宽度维度取max得到的结果完全不符合逐像素预测的要求 - 你传入的
op已经是没有通道维的二维单通道图,此时执行dim=1的max操作,会将二维矩阵压缩为一维向量,直接引发输入类型不匹配的报错。
- 原函数中
- 缺少必需的展平步骤:逐像素计算分类指标时,需要把[H,W]形状的预测、标签矩阵全部展平为一维向量,
sklearn的分类指标不支持直接输入二维图像矩阵(会被自动识别为多标签输入,而非逐像素分类输入)。 - 数据加载逻辑混淆:你将单通道PNG标注图作为模型输出,将三通道彩色JPG图作为真值,对三通道图按通道维做argmax得到的结果并非逐像素的真实类别标注,会进一步导致指标计算结果失真。
- 变量名冲突:原代码中自定义的
f1函数和存储计算结果的f1变量重名,会覆盖函数定义导致后续调用错误。
- 维度操作适用场景错误:
可运行的修正方案
- 第一步:对齐输入格式
- 模型输出:若为三通道logits格式
[3, H, W],在通道维(dim=0)做argmax,得到形状为[H, W]的逐像素预测类别矩阵 - 真值标注:直接读取单通道标注图(形状为
[H, W]),每个像素值对应真实类别
- 模型输出:若为三通道logits格式
- 第二步:调整指标计算逻辑
- 去掉原函数中针对无通道维输入的
torch.max操作 - 把预测矩阵、标签矩阵全部展平为一维张量,再传入
sklearn的指标函数
- 去掉原函数中针对无通道维输入的
- 修正后的完整代码示例:
from sklearn.metrics import precision_score, recall_score, f1_score import torch import numpy as np from PIL import Image from torchvision import transforms def precision(preds, labels): # 展平为一维向量,匹配sklearn输入要求 preds_flat = preds.flatten() labels_flat = labels.flatten() return torch.tensor(precision_score(labels_flat, preds_flat, average='micro')) def recall(preds, labels): preds_flat = preds.flatten() labels_flat = labels.flatten() return torch.tensor(recall_score(labels_flat, preds_flat, average='weighted', zero_division=1)) def f1_score_func(preds, labels): preds_flat = preds.flatten() labels_flat = labels.flatten() return torch.tensor(f1_score(labels_flat, preds_flat, average='weighted')) # 读取模型输出(三通道logits格式) img_model = Image.open('model_output.png') numpydata_model = np.array(img_model).astype('uint8') numpydata_model = transforms.ToTensor()(numpydata_model) # 对通道维做argmax得到逐像素预测类别 preds = torch.argmax(numpydata_model, dim=0).squeeze() print("final preds shape", preds.shape) # 读取真值标注(单通道) img_gt = Image.open('gt_label.png') numpydata_gt = np.array(img_gt).astype('uint8') labels = torch.from_numpy(numpydata_gt) print("final labels shape", labels.shape) prec = precision(preds, labels) print("precision is", prec) rec = recall(preds, labels) print("recall is", rec) f1_score_val = f1_score_func(preds, labels) print("f1 score is", f1_score_val)
注意事项
- 不要把带通道维的输出和已经argmax完的二维矩阵传给原指标函数,否则会重复执行取max的操作,得到错误结果
- 若计算时仍出现维度不匹配报错,可通过
print(preds.shape, labels.shape)确认两个矩阵展平后的长度完全一致
内容的提问来源于stack exchange,提问作者xubi
相关产品推荐
相关产品推荐

