【YOLO系列result中的map、loss、pr、F1绘图】根据v5、v8、v7训练后生成的result文件用matplotlib进行绘图

文章介绍了如何解析YOLOv7的result.txt和YOLOv5/v8的result.csv文件,重点关注了mAP、Loss等指标,并提供了代码示例来绘制不同模型在训练过程中的mAP和总Loss变化图。此外,还提及了PR和F1曲线的绘制方法,以及如何通过val.py或test.py生成pr.csv文件进行进一步的分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 效果图

在这里插入图片描述

2. 认识result内容

2.1 YOLOv7的result.txt

0/299      14.7G         0.07522         0.009375          0.02266          0.1073                    58            640           0.0002958    0.1458   0.0002676     4.469e-05          0.1005          0.01098       0.02545
训练轮数   GPU消耗     train/box_loss   train/obj_loss    train/cls_loss  train/total_loss     本轮中数据中目标数量   输入图片大小         P          R         mAP@.5     mAP@.5:.95        val/Box_loss  val/obj_loss   val/cls_loss

在这里插入图片描述

2.2 YOLOv5 | YOLOv8的result.csv(每列含义相同)

每列的含义是相同的,可能因为是同一个作者写的代码,所以result.csv的保存内容没有发生改变

YOLOv5

在这里插入图片描述

YOLOv8

在这里插入图片描述

3. 代码(只有map和loss)

  • 需要更改的地方result_dict中的内容,每行表示的是模型名称该模型训练得到的result文件地址
  • v5、v8都是csv格式的,v7是txt格式的
  • 需要关注的重点地方:下面代码中关于下标的注释位置,下标都是从0开始向右依次加一的
  • plt.savefig("mAP50.png", dpi=600) # dpi可设为300/600/900,表示存为更高清的矢量图
  • data = pd.read_csv(res_path, usecols=[6]).values.ravel() 表示读取csv文件后,只取下标为6的一列的值values,并将值ravel()展平为一维数组(如果想要绘制result.csv/result.txt中的其他值,直接改为对应的下标即可。例如想要绘制train/box_loss,则绘制map50中的6改为1,10改为2)
  • plt.plot(x, data, label=modelname, linewidth='1') # 线条粗细设为1
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

if __name__ == '__main__':
    # 列出待获取数据内容的文件位置
    # v5、v8都是csv格式的,v7是txt格式的
    result_dict = {
        'YOLOv5m': r'C:\Users\dadandan\Desktop\workspace_temp\NeimengA_train_resultcsv\yolov5m\results.csv',
        'YOLOv7': r'C:\Users\dadandan\Desktop\workspace_temp\NeimengA_train_resultcsv\yolov7\results.txt',
        'YOLOv7-tiny': r'C:\Users\dadandan\Desktop\workspace_temp\NeimengA_train_resultcsv\yolov7-tiny\results.txt',
        'YOLOv7-tiny-large': r'C:\Users\dadandan\Desktop\workspace_temp\NeimengA_train_resultcsv\yolov7-tiny-large\results.txt',
        'YOLOv7-tiny-PConv': r'C:\Users\dadandan\Desktop\workspace_temp\NeimengA_train_resultcsv\yolov7-tiny-PConv\results.txt',
        'YOLOv7-tiny-GhostNetv2': r'C:\Users\dadandan\Desktop\workspace_temp\NeimengA_train_resultcsv\yolov7-tiny-GhostNetv2\results.txt',
        # 'YOLOv8s': r'C:\Users\dadandan\Desktop\workspace_temp\NeimengA_train_resultcsv\yolov8s\results.csv',
        'YOLOv7-tiny-large-GhostNetv2': r'C:\Users\dadandan\Desktop\workspace_temp\NeimengA_train_resultcsv\yolov7-tiny-large-GhostNetv2\results.txt',
        'YOLOv7-GhostNetv2': r'C:\Users\dadandan\Desktop\workspace_temp\NeimengA_train_resultcsv\yolov7-GhostNetv2\results.txt',
        'YOLOv7-FasterNet': r'C:\Users\dadandan\Desktop\workspace_temp\NeimengA_train_resultcsv\yolov7-FasterNet\results.txt'
    }

    # 绘制map50
    for modelname in result_dict:
        res_path = result_dict[modelname]
        ext = res_path.split('.')[-1]
        if ext == 'csv':
            data = pd.read_csv(res_path, usecols=[6]).values.ravel()    # 6是指map50的下标(每行从0开始向右数)
        else:   # 文件后缀是txt
            with open(res_path, 'r') as f:
                datalist = f.readlines()
                data = []
                for d in datalist:
                    data.append(float(d.strip().split()[10]))   # 10是指map50的下标(每行从0开始向右数)
                data = np.array(data)
        x = range(len(data))
        plt.plot(x, data, label=modelname, linewidth='1')   # 线条粗细设为1

    # 添加x轴和y轴标签
    plt.xlabel('Epochs')
    plt.ylabel('mAP@0.5')
    plt.legend()
    plt.grid()
    # 显示图像
    plt.savefig("mAP50.png", dpi=600)   # dpi可设为300/600/900,表示存为更高清的矢量图
    plt.show()


    # 绘制map50-95
    for modelname in result_dict:
        res_path = result_dict[modelname]
        ext = res_path.split('.')[-1]
        if ext == 'csv':
            data = pd.read_csv(res_path, usecols=[7]).values.ravel()    # 7是指map50-95的下标(每行从0开始向右数)
        else:
            with open(res_path, 'r') as f:
                datalist = f.readlines()
                data = []
                for d in datalist:
                    data.append(float(d.strip().split()[11]))   # 11是指map50-95的下标(每行从0开始向右数)
                data = np.array(data)
        x = range(len(data))
        plt.plot(x, data, label=modelname, linewidth='1')

    # 添加x轴和y轴标签
    plt.xlabel('Epochs')
    plt.ylabel('mAP@0.5:0.95')
    plt.legend()
    plt.grid()
    # 显示图像
    plt.savefig("mAP50-95.png", dpi=600)
    plt.show()

    # 绘制训练的总loss
    for modelname in result_dict:
        res_path = result_dict[modelname]
        ext = res_path.split('.')[-1]
        if ext == 'csv':
            box_loss = pd.read_csv(res_path, usecols=[1]).values.ravel()
            obj_loss = pd.read_csv(res_path, usecols=[2]).values.ravel()
            cls_loss = pd.read_csv(res_path, usecols=[3]).values.ravel()
            data = np.round(box_loss + obj_loss + cls_loss, 5)    # 3个loss相加并且保留小数点后5位(与v7一致)

        else:
            with open(res_path, 'r') as f:
                datalist = f.readlines()
                data = []
                for d in datalist:
                    data.append(float(d.strip().split()[5]))
                data = np.array(data)
        x = range(len(data))
        plt.plot(x, data, label=modelname, linewidth='1')

    # 添加x轴和y轴标签
    plt.xlabel('Epochs')
    plt.ylabel('Loss')
    plt.legend()
    plt.grid()
    # 显示图像
    plt.savefig("loss.png", dpi=600)
    plt.show()

4. 关于绘制PR和F1,查看这篇文章

<think>嗯,用户问的是YOLO模型的PR曲线如何生成或优化。首先,我需要回忆一下PR曲线的基本概念。PR曲线是精确率(Precision)和召回率(Recall)在不同置信度阈值下的关系图。对于目标检测模型如YOLO来说,生成PR曲线需要计算不同阈值下的精确率和召回率,然后绘制出来。 接下来,我得想生成PR曲线的步骤。首先,模型在测试集上进行推理,得到所有预测框的置信度分数和类别信息。然后,需要为每个类别单独处理,因为PR曲线通常是按类别绘制的。对于每个预测框,要和真实标注进行匹配,判断是真正例(TP)、假正例(FP)还是假负例(FN)。这时候需要使用交并比(IoU)作为匹配的标准,通常IoU阈值设为0.5。 然后是排序问题,预测框需要按置信度降序排列,这样在不同的置信度阈值下,可以计算对应的TP和FP数量。累积计算这些数值,就能得到不同阈值下的精确率和召回率点,连接起来就是PR曲线了。 优化PR曲线的话,可能需要调整模型的置信度阈值,或者改进模型本身。比如,数据增强可以提升模型对不同场景的适应能力,从而减少漏检和误检。调整非极大值抑制(NMS)的参数,比如IoU阈值,可能会影响检测框的合并,进而影响精确率和召回率。另外,模型结构优化,比如使用更先进的Backbone或者注意力机制,也能提升检测性能。类别不平衡的问题可以通过调整损失函数的权重,或者采用Focal Loss来缓解。 不过用户提供的引用里提到了量化方法、损失函数比如MSE和MAE,以及特征图的处理。虽然这些引用可能不是直接相关,但可以考虑是否有些内容可以关联。比如,引用3提到MSE和MAE作为损失函数,可能影响模型训练,进而影响PR曲线。如果YOLO的损失函数优化了,可能会提升检测效果,从而优化PR曲线。另外,引用4中提到特征图的使用,检测头可能影响检测的准确性,进而影响PR曲线的生成。 需要确保回答的结构清晰,分步骤说明生成和优化的方法,同时结合可能的引用内容。比如在优化部分提到损失函数的选择,可以引用引用3中的内容,说明不同损失函数对异常值的鲁棒性,进而影响模型性能。或者特征图的处理(引用4)如何影响检测头的准确性,从而优化PR曲线。 还要注意用户可能的问题是否涉及具体实现细节,比如代码示例,但用户的问题更偏向于方法,所以可能需要给出步骤而不是代码。不过示例中的快速排序有代码,可能用户希望有相关代码,但YOLOPR生成代码可能比较复杂,是否要提供?或者指导用户使用现有工具如COCO API来计算PR曲线。 此外,用户可能想知道如何解读PR曲线,或者如何根据曲线调整模型,比如AP(平均精度)的计算,但问题集中在生成和优化,所以可能需要集中在这些方面。 总结一下,回答的结构应该是: 1. PR曲线的生成步骤: - 模型推理,收集预测结果 - 计算TP、FP、FN - 排序预测,计算精确率和召回率 - 绘制曲线 2. 优化方法: - 调整置信度阈值 - 数据增强 - 调整NMS参数 - 模型结构优化 - 处理类别不平衡 可能结合引用中的相关内容,比如损失函数的选择(引用3)或特征图处理(引用4)对模型性能的影响。</think>### YOLO模型PR曲线的生成与优化方法 PR曲线(精确率-召回率曲线)是评估目标检测模型性能的重要工具,其生成和优化需遵循以下步骤: --- #### **一、PR曲线的生成步骤** 1. **模型推理与数据收集** - 在测试集上运行YOLO模型,记录所有预测框的置信度$s_i$、类别$c_i$和边界框坐标。 - 同时加载测试集的真实标注(GT),包括目标类别和边界框坐标。 2. **匹配预测与真实标注** - 对每个类别独立处理,计算交并比(IoU): $$ \text{IoU} = \frac{\text{预测框} \cap \text{真实框}}{\text{预测框} \cup \text{真实框}} $$ - 若IoU ≥ 0.5(标准阈值)且类别正确,则判定为真正例(TP),否则为假正例(FP)[^4]。 - 未被匹配的真实框视为假负例(FN)。 3. **排序与累积统计** - 将同一类别的所有预测框按置信度降序排列。 - 遍历排序后的列表,计算每个置信度阈值下的累积TP和FP数量,进而得到精确率(Precision)和召回率(Recall): $$ \text{Precision} = \frac{\text{TP}}{\text{TP} + \text{FP}}, \quad \text{Recall} = \frac{\text{TP}}{\text{TP} + \text{FN}} $$ 4. **曲线绘制** - 以Recall为横轴、Precision为纵轴,绘制所有阈值下的点并连接成曲线。 --- #### **二、PR曲线的优化方法** 1. **调整置信度阈值** - 选择使F1分数(Precision和Recall的调和平均)最大的阈值: $$ F1 = \frac{2 \cdot \text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}} $$ 2. **改进模型性能** - **数据增强**:增加遮挡、光照变化等场景的训练数据,减少FP和FN[^2]。 - **NMS优化**:调整非极大值抑制(NMS)的IoU阈值,平衡检测框的数量与质量。 - **模型结构改进**:使用更高效的特征提取网络(如Transformer)或注意力机制,提升特征图质量[^4]。 3. **处理类别不平衡** - 对长尾分布类别,采用Focal Loss或重加权损失函数,减少高频类别对低频类别的压制[^3]。 --- #### **三、工具与代码示例** 使用COCO API或PyTorch内置函数可自动生成PR曲线: ```python from pycocotools.coco import COCO from pycocotools.cocoeval import COCOeval # 加载预测结果和真实标注 coco_gt = COCO("annotations.json") coco_dt = coco_gt.loadRes("predictions.json") # 评估并生成PR曲线 evaluator = COCOeval(coco_gt, coco_dt, "bbox") evaluator.evaluate() evaluator.accumulate() evaluator.summarize() ``` ---
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟孟单单

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值