mmdetection最小复刻版(三):数据分析神兵利器
AI编辑:深度眸
本文主要说明mmdetection-mini到目前为止已经新增的一些好用的工具,原理方面会稍微提一句,主要是说明使用方法,这些工具是用来分析数据,分析模型,分析模型预测质量的,在实际项目中针对自己的数据进行可视化分析非常有用,例如感受野计算、特征图分析、loss函数分析、推理时间分析等等。
这里写的是到目前为止,后面也会新增新的,欢迎各位客官提出新的想法!
github:
https://github.com/hhaAndroid/mmdetection-mini
欢迎star
1 数据浏览browse_dataset
给你一个新的目标检测项目,转化为coco格式,设置好cfg后,难道不需要看下label和bbox是否正确?不需要看下数据增强策略是否合适?我想作为一个有经验的工程师必然少不了这个步骤。 故browse_dataset可以对datasets吐出的数据进行可视化检查,看下是否有错误。这个工具我是直接从mmdetection里面copy过来的,并修复了在voc那种数据的配置上面出错的bug。
用法非常简单,只需要传入cfg文件即可,以coco数据为例,如下所示
可视化效果看起来比较难看,不过我懒得改了。
2 coco数据可视化visualize_coco
上面的可视化效果有点糟糕,既然是coco,那可以调用coco里面的api进行可视化。我对其进行了扩展,可以仅仅显示bbox,为啥要扩展?因为在coco格式中如果没有mask数据是无法显示的,但是例如voc数据即使转化为coco格式,也是不存储mask的,此时用coco api进行显示,是啥都没有的。
其核心参数有两个:
only_bbox为True表示仅仅可视化bbox,其余label不显示
show_all为Ture表示所有类别都显示,否则通过指定category_name来确定显示类别
用法在main函数里面。以coco为例, only_bbox=False,也就是coco默认的显示格式:
only_bbox=True,也就是扩展模式:
这个显示就酷炫很多了。
如果show_all=Fasle,且category_name='bicycle'(一共有多少类别会同时打印出来,你就可以直接copy了)
如果不想bbox内部填充,可以is_filling设置为False即可
3 任意格式转化为coco格式工具CocoCreator
对于目标检测,我都推荐大家转化为coco格式进行分析和训练。故咋能没有任意数据转化为coco的工具呢? 这个工具核心类在mmdet/cv_core/utils/coco_creator.py,其中嵌入了github上面的pycococreatortools函数,我进行了修改使其能够适用多种情况。
但是考虑到场景实在是太多了,不知道你的格式长啥样子,所以我这个工具其实有点名不副实,用起来需要掌握点东西才行。慢慢完善吧,我个人精力有限,我自己用还蛮习惯的,大家凑合用吧。
以我提供的tools/convert/widerface2coco.py为例说明用法,要生成coco格式数据需要三个步骤,分别对应CocoCreator的三个api,我仔细说下。
1 准备categories字段
首先你需要手动写categories,里面存储的是类名,例如:
[
{
'id': 1, # 类别1
'name': 'power',
'supercategory': 'object',
}
{
'id': 2, # 类别2
'name': 'circle',
'supercategory': 'shape',
}
]
上面显示的是两个类的写法。如果多个类,自己追加List就行。但是这种写法有个弊端:当类别很多时候,会累死人的!改进办法应该是通过读取标注文件,然后追加,类似voc2coco脚本一样。
2 遍历图片和label
如何遍历,那就是你自己的事情了,我在cv_core里面提供了遍历函数traverse_file_paths,很好用。
3 处理数据
第一个核心api是coco_creater.create_image_info(image_id, imFilename, image.size)
image_id是用来表示图片编号的,你可以简单从1开始累加,也可以像coco一样直接采用文件名然后Int即可,因为有些图片命名格式无法变成image_id,故我需要你自己传入。class_id是类别id,你自己从categories里面取就行
第二个核心api是coco_creater.create_annotation_info,他可以传入bbox格式,也可以传入二值mask。传入mask时候就不需要传入bbox了,因为基于mask会自动计算出Bbox。 同样的,对于一张图片中有多个物体的场景,需要遍历各个实例,并且通过segmentation_id来区分,所以这个字段也是你自己累加就行。
4 保存
在所有图片遍历完成后,直接coco_creater.dump()就可以保存为json输出了。
5 可视化
为了检查生成的json文件是否正确,可以用上一个小节的coco可视化工具进行检查。
以wider face为例,转化后可视化如下:
4 anchor分析工具anchor_analyze
这个工具其实意义不是很大,只能提供一些直观的感觉。这个工具的作用是对AnchorGenerator生成的anchor进行可视化,主要是可以分析出anchor分布、anchor大小和anchor比例等等。
其用法非常简单,只需要填入anchor相关配置即可,例如yolov3:
stride = [32, 16, 8]
anchor_generator_cfg = dict(
type='YOLOAnchorGenerator',
base_sizes=[[(116, 90), (156, 198), (373, 326)],
61), (62, 45), (59, 119)],
13), (16, 30), (33, 23)]],
strides=stride)
如果觉得显示的过多不好看,可以自己设置显示个数。
5 数据分析工具dataset_analyze
数据分析工具目前支持三个:wh比例分析;wh尺寸分析和kmean算法。本来可以直接对coco的json文件进行分析的,但是基于以下几点考虑,最终采用了dataloader:
网络真正运行的图片size不是原始coco文件里面的size,肯定会进行前处理
训练过程中会进行图片增强,考虑增强后的图片和label才是合理的
dataloader可以利用work num加速,比单纯读取json文件遍历快很多
基于以上几点考虑,我这里分析的wh是dataloader输出的图片bbox的宽高。先通过dataloader进行遍历,收集所有bbox的wh,并进行后续分析。k考虑到跑一遍dataloader要很久,故自动会保存wh矩阵,下一次统计数据时候就不需要经过dataloader了。
1. wh比例分析
wh宽高比例分析是指对所有gt bbox的wh进行高宽比例统计,分成两个部分,分别是h/w>=1和h/w<1两个,效果如下:
以coco数据集,配置文件为retinanet_r50_fpn_coco.py,其核心参数img_scale=(600, 800)为例进行分析:
上图是h/w>=1,下图是h/w<1,可以看出数据高宽分布主要是1.0、2.0、3.0、0.7、0.9这些,也就是说其实大部分物体都是高大于宽的,实际上也很合理,因为大部分自然场景下物体例如人都是高大于宽的。打印输出:
# 按照num数从大到小排序输出
hw_ratio:(1.0, 2.0, 0.7, 3.0, 0.8, 0.9, 0.6, 0.5, 0.4, 0.3, 0.2, 4.0, 0.1, 5.0, 6.0, 7.0, 8.0)
num:(27340, 11147, 4524, 4374, 4206, 4179, 4024, 3543, 3116, 2391, 1451, 1357, 591, 532,
通过这种图启发我们,其实在设置anchor的wh比例时候不一定要对称设置,例如常规的设置是(0.5,1.0,2.0),而是可以对于coco数据集设置为(0.5,0.7,1.0,2.0,3.0)或许更加合适。
2. wh尺寸分析
wh scale参数也很关键,但是不好意思,我目前没有发现很好的可视化手段,什么叫做很好的可视化手段:换一个新数据集情况下,只需要运行我的脚本生成几个图表,你立刻就能够设置wh比例和wh尺度参数了。
但是目前我还没有想到非常好的可视化手段,欢迎各位朋友提出改进意见。
我只是简单绘制了w和h尺度的直方图而已,不太直观。
3. anchor计算
这部分是为yolo系列算法设计的,通过本脚本可以直接生成指定数目的anchor。
假设设置为9个anchor,那么在coco部分数据集上打印如下:
Accuracy: 61.29%
K anchors:
[[8, 12], [19, 23], [26, 54], [54, 32], [54, 84], [136, 85], [88, 176], [207, 245], [468, 435]]
由于gt bbox的宽高变化比较大,故kmean后准确率才61.29%。大家可以多运行几次,有可能会得到更好一点的结果。
总之,这个数据分析工具dataset_analyze还不太完善,欢迎大家提出想法。
6 推理时间计算工具infertime_analyze
当我们设计了一个新网络结构的时候,首先第一个任务就是分析耗时。希望知道这个改进对推理速度有多少影响?并且为了方便对mmdetection-mini里面的所有算法进行公平时间对比,需要一个推理时间计算工具。
该工具需要输入配置cfg用来确定算法模型,还需要输入图片size。需要特别注意的是我们仅仅是为了计算前向推理时间,故需要采用forward重写方法实现。
以yolov3,rtx1070ti硬件为例,脚本运行后打印如下:
# input_shape = (4, 3, 320, 320)
batch_avg_time=39.06158ms,one_avg_time==9.76539ms
# input_shape = (8, 3, 320, 320)
batch_avg_time=72.22127ms,one_avg_time==9.02766ms
# input_shape = (1, 3, 320, 320)
batch_avg_time=16.97711ms,one_avg_time==16.97711ms
可以看出,batch越大,耗时越短。有了这个工具你就可以在同一硬件情况下测试不同模型推理时间
7 loss分析工具loss_analyze
loss分析工具的主要目的有两个:
检查代码是否有bug
理解别人写好的loss
目前这个工具还不完善,只指出focal loss。后续会写通用版本,可以指出mmdetection-mini里面的所有Loss,只需要传入loss的cfg即可。focal loss分析如下:
上图是loss曲线,下图是梯度曲线。
8 特征图可视化工具featuremap_analyze
特征图可视化工具的用途是用来可视化任意层的输出特征图,主要用途是:
查看任意层特征图的预测情况,看下是否符合预期
查看新增的注意力模块到底有没有起作用
有待挖掘
需要特别说明的是:这个工具非常通用,可以指出任何框架的模型,只需要传入Model即可,不需要绑定mmdetection-mini框架也可以使用。
下面介绍用法。以yolov3 320尺寸,并且下载mmdetection已经训练好的权重进行分析。在配置好参数后,首先你需要指的想看哪一层特征图,为了方便大家,在运行前我会打印网络层数(内部采用torchsummaryX第三方库),如下所示:
可以看出,yolov3的三个输出层索引分别是 [218, 214, 210],特征图从大到小,也就是说这三个特征图是用来检测小物体、中等物体和大物体的。我可视化的这三个层都是255的通道输出,然后全部resize到原图大小进行显示。
效果还是可以的。
但是其实可以控制更加精细,我们知道这三个其实都是yolov3的输出层,输出通道255都是有具体含义的,例如你可以直接把confidence通道切割出来,然后可视化,效果应该会更好。鉴于我目前代码都是通用的,故你可以自己改改实现这个效果。
9 感受野计算工具receptive_analyze
感受野分析的作用性,我想大家都知道,在设计网络模型时候非常关键。为了方便大家计算各种模型感受野,我提供了这个工具,和featuremap_analyze一样,也是通用工具。用法和featuremap_analyze一样。
你也可以指定想看任意层的感受野,这里是通过梯度反向传播、像素改变的最大范围来计算的。可以发现这里的感受野不是理论值,而是实际值。
有一个细节需要说明下:我们知道激活函数relu是非常常用的,但是其梯度仅仅计算大于0区域,这样子的话,算感受野的时候会偏小,所以为了避免计算不准确,我会内部自动把relu替换为Linear,同理,自动把MaxPool2d替换为AvgPool2d,这样子计算的感受野才是准确的。但是目前我仅仅考虑了这两个算子,如果有其他有相同效应的算子也是同样道理替换即可。 以yiny_yolov3为例,计算2个输出层的感受野如下:
特征图最大预测层感受野(42):w=286, h=286
特征图最小预测层感受野(214):w=318, h=318
大家可以测试自己的模型,暂时不知道还有没有bug,欢迎大家试用!
再次贴一下github:
https://github.com/hhaAndroid/mmdetection-mini
欢迎star
整体来说,工具的作用就是为了减少出错次数和容易分析模型,目前这些工具有些比较通用,有些还有待完善,希望各位客官能够给出指导意见!
推荐阅读
mmdetection最小复刻版(二):RetinaNet和YoloV3分析
机器学习算法工程师
一个用心的公众号