新手求助:如何为YOLOv4目标检测模型计算mAP、F1分数及混淆矩阵?
针对YOLOv4-GPU模型计算mAP、F1分数及混淆矩阵的实现方案
一、准备评估数据集
- 确保验证集包含图片文件和对应的YOLO格式标注文件:每个图片对应一个同名
.txt文件,每行格式为class_id x_center y_center width height(坐标已归一化)。 - 将验证集放在指定目录(如
data/validation),并在data/classes.txt中按顺序列出所有类别名称。
二、调整仓库配置参数
打开core/config.py,修改以下关键配置:
- 设置
TEST_PATH为你的验证集路径; - 确保
CLASSES指向正确的classes.txt文件; - 根据GPU显存调整
BATCH_SIZE(推荐8或16); - 设定
CONF_THRESH(如0.5,过滤低置信度检测框)和IOU_THRESH(如0.5,用于NMS和指标计算)。
三、计算mAP(平均精度均值)
步骤1:导出模型检测结果
修改或编写脚本,遍历验证集图片,将检测结果保存为YOLO格式的.txt文件(存放在detections/目录):
import cv2 from core.yolov4 import YOLOv4 from core.utils import load_class_names # 初始化模型 class_names = load_class_names("data/classes.txt") yolo = YOLOv4(weights="data/yolov4.weights", class_names=class_names, gpu=True) # 遍历验证集图片 validation_img_paths = ["data/validation/img1.jpg", "data/validation/img2.jpg"] # 替换为你的图片路径列表 for img_path in validation_img_paths: img = cv2.imread(img_path) img_h, img_w = img.shape[:2] # 执行检测 detections = yolo.detect(img, conf_thresh=0.5, iou_thresh=0.5) # 保存检测结果 det_txt_path = f"detections/{img_path.split('/')[-1].replace('.jpg', '.txt')}" with open(det_txt_path, "w") as f: for det in detections: class_id = det["class_id"] x, y, w, h = det["bbox"] # 转换为YOLO归一化格式 x_center = (x + w/2) / img_w y_center = (y + h/2) / img_h width = w / img_w height = h / img_h f.write(f"{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\n")
步骤2:计算mAP
使用YOLO标准mAP计算逻辑:
- 对每个类别,遍历所有标注框和检测框,按置信度排序检测框;
- 逐个匹配检测框与标注框(IOU>阈值则视为正确),统计TP(真阳性)、FP(假阳性);
- 计算每个类别的Precision-Recall曲线,通过曲线下面积得到AP;
- 所有类别的AP取平均值即为mAP。
可以直接复用仓库中自带的calculate_map.py(若存在),或基于上述逻辑编写脚本。
四、计算F1分数
F1分数是精确率(Precision)和召回率(Recall)的调和均值,公式为:F1 = 2*(Precision*Recall)/(Precision+Recall)
统计核心指标
- TP:检测框与标注框IOU>阈值且类别匹配;
- FP:无对应标注框的检测框,或类别不匹配的检测框;
- FN:未被检测到的标注框;
基于这些指标计算:
# 假设已统计得到全局TP、FP、FN precision = TP / (TP + FP) if (TP + FP) > 0 else 0 recall = TP / (TP + FN) if (TP + FN) > 0 else 0 f1_score = 2 * (precision * recall) / (precision + recall) if (precision + recall) > 0 else 0 print(f"F1 Score: {f1_score:.4f}")
五、生成混淆矩阵
混淆矩阵用于展示真实类别与预测类别的匹配情况,可借助sklearn实现:
from sklearn.metrics import confusion_matrix import matplotlib.pyplot as plt import os true_labels = [] pred_labels = [] class_names = load_class_names("data/classes.txt") # 收集真实标签和预测标签 for img_path in validation_img_paths: # 读取真实标签 label_path = img_path.replace(".jpg", ".txt") if os.path.exists(label_path): with open(label_path, "r") as f: for line in f: true_labels.append(int(line.split()[0])) # 读取预测标签 det_path = f"detections/{img_path.split('/')[-1].replace('.jpg', '.txt')}" if os.path.exists(det_path): with open(det_path, "r") as f: for line in f: pred_labels.append(int(line.split()[0])) # 补充FN:未被检测到的真实标签(需额外逻辑匹配,示例简化处理) # 生成混淆矩阵 cm = confusion_matrix(true_labels, pred_labels, labels=range(len(class_names))) # 可视化混淆矩阵 plt.figure(figsize=(12, 10)) plt.imshow(cm, interpolation="nearest", cmap=plt.cm.Blues) plt.title("Confusion Matrix") plt.colorbar() tick_marks = range(len(class_names)) plt.xticks(tick_marks, class_names, rotation=45) plt.yticks(tick_marks, class_names) plt.xlabel("Predicted Class") plt.ylabel("True Class") plt.savefig("confusion_matrix.png") plt.show()
六、注意事项
- 验证集标注格式必须严格符合YOLO要求,避免坐标未归一化、类别ID错误等问题;
CONF_THRESH和IOU_THRESH的取值会直接影响所有指标结果,建议根据任务需求多次调试;- 若GPU显存不足,可减小
BATCH_SIZE或降低输入图片分辨率; - 优先查看仓库自带的评估脚本(如
eval.py),部分逻辑已封装,可直接调用。
内容的提问来源于stack exchange,提问作者Shaik
相关产品推荐
相关产品推荐

