写在前面的话
最近在使用 detectron2 训练网络的时候,我想在训练的过程中能看到模型对测试集的检测效果,我在yaml配置文件设置的是5000次迭代输出一次对测试集的评估结果,设置代码如下:
cfg.TEST.EVAL_PERIOD = 5000
但是当我训练到第5000个迭代的时候却没有如我设想的出现测试集的评估结果,显示的是一个 warning ,报错如下:
No evaluator found. Use DefaultTrainer.test(evaluators=), or implement its build_evaluator method.
解决方法
这个报错(warning)的出处是 detectron2/engine/defaults.py 里面官方原始build_evaluator 函数
官方原始build_evaluator 函数
@classmethod
def build_evaluator(cls, cfg, dataset_name):
"""
Returns:
DatasetEvaluator or None
It is not implemented by default.
"""
raise NotImplementedError(
"""
If you want DefaultTrainer to automatically run evaluation,
please implement `build_evaluator()` in subclasses (see train_net.py for example).
Alternatively, you can call evaluation functions yourself (see Colab balloon tutorial for example).
"""
)
github上面的对这个issue的讨论: https://github.com/facebookresearch/detectron2/issues/951
参考github上面的答案: See examples https://github.com/facebookresearch/detectron2/blob/master/tools/train_net.py
官方源码的主目录下有一个 train_net.py 文件,里面也有build_evaluator 函数,github上面的答案的意思是参考 train_net.py 里面 build_evaluator 函数的内容.
我的方法比较简单粗暴,我也懒得参考,直接把原始的build_evaluator 函数删除,然后把 train_net.py 里面 build_evaluator 函数复制粘帖到原始的位置
修改后的build_evaluator 函数(跟train_net.py 里面 build_evaluator 函数一样)
@classmethod
def build_evaluator(cls, cfg, dataset_name, output_folder=None):
"""
Create evaluator(s) for a given dataset.
This uses the special metadata "evaluator_type" associated with each builtin dataset.
For your own dataset, you can simply create an evaluator manually in your
script and do not have to worry about the hacky if-else logic here.
"""
if output_folder is None:
output_folder = os.path.join(cfg.OUTPUT_DIR, "inference")
evaluator_list = []
evaluator_type = MetadataCatalog.get(dataset_name).evaluator_type
if evaluator_type in ["sem_seg", "coco_panoptic_seg"]:
evaluator_list.append(
SemSegEvaluator(
dataset_name,
distributed=True,
num_classes=cfg.MODEL.SEM_SEG_HEAD.NUM_CLASSES,
ignore_label=cfg.MODEL.SEM_SEG_HEAD.IGNORE_VALUE,
output_dir=output_folder,
)
)
if evaluator_type in ["coco", "coco_panoptic_seg"]:
evaluator_list.append(COCOEvaluator(dataset_name, cfg, True, output_folder))
if evaluator_type == "coco_panoptic_seg":
evaluator_list.append(COCOPanopticEvaluator(dataset_name, output_folder))
if evaluator_type == "cityscapes_instance":
assert (
torch.cuda.device_count() >= comm.get_rank()
), "CityscapesEvaluator currently do not work with multiple machines."
return CityscapesInstanceEvaluator(dataset_name)
if evaluator_type == "cityscapes_sem_seg":
assert (
torch.cuda.device_count() >= comm.get_rank()
), "CityscapesEvaluator currently do not work with multiple machines."
return CityscapesSemSegEvaluator(dataset_name)
elif evaluator_type == "pascal_voc":
return PascalVOCDetectionEvaluator(dataset_name)
elif evaluator_type == "lvis":
return LVISEvaluator(dataset_name, cfg, True, output_folder)
if len(evaluator_list) == 0:
raise NotImplementedError(
"no Evaluator for the dataset {} with the type {}".format(
dataset_name, evaluator_type
)
)
elif len(evaluator_list) == 1:
return evaluator_list[0]
return DatasetEvaluators(evaluator_list)
注意:一些调用的函数需要 import 进来
'''记得加载函数!!!'''
from detectron2.evaluation import (
CityscapesInstanceEvaluator,
CityscapesSemSegEvaluator,
COCOEvaluator,
COCOPanopticEvaluator,
DatasetEvaluators,
LVISEvaluator,
PascalVOCDetectionEvaluator,
SemSegEvaluator,
verify_results,
)
修改完成后,遇到的问题就解决了!!!
|