YOLO11论文 | 实用脚本 | 绘制多个实验的loss、mAP@0.5、mAP@0.5:0.95的高级图像【科研必备 + 绘图神器】
💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡
在发表论文的时候,丰富的图标,高级的图像会让你的论文拥有更高的印象分。可能长篇大论并不会让审稿人眼前一亮觉得你的创新点多大的提升,只是和其他人一样陈列一些必要的数据也没有新意,审稿人早已审美疲劳了。然而将这些数据可视化之后能给人带来眼前不一样的体验。对比更加明显,更具有说服力。下面是我自己写的两个脚本,可以画出mAP和loss等关键的实验结果。可以根据你的实验结果的数据画出相应的图像。
专栏地址:YOLO11入门 + 改进涨点——点击即可跳转 欢迎订阅
1. 绘制多个实验的Loss和mAP
import os
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns# 设置 Seaborn 风格
sns.set(style="whitegrid")def plot_metrics_and_loss(experiment_names, metrics_info, loss_info, metrics_subplot_layout, loss_subplot_layout,metrics_figure_size=(15, 10), loss_figure_size=(15, 10), base_directory='../runs/detect/'):"""绘制多个实验的指标和损失曲线图并保存。Parameters:- experiment_names: List[str], 实验名称列表,对应各自的目录名。- metrics_info: List[Tuple[str, str]], 包含指标列名及其标题的元组列表。- loss_info: List[Tuple[str, str]], 包含损失列名及其标题的元组列表。- metrics_subplot_layout: Tuple[int, int], 指标图的子图布局,行数和列数。- loss_subplot_layout: Tuple[int, int], 损失图的子图布局,行数和列数。- metrics_figure_size: Tuple[int, int], 指标图的尺寸,默认值为(15, 10)。- loss_figure_size: Tuple[int, int], 损失图的尺寸,默认值为(15, 10)。- base_directory: str, 基础目录,存放各实验结果的文件夹,默认值为'../runs/detect/'。Returns:- metrics_filename: str, 保存的指标图文件名。- loss_filename: str, 保存的损失图文件名。"""# 定义颜色和线型样式colors = sns.color_palette("deep", len(experiment_names))linestyles = ['-', '--', '-.', ':'] # 如果实验较多,可进一步扩展此列表# 绘制指标图plt.figure(figsize=metrics_figure_size)for i, (metric_name, title) in enumerate(metrics_info):plt.subplot(*metrics_subplot_layout, i + 1)for j, name in enumerate(experiment_names):file_path = os.path.join(base_directory, name, 'results.csv')if os.path.exists(file_path):data = pd.read_csv(file_path)column_name = next((col for col in data.columns if col.strip() == metric_name), None)if column_name:plt.plot(data[column_name], label=name, color=colors[j], linestyle=linestyles[j % len(linestyles)])else:print(f"Warning: Column {metric_name} not found in {file_path}")else:print(f"Warning: File {file_path} does not exist.")plt.xlabel('Epoch')plt.ylabel(title)plt.title(title)plt.grid(True, which='both', linestyle='--', linewidth=0.5) # 增加次网格plt.legend(loc='upper right')plt.tight_layout()metrics_filename = 'metrics_curves.png'plt.savefig(metrics_filename, dpi=300) # 设置较高分辨率plt.show()# 绘制损失图plt.figure(figsize=loss_figure_size)for i, (loss_name, title) in enumerate(loss_info):plt.subplot(*loss_subplot_layout, i + 1)for j, name in enumerate(experiment_names):file_path = os.path.join(base_directory, name, 'results.csv')if os.path.exists(file_path):data = pd.read_csv(file_path)column_name = next((col for col in data.columns if col.strip() == loss_name), None)if column_name:plt.plot(data[column_name], label=name, color=colors[j], linestyle=linestyles[j % len(linestyles)])else:print(f"Warning: Column {loss_name} not found in {file_path}")else:print(f"Warning: File {file_path} does not exist.")plt.xlabel('Epoch')plt.ylabel(title)plt.title(title)plt.grid(True, which='both', linestyle='--', linewidth=0.5) # 增加次网格plt.legend(loc='upper right')plt.tight_layout()loss_filename = 'loss_curves.png'plt.savefig(loss_filename, dpi=300)plt.show()return metrics_filename, loss_filename# 定义要绘制的指标
metrics_info = [('metrics/precision(B)', 'Precision'),('metrics/recall(B)', 'Recall'),('metrics/mAP50(B)', 'mAP50 at IoU=0.5'),('metrics/mAP50-95(B)', 'mAP for IoU Range 0.5-0.95')
]# 定义要绘制的损失
loss_info = [('train/box_loss', 'Training Box Loss'),('train/cls_loss', 'Training Classification Loss'),('train/dfl_loss', 'Training DFL Loss'),('val/box_loss', 'Validation Box Loss'),('val/cls_loss', 'Validation Classification Loss'),('val/dfl_loss', 'Validation DFL Loss')
]if __name__ == '__main__':# 从多个实验中绘制指标和损失曲线metrics_filename, loss_filename = plot_metrics_and_loss(experiment_names=['train', 'train1'], # 这个train和train1是你对应的实验结果保存位置,画图的时候将train修改为ni实验所用的方法。metrics_info=metrics_info,loss_info=loss_info,metrics_subplot_layout=(2, 2),loss_subplot_layout=(2, 3))
样例【数据是随便找的】
- mAP
- Loss
2. 绘制单个的mAP、Loss
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sns# 设置 Seaborn 风格
sns.set(style="whitegrid")def plot_metric(data, metric_name, xlabel='Epochs', ylabel=None, save_name=None):"""绘制并保存指定的指标图像"""plt.figure(figsize=(10, 6))# 使用 Seaborn 颜色调色板colors = sns.color_palette("deep", len(data))linestyles = ['-', '--', '-.', ':']for i, (modelname, values) in enumerate(data.items()):x = range(len(values))plt.plot(x, values, label=modelname, linewidth=2.5, color=colors[i], linestyle=linestyles[i % len(linestyles)])plt.xlabel(xlabel, fontsize=12)plt.ylabel(ylabel if ylabel else metric_name, fontsize=12)plt.title(f'{metric_name} Over Epochs', fontsize=16)plt.legend(loc='best', fontsize=10)# 使用自定义网格plt.grid(True, linestyle='--', alpha=0.7)if save_name:plt.savefig(save_name, dpi=300, bbox_inches='tight')plt.show()def load_data(file_path, csv_column_index=None, txt_split_index=None):"""根据文件类型加载数据,支持CSV和TXT格式"""ext = file_path.split('.')[-1]if ext == 'csv':return pd.read_csv(file_path, usecols=[csv_column_index]).values.ravel()elif ext == 'txt':with open(file_path, 'r') as f:return np.array([float(line.strip().split()[txt_split_index]) for line in f])else:raise ValueError(f"Unsupported file extension: {ext}")if __name__ == '__main__':# 定义各模型的结果文件路径result_dict = {'YOLOv8s': r'../runs/detect/Improved YOLOv8s/results.csv',# 添加其他模型路径,按需启用# 'YOLOv5m': r'path/to/yolov5m/results.csv',# 'YOLOv7': r'path/to/yolov7/results.txt',# ...}# 绘制mAP@0.5map50_data = {model: load_data(path, csv_column_index=6, txt_split_index=10) for model, path in result_dict.items()}plot_metric(map50_data, metric_name='mAP@0.5', ylabel='mAP@0.5', save_name="mAP50.png")# 绘制mAP@0.5:0.95map50_95_data = {model: load_data(path, csv_column_index=7, txt_split_index=11) for model, path in result_dict.items()}plot_metric(map50_95_data, metric_name='mAP@0.5:0.95', ylabel='mAP@0.5:0.95', save_name="mAP50-95.png")# 绘制训练总损失(Loss)loss_data = {}for model, path in result_dict.items():if path.endswith('.csv'):# 分别读取三个损失值并求和box_loss = pd.read_csv(path, usecols=[1]).values.ravel()obj_loss = pd.read_csv(path, usecols=[2]).values.ravel()cls_loss = pd.read_csv(path, usecols=[3]).values.ravel()total_loss = np.round(box_loss + obj_loss + cls_loss, 5)else:# 直接读取txt文件中的总损失total_loss = load_data(path, txt_split_index=5)loss_data[model] = total_lossplot_metric(loss_data, metric_name='Loss', ylabel='Loss', save_name="loss.png")
- mAP@0.5:0.95
- mAP@0.5
- Loss
代码概述
这两个代码片段分别用于数据可视化,尤其是在目标检测YOLO系列算法中,用于对训练过程中的关键指标和损失函数进行跟踪和分析。它们的主要功能是从训练结果中提取数据,并将这些数据绘制成图表,以便更直观地观察和分析模型的性能。
-
绘图
-
功能:该代码主要用于绘制多个深度学习模型在不同训练阶段的关键指标(如mAP@0.5和mAP@0.5:0.95)以及训练损失(Loss)的曲线图。
-
特点:
-
支持从CSV文件中提取数据。
-
使用简单的线条图展示每个模型的性能变化。
-
基础的绘图逻辑和样式,没有过多的美化
-
引入了
Seaborn
的配色方案和风格,提升图表的美观性和一致性。 -
增加了线条的宽度和多样化的线型,使不同模型的曲线更容易区分。
-
对图表的布局、网格、标签和标题进行了优化,使其更清晰、更有层次感。
-
输出高分辨率的图像,适合用于论文的图表部分。
-
-
对发表论文的作用
在科研论文中,清晰、直观的数据可视化对于展示研究成果的有效性至关重要。以下是这两个代码在发表论文中的具体作用:
-
展示模型性能:
-
通过绘制训练过程中关键指标(如mAP)的变化曲线,研究者可以直观地展示不同模型或不同实验设置下的性能比较。这种图表通常用于说明新方法或改进的模型在标准数据集上的表现,帮助评审者和读者快速理解实验结果的有效性。
-
-
分析训练过程:
-
绘制损失曲线可以展示模型在训练过程中如何收敛。对于论文的实验部分,展示这些曲线可以帮助说明模型是否稳定收敛、是否存在过拟合现象等。这些图表对验证实验的合理性和解释实验结果有重要作用。
-
-
提升论文质量:
-
第二个代码片段生成的图表更加美观和专业,适合直接用于论文发表。这不仅提高了图表的可读性,还能增强论文的整体视觉效果,让读者对论文的实验部分留下深刻印象。
-
-
支持多模型对比:
-
通过在同一张图表上展示多个模型的表现,可以有效地对比和讨论不同方法的优劣,帮助构建有力的研究论证。
-
总体而言,这两个代码片段能够显著增强科研论文中数据展示的效果,帮助作者清晰、有力地传达其研究成果的价值。