Vision Mamba 项目中的 Detectron2 Evaluation 评估模块:从 DatasetEvaluator 到 COCO/LVIS 全量评估体系

原创2026-10-03 09:57:28833 阅读
文章标签:人工智能计算机视觉深度学习预训练微调

Vision Mamba 项目中的 Detectron2 Evaluation 评估模块:从 DatasetEvaluator 到 COCO/LVIS 全量评估体系

本篇文章以仓库 det/docs/modules/evaluation.rst 所索引的 detectron2.evaluation 模块为核心,系统讲解 Vision Mamba(Vim)检测框架中用于模型性能评估的完整技术栈:评估器的抽象基类、评估驱动的统一入口、面向 COCO / LVIS / Panoptic / 语义分割 / Pascal VOC / Cityscapes 的具体评估器实现,以及评估结果如何接入训练流程与命令行。读者读完本文后,将掌握在 detectron2 系框架内为任意检测/分割数据集接入评估器、运行离线评测、解读评估结果,并复现本仓库 det/scripts 下 Vim 检测模型评估脚本的完整能力。

评估模块全景:detectron2.evaluation 包的构成

本仓库的评估代码全部位于 det/detectron2/evaluation/ 目录,该目录的包入口 init.py 统一导出了全部对外 API:

from .cityscapes_evaluation import CityscapesInstanceEvaluator, CityscapesSemSegEvaluator
from .coco_evaluation import COCOEvaluator
from .rotated_coco_evaluation import RotatedCOCOEvaluator
from .evaluator import DatasetEvaluator, DatasetEvaluators, inference_context, inference_on_dataset
from .lvis_evaluation import LVISEvaluator
from .panoptic_evaluation import COCOPanopticEvaluator
from .pascal_voc_evaluation import PascalVOCDetectionEvaluator
from .sem_seg_evaluation import SemSegEvaluator
from .testing import print_csv_format, verify_results

从源码结构看,整个评估体系可分为四个层次:

  1. 抽象基类与驱动入口:DatasetEvaluator(评估器基类)、DatasetEvaluators(多评估器聚合)、inference_on_dataset(推理+评估统一驱动)与 inference_context(模型推理模式上下文),见 evaluator.py;
  2. 具体任务评估器:COCOEvaluator、LVISEvaluator、RotatedCOCOEvaluator、COCOPanopticEvaluator、SemSegEvaluator、PascalVOCDetectionEvaluator、CityscapesInstanceEvaluator、CityscapesSemSegEvaluator;
  3. 性能加速与工具函数:fast_eval_api.py 中的 COCOeval_opt(C++ 加速的 COCO 评估实现)、testing.py 中的 print_csv_format 与 verify_results;
  4. 引擎集成层:DefaultTrainer 通过 EvalHook 在训练中周期性调用评估,tools/train_net.py 与 tools/plain_train_net.py 提供 build_evaluator 工厂函数。

评估器抽象基类:DatasetEvaluator 的三个生命周期方法

所有具体评估器都继承自 DatasetEvaluator,其设计思想是"推理与评估解耦":inference_on_dataset 负责把模型跑完整个测试集,而 DatasetEvaluator 负责逐步累积模型输入/输出并在最后汇总出指标。基类定义了三个可重写的方法:

方法 职责 说明
reset() 开始一轮评估前的准备工作 在每个评估轮次开始前调用,典型实现是清空 self._predictions 列表
process(inputs, outputs) 处理一对输入与输出 若输入输出包含 batch,可按 for input_, output in zip(inputs, outputs) 逐条消费
evaluate() 汇总全部结果并返回指标字典 返回格式为 {task_name: {metric_name: score}},例如 {"bbox": {"AP50": 80}}

基类注释中特别指出,evaluate() 返回的字典格式约定是 train_net.py 所期望的:key 为任务名(如 bbox),value 为指标名到分数的映射。具体评估器可以返回任意格式的字典,只要调用方能够处理即可。

DatasetEvaluators:多评估器聚合分发

DatasetEvaluators 是一个包装类,把多个评估器组合成一个,将 reset()、process()、evaluate() 依次分发给内部所有评估器。其 evaluate() 会合并各评估器返回的结果,且断言不同评估器不得产生同名的 key,避免结果冲突。这为"一个数据集同时评估多个任务"提供了组合能力——例如 COCO Panoptic 场景中同时跑 COCOEvaluator 与 COCOPanopticEvaluator。

推理与评估的统一驱动:inference_on_dataset

inference_on_dataset 是整个评估流程的核心入口函数,它同时完成三件事:推理、指标评估、推理速度基准测试。其签名与行为要点如下:

  • model:可调用对象,接收 data_loader 产出的一个元素并返回输出;若是 nn.Module,会通过 inference_context 临时切到 eval 模式(inference_context 会在退出后恢复原训练状态);
  • data_loader:有确定长度的可迭代对象,其元素作为模型输入;
  • evaluator:传入 DatasetEvaluator、评估器列表或 None。传 None 时内部创建一个空操作评估器,仅做推理速度基准而不评估任何指标;
  • callbacks:可选的回调字典,支持 on_start、before_inference、after_inference、on_end 四个阶段钩子。

流程上的关键实现细节(对应 evaluator.py):

  • 进入 torch.no_grad() 上下文,避免推理产生梯度开销;
  • 预热机制:num_warmup = min(5, total - 1),前若干个 batch 只跑不计时,用于排除 CUDA 初始化、显存分配等干扰,从预热结束处重新起表计时;
  • 分项计时:分别统计 total_data_time(数据加载)、total_compute_time(模型计算,GPU 下会调用 torch.cuda.synchronize() 保证计时准确)、total_eval_time(评估器 process);
  • 周期性日志:每 5 秒至少输出一次 Dataloading / Inference / Eval / Total s per iter 与 ETA;
  • 结束日志格式为 Total inference time: {mm:ss} ({x.xxxxxx} s / iter per device, on {n} devices),该格式注释标明会被 grep 解析,可用于脚本化结果提取;
  • 返回值即 evaluator.evaluate() 的结果,主进程之外的 rank 返回 None 时统一替换为空字典 {}。

COCOEvaluator:bbox / segm / keypoints 三类任务的通用评估器

COCOEvaluator 是使用最广泛的评估器,其定位是"在 COCO 指标之外,还能支持任意边界框检测、实例分割或关键点检测数据集"。指标范围 0~100(区别于 0~1),当无法计算(如没有预测)时返回 -1 或 NaN。

构造参数详解

其构造函数(L47-L96)接收以下参数:

参数 含义与要点
dataset_name 被评估数据集的名字。数据集元数据必须包含 json_file(COCO 格式标注路径),或者该数据集处于 detectron2 标准格式、可自动转换为 COCO 格式
tasks 可评估的任务元组,取值 "bbox"、"segm"、"keypoints"。默认从预测结果自动推断(_tasks_from_predictions 会扫描预测中是否含 segmentation 与 keypoints 字段,见 L210-L220)
distributed 默认 True,表示收集所有 rank 的结果并在主进程执行评估;False 则只评估当前进程
output_dir 可选,用于转储预测结果,包含两个文件:instances_predictions.pth(torch.load 可加载的原始预测)与 coco_instances_results.json(COCO 结果格式的 json)
max_dets_per_image 每张图最大检测数上限,COCO 默认 100;内部会重排为 COCOeval 需要的 <a href="https://link.gitcode.com/i/e42fbe51ea26c4c28dac928b81fe0276" target="_blank">1, 10, max_dets_per_image] 形式([L106-L115),可用于 AP fixed / AP pool 等需要更大上限的指标
use_fast_impl 是否使用快速但非官方的 AP 实现 COCOeval_opt;该实现结果与官方 API 非常接近,但更耗内存,论文发表建议仍用官方 API
kpt_oks_sigmas 关键点 OKS 计算所需 sigmas,为空时使用 COCO 默认值;否则长度应与 ROI_KEYPOINT_HEAD.NUM_KEYPOINTS 一致
allow_cached_coco 是否复用前次验证生成的缓存 COCO json,更换验证数据时应置为 False

评估流程与输出

process()(L157-L175)从每个输入的 image_id 与输出的 instances / proposals 构建预测记录;evaluate()(L177-L208)负责跨进程聚合(comm.gather)、转储预测文件,并分别走 _eval_box_proposals(AR 指标)与 _eval_predictions(AP 指标)两条分支。

生成的指标集(见 _derive_coco_results,L323-L389):

  • bbox / segm:AP、AP50、AP75、APs、APm、APl;
  • keypoints:AP、AP50、AP75、APm、APl;
  • 当类别数大于 1 时,额外输出每个类别的 AP-{category_name} 逐类 AP,并用 tabulate 打印成管道表格。

值得注意的是 instances_to_coco_json 中 mask 用 RLE 编码(counts 需 decode 为 UTF-8 字符串以适配 json 序列化),关键点坐标需减 0.5 与 COCO 标注格式对齐——这是评估精度正确性的关键细节。

其他内置评估器一览

包内还提供了面向不同数据协议与任务类型的评估器:

  • LVISEvaluator:使用 LVIS 官方评估 API 评估 proposal 与实例检测/分割,要求数据集元数据提供 LVIS 格式 json_file,支持 bbox / segm 任务,max_dets_per_image 默认上限为 300(LVIS 数据集约定);
  • COCOPanopticEvaluator:基于 PanopticAPI 评估 Panoptic Quality,并将全景分割预测保存到 output_dir;内部会把连续类别 id 映射回数据集的原始 id(区分 thing / stuff,见 L53-L60);
  • SemSegEvaluator 与 CityscapesInstanceEvaluator / CityscapesSemSegEvaluator:面向语义分割与 Cityscapes 数据集;
  • RotatedCOCOEvaluator:面向旋转框检测(对应 RRPN);
  • PascalVOCDetectionEvaluator:VOC 数据集的 mAP 评估;
  • fast_eval_api.py 中的 COCOeval_opt:把官方 COCO API 的 evaluateImg() 与 accumulate() 用 C++ 实现加速,绕开 Python 层的 evalImgs 计算瓶颈,且直接输出与官方一致的 precision/recall 数据结构。

评估结果的格式化与校验工具

testing.py 提供三个高频工具:

  • print_csv_format(results)(L9-L28):将 {task: {metric: score}} 形式的评估结果打印为以 copypaste: 前缀开头的 CSV 行,便于直接粘贴进表格,且自动跳过含 - 的逐类指标;
  • verify_results(cfg, results)(L31-L65):读取 cfg.TEST.EXPECTED_RESULTS 中声明的 [task, metric, expected, tolerance] 列表,逐一比对实际指标,超出容差即打印错误并以 sys.exit(1) 失败退出,常用于回归测试;
  • flatten_results_dict(results)(L68-L85):把层级嵌套的结果字典展开为 "k1/k2/k3": v 形式的扁平字典,便于 TensorBoard 等标量记录。

与训练引擎的集成:EvalHook 与 build_evaluator

评估并非只能手动调用。在 DefaultTrainer 中,训练流程通过 hooks.EvalHook(cfg.TEST.EVAL_PERIOD, test_and_save_results) 周期性触发评估;其默认实现要求子类实现 build_evaluator(cfg, dataset_name)(L563-L576),并在 test() 中对 cfg.DATASETS.TEST 中的每个数据集执行 inference_on_dataset(model, data_loader, evaluator)(L619)。

相关配置项集中在 det/detectron2/config/defaults.py:

  • TEST.EVAL_PERIOD(默认 0):训练中每隔多少 step 评估一次,0 表示关闭;
  • TEST.EXPECTED_RESULTS(默认空列表):形如 [['bbox', 'AP', 38.5, 0.2]] 的期望结果校验项,配合 verify_results 使用;
  • INPUT.MIN_SIZE_TEST(默认 800)/ INPUT.MAX_SIZE_TEST(默认 1333):测试期图像缩放约束,直接影响推理与评估结果。

两种官方入口脚本

  • tools/train_net.py 的 build_evaluator 依据数据集元数据中的 evaluator_type 自动选择评估器:sem_seg / coco_panoptic_seg 挂 SemSegEvaluator,coco 挂 COCOEvaluator,cityscapes_instance / cityscapes_sem_seg / pascal_voc / lvis 分别对应各自评估器,多个评估器时用 DatasetEvaluators 聚合;默认输出目录为 cfg.OUTPUT_DIR/inference;
  • tools/plain_train_net.py 提供无框架依赖的自写训练循环示范,其 do_test(cfg, model) 手动构建 test loader 与评估器并调用 inference_on_dataset,随后在主进程打印 CSV 格式结果。

在 Vision Mamba(VimDet)项目中的实际应用

本仓库将上述评估体系用于 Vision Mamba 骨干网的检测任务评测。以 det/scripts/eval_vim_tiny_vimdet.sh 为例,离线评估命令为:

python3 tools/lazyconfig_train_net.py \
  --config-file /mnt/bn/lianghuidata/Vim/det/projects/ViTDet/configs/COCO/cascade_mask_rcnn_vimdet_t_100ep_adj1.py \
  --eval-only train.init_checkpoint="/mnt/bn/lianghuidata/Vim/det/released_ckpt/vimdet.pth"

其中 --eval-only 让训练脚本跳过训练直接进入评估路径,train.init_checkpoint 覆盖配置文件中的初始权重为已发布的 VimDet 检查点。对应配置 cascade_mask_rcnn_vimdet_t_100ep.py 通过继承 base 配置并设置 embed_dim = 192、depth = 24 等参数定义 ViM-Tiny 骨干,评估时会经由 lazyconfig_train_net 内部的 build_evaluator 为 COCO 验证集构造 COCOEvaluator,最终输出 bbox / segm 的 AP 指标族。这正体现了"评估模块复用 + 骨干网络可插拔"的工程组织方式:评估链路完全复用 detectron2 标准体系,Vim 只需作为 backbone 实现接入(见 det/detectron2/modeling/backbone/vim.py)。

测试验证与一致性保证

仓库测试对评估模块的正确性做了两层保障:

  1. 评估器接口测试:在 det/tests/data/test_coco_evaluation.py 中,直接实例化 COCOEvaluator,构造包含随机 pred_boxes、scores 与已知类别 id 的 Instances,调用 process() 后验证非法类别 id 会触发断言——确保类别映射的边界行为可预期;
  2. 快慢实现一致性测试:同一文件的 test_fast_eval 对比官方 COCOeval 与加速版 COCOeval_opt 的 precision / recall,断言差异小于 1e-4,为 use_fast_impl=True 的工程加速提供了数值正确性背书。

小结:一套可复用的评估抽象

detectron2.evaluation 模块的核心价值在于将"跑推理"与"算指标"彻底解耦:DatasetEvaluator 三方法抽象让新评估器只需关注数据累积与指标汇总,inference_on_dataset 统一承担预热、计时、聚合与回调,而 build_evaluator 工厂让数据集类型到评估器的映射开箱即用。无论是复现 det/scripts 中的 Vim 检测评估,还是为自定义数据集接入 COCO 风格指标,都可以直接复用本模块,并将其作为了解 detectron2 评估体系设计的最佳参考。

登录后查看全文
Vim