文章目录
- 一、无法使用pycocotools进行评估
- 二、使用pycocotools计算的结果与YOLO自身的mAP差异较大的原因
一、无法使用pycocotools进行评估
yolov7有自己的计算mAP方式,但是在使用pycocotools进行test时,出现了pycocotools unable to run: Results do not correspond to current coco set
。
这个问题是因为yolo在保存json结果时,把image_id保存为了图片的文件名,而不是对应的图片ID。按照COCO数据集的annotation格式来说,每张图片都会有一个image_id,比如这里的task_0056_000000
对应的image_id应该是0。在进行测试时,pycocotools找不到对应的image_id,所以报错。
但是coco数据集的图片命名是以纯数字命名的,所以图片的文件名即可作为ID,所以训练coco数据集不会有这个问题。
所以,应该把yolo保存的json文件中的image_id做一个转换,在test.py
文件增加一段代码,来获取文件名和id的键值对。
with open(anno_json, "r") as f:
anns = json.load(f)
imagenames2id = {ann["file_name"].split(".")[0]: ann["id"] for ann in anns["images"]}
for pre_ann in jdict:
pre_ann["image_id"] = imagenames2id[pre_ann["image_id"]]
增加代码后,即可获取正确的JSON格式数据。
其实这里可以更改
anno_json
,设置为自己保存验证集annotation的路径即可
二、使用pycocotools计算的结果与YOLO自身的mAP差异较大的原因
首先,强烈推荐在传命令行参数:--data data/coco.yaml
时,如果是训练自己的数据集,最好新建或者重命名改yaml文件并且不要以coco.yaml结尾
解决了问题一,可以计算出结果,但是pycocotools计算得到的结果与yolo计算的相差非常大。yolo计算得到mAP时27.3,但是此时调用coco的api计算得到的只有0.005
包括YOLO V7的github上也有人提issue,见:COCO eval produce wrong results
通过查看源码,判断应该是命令行参数:--data data/coco.yaml
的问题,不管是在训练时还是在测试时,都需要传入数据集的YAML
文件,当时是直接修改项目中自带的 data/coco.yaml
,没有新建一个YAML文件。
这时候问题来了,在test.py
文件中,有这么一个判断(其实是不是改成 data == "coco.yaml"
更合理):
如果命令行参数data
以coco.yaml
结尾,那么is_coco变量就为True
。也就是默认你是在训练coco数据集,而众所周知,coco数据集里面的类别ID是不连续的,coco总共只有80类,但是ID最大值却为91,这时候问题就出现了,我们自己的数据集类别ID在转化成coco格式时是从0开始的,并且是连续的,所以在保存JSON文件时,如果你是coco数据集,会帮你做一个映射也就是,红框中的coco91class
,会帮你把0-79
的ID(即80类)映射成1-91
。
映射方式如下,即返回一个列表,进行索引,可以看出索引为0时,值已经变成1了。但我们的类别索引应该是不用映射的,但是我们传入:--data data/coco.yaml
,此时is_coco
已经为True,所以自动帮我们进行了映射,映射以后类别信息就已经错了,所以导致mAP极低,与yolo计算的相差很大(虽然两者的计算方式不同本身会产生误差)。
在训练自己的数据集时,我们只需将is_coco = Fasle
即可。更加推荐在传命令行参数:--data data/coco.yaml
时,如果是训练自己的数据集,最好新建或者重命名改yaml文件并且不要以coco.yaml结尾
即使自己标注的数据集类别ID也是从1开始,也推荐这样做,毕竟coco数据集里面有缺失值,与yolo计算的mAP误差较大可以考虑是由于映射造成的。
更新代码后,mAP计算应该是正常了,与yolo计算的有0.3的误差。