[关闭]
@huanghaian 2020-09-26T12:23:41.000000Z 字数 5627 阅读 2252

mmdetection最小复刻版(三):数据分析神兵利器

mmdetection


本文主要说明下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数据为例,如下所示”
image.png-706.1kB

可视化效果看起来比较难看,不过我懒得改了。

2 coco数据可视化visualize_coco

上面的可视化效果有点糟糕,既然是coco,那可以调用coco里面的api进行可视化。我对其进行了扩展,可以仅仅显示bbox(),为啥要扩展?因为在coco格式中如果没有mask数据是无法显示的,但是例如voc数据即使转化为coco格式,也是不存储mask的,此时用coco api进行显示,是啥都没有的。

其核心参数有两个:

用法在main函数里面。以coco为例,
only_bbox=False,也就是coco默认的显示格式:
image.png-548.7kB

only_bbox=True,也就是扩展模式:
image.png-510.6kB

这个显示就酷炫很多了。

如果show_all=Fasle,且category_name='bicycle'(一共有多少类别会同时打印出来,你就可以直接copy了)
image.png-587.6kB

如果不想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为例,转化后可视化如下:
image.png-425.4kB

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)],
                [(30, 61), (62, 45), (59, 119)],
                [(10, 13), (16, 30), (33, 23)]],
    strides=stride)

image.png-76kB

如果觉得显示的过多不好看,可以自己设置显示个数。

5 数据分析工具dataset_analyze

数据分析工具目前支持三个:wh比例分析;wh尺寸分析和kmean算法。本来可以直接对coco的json文件进行分析的,但是基于以下几点考虑,最终采用了dataloader:

基于以上几点考虑,我这里分析的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)为例进行分析:
image.png-41kB

上图是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尺度参数了。

但是目前我还没有想到非常好的可视化手段,欢迎各位朋友提出改进意见。

image.png-44.2kB

我只是简单绘制了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分析工具的主要目的有两个:

目前这个工具还不完善,只指出focal loss。后续会写通用版本,可以指出mmdetection-mini里面的所有Loss,只需要传入loss的cfg即可。

focal loss分析如下:
image.png-103.2kB

上图是loss曲线,下图是梯度曲线。

具体分析见:文章...

8 特征图可视化工具featuremap_analyze

特征图可视化工具的用途是用来可视化任意层的输出特征图,主要用途是:

需要特别说明的是:这个工具非常通用,可以指出任何框架的模型,只需要传入Model即可,不需要绑定mmdetection-mini框架也可以使用。

下面介绍用法。以yolov3 320尺寸,并且下载mmdetection已经训练好的权重进行分析。

在配置好参数后,首先你需要指的想看哪一层特征图,为了方便大家,在运行前我会打印网络层数(内部采用torchsummaryX第三方库),如下所示:

image.png-101.5kB

可以看出,yolov3的三个输出层索引分别是 [218, 214, 210],特征图从大到小,也就是说这三个特征图是用来检测小物体、中等物体和大物体的。我可视化的这三个层都是255的通道输出,然后全部resize到原图大小进行显示。

image.png-572.4kB

效果还是可以的。

但是其实可以控制更加精细,我们知道这三个其实都是yolov3的输出层,输出通道255都是有具体含义的,例如你可以直接把confidence通道切割出来,然后可视化,效果应该会更好。鉴于我目前代码都是通用的,故你可以自己改改实现这个效果。

9 感受野计算工具receptive_analyze

感受野的分析的作用性,我想大家都知道,在设计网络模型时候非常关键。为了方便大家计算各种模型感受野,我提供了这个工具,和featuremap_analyze一样,也是通用工具。用法和featuremap_analyze一样。
你也可以指定想看任意层的感受野,这里是通过梯度反向传播、像素改变的最大范围来计算的。可以发现这里的感受野不是理论值,而是实际值。
有一个细节需要说明下:我们知道激活函数relu是非常常用的,但是其梯度仅仅计算大于0区域,这样子的话,算感受野的时候会偏小,所以为了避免计算不准确,我会内部自动把relu替换为Linear,同理,自动把MaxPool2d替换为AvgPool2d,这样子计算的感受野才是准确的。但是目前我仅仅考虑了这两个算子,如果有其他有相同效应的算子也是同样道理替换即可。
以yiny_yolov3为例,计算2个输出层的感受野如下:

大家可以测试自己的模型,暂时不知道还有没有bug,欢迎大家试用!

再次贴一下

github: https://github.com/hhaAndroid/mmdetection-mini

欢迎star

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注