MMDetection | 它来了它来了!两款轻量级检测模型上线了!

简介: SSDLite 是 Google 在 CVPR2018 论文 MobileNetV2: Inverted Residuals and Linear Bottlenecks 中提出的轻量级检测模型。

一直以来,很多同学都热切希望 MMDetection 加入一些轻量级的检测模型。今天,它们来了!

640.png

在大家的热切期待之下,MMDetection 最近加入了两大经典算法


SSDLiteMobileNetV2-YOLOV3!


这两个模型已经提出了很久,但因为有很强的实用性,一直以来都在工业界有着非常广泛的应用。因此,这次 MMDetection 带来了更加豪华的大餐,不仅支持了两个模型的训练,同样也支持模型导出与部署。


下面就来详细介绍一下这两个模型的实现过程以及使用方法~


本文内容


1. SSDLite

  1.1 简介

  1.2 SSD重构

  1.3 算法复现

2.MobileNetV2-YOLOV3

  2.1 简介

  2.2 模型结构调整

  2.3 Anchor 超参搜索小工具

3.如何部署


1. SSDLite



简介


SSDLite 是 Google 在 CVPR2018 论文 MobileNetV2: Inverted Residuals and Linear Bottlenecks 中提出的轻量级检测模型。


与 SSD 相比,除了将 backbone 从 VGG 替换为 MobileNetV2 之外, SSDLite 还将所有的卷积替换为了深度可分离卷积模块,使得模型的计算量与参数量都大幅下降,更适合移动端使用。在使用同样 Backbone 的情况下,模型的参数量缩小了7倍,计算量缩小了将近4倍,但是依旧保持相同的性能。

640.png

注:数据来源于 Google Tensorflow Object Detection API

SSD 重构


由于 SSD 是 MMDetection 中最早支持的一批检测算法,许多接口都不够灵活,如果需要使用同一个 SSD 模块支持 VGG SSD 和 SSDLite,需要对整个模型进行重构。


在之前版本的 MMDetection 中,SSD 的 backbone 是单独定制的 SSD-VGG,相对于标准的 VGG-16,在模型的末尾又插入了几层卷积层和 pooling 层,用来提取更小尺度的 feature map。


在 Tensorflow 官方版的 SSDLite 中也是采用同样的实现方式:需要修改 MobileNetV2 backbone,增加额外的卷积层。这也就意味着如果要替换 backbone 的话,都需要手动添加额外的层,这样的设计模式并不符合 MMDetection 中的模块化设计思路,也不够灵活。


因此,我们选择将这些额外的层提取出来作为一个单独的模块,按照目前主流的检测模型结构,这部分介于 detection head 和 backbone 之间的模块显然属于 neck,所以将其拆分为 SSDNeck 模块。

640.png

为了支持不同 SSD 模型的设置,新的 SSDNeck 模块预留了丰富的定制化接口,其中包括:


可通过 out_channels 设置输出的通道数;


通过 level_strides level_paddings 设置每一层的卷积的 stride 和 padding 从而控制输出的 feature map 大小;


通过 last_kernel_size 来设置最后一层的卷积核大小(VGG SSD 512 中使用 4x4 kernel);


通过 use_depthwise 来决定是否使用深度可分离的卷积模块;


使用 ConvModule 从而达到可以自由切换 normalize 和激活函数。


将原本以 hardcode 形式实现的一些模型结构都重构为可以使用配置文件设置的形式,提升了灵活性。

# 以 SSDLite 使用的 Neck 为例
# 文件位于 configs/ssd/ssdlite_mobilenetv2_scratch_600e_coco.py
neck=dict(
    type='SSDNeck',
    in_channels=(96, 1280),
    out_channels=(96, 1280, 512, 256, 256, 128),  # 设置输出通道数
    level_strides=(2, 2, 2, 2),  # 设置不同 level 的卷积 stride
    level_paddings=(1, 1, 1, 1),  # 设置不同 level 的卷积 padding
    l2_norm_scale=None,  # 设置是否加上 l2 norm
    use_depthwise=True,  # 设置是否使用深度可分离卷积模块
    norm_cfg=dict(type='BN', eps=0.001, momentum=0.03),  # 设置 norm layer
    act_cfg=dict(type='ReLU6'),  # 设置激活函数
    init_cfg=dict(type='TruncNormal', layer='Conv2d', std=0.03)),  # 设置初始化方式

除了 Neck 部分,SSD 的 head 也进行了重构,包括 head 的模型结构以及 SSD 的 AnchorGenerator。


首先,对 head 的模型结构增加了更多定制化的接口,包括可以配置是否使用深度可分离卷积以及是否堆叠单个 level 下 head 的卷积层层数(虽然默认的配置不会用到,但实际使用场景中可以选择使用此功能可以提升模型性能)。


其次,对 SSDAnchorGenerator 加入了炼丹师们喜闻乐见的手动设置 anchor 大小的接口。原本的 SSDAnchorGenerator 在代码中以 hardcode 的形式设置了 VGG SSD 300 和 512 在 coco 数据集和 voc 数据集上的 anchor 大小,并不能够自由设置 anchor,显得很不灵活。


为此,重构后的版本加入了 min_sizesmax_sizes 这两组参,使用过其他开源版本的 SSD 的同学应该对这两组参数非常熟悉,SSDAnchorGenerator 会根据这两组数值以及设置的 ratio 值计算出每一层 anchor 的 scale 和 ratio。具体的计算过程如下:


anchor_ratios = []
anchor_scales = []
for k in range(len(self.strides)):
    scales = [1., np.sqrt(max_sizes[k] / min_sizes[k])]
    anchor_ratio = [1.]
    for r in ratios[k]:
        anchor_ratio += [1 / r, r]  # 4 or 6 ratio
    anchor_ratios.append(torch.Tensor(anchor_ratio))
    anchor_scales.append(torch.Tensor(scales))


算法复现


由于 MobileNetV2 论文中没有给出 SSDLite 模型训练的细节,Tensorflow Object Detection API 中提供的配置也不够详细,并且其中给出的结果也是在 coco 2014 上得出的,训练集和验证集的划分也不太一样(使用了自定义划分的 coco minival 8000 张图片进行验证)。


除此之外,Tensorflow 中模型的一些操作也和 Pytorch 中不一样,比如自适应的 padding 等。因此,如何寻找一个可对比的 baseline 以及如何在 coco 2017 上进行调参就显得比较困难

在这里,我们参考了另外两篇工作:

设置了一套方案

使用更为通用的 320x320 大小作为输入,避免了 300 输入下 tf 和 pytorch padding 不一样的问题;


将原本 C4 feature 从 backbone inverted residual 中间抽取改为了从 stage 之后取,来避免修改 backbone;


由于输入分辨率有一定的变化,因此也相应修改了原本 ssd 300下的 anchor 设置;


参考 tf model zoo 中的设置,使用 TruncNormal 进行初始化,并修改了 BN 的 eps 和 momentum;


采用 SGD momentum 优化器,初始学习率为 0.015,修改 weight_decay=4.0e-5,并使用 CosineAnnealing 学习率。


从 tf model zoo 的配置可以看出,Google 使用的训练策略比较难以模仿(他们使用超大 batch 在 n 个 TPU 上训练,我们平民玩家玩不起),因此只能参考 torchvison 复现时的训练设置进行训练,最终训练的模型得到了 21.3 的 mAP(由于 Pytorch 和 tf 的一些设置比较难以对齐,使用源码在相似设置下得到了20.2 的 mAP)。


如果有同学觉得 SSDLite 作为一个几年前的算法,性能不够强劲,其实也可以通过修改配置文件来获得性能更强的模型。比如参考 tf2 model zoo 中,为 SSDLite 加入 FPN,可以达到 22.2 的 mAP,也可以像上文所说的,调整 head 里卷积的层数来提升性能,当然还可以重新设计 anchor 的超参来适应自己的数据集。


总而言之,重构后的 MMDetection 的 SSDLite 提供了非常丰富的配置文件接口,供广大炼丹师进行调参,如果有同学实现了更好的配置,我们也非常欢迎 PR~


2. MobileNetV2-YOLOV3



简介


与 SSD 一样,YOLO 也是工业界应用非常广泛的算法,在社区同学的共同帮助下,我们也提供了两种分辨率下的 MobileNetV2-YOLOV3 的配置文件和预训练模型,并且做了一定的优化。

模型结构调整


首先感谢 hokmund 同学对 YOLOV3 Neck 的修改,使其输出通道能够被更灵活的配置,同时也感谢 ElectronicElephant 同学提供的 config。


我们对 ElectronicElephant 提交的配置文件进行了优化,主要有以下几点:


将原本的 608x608 输入修改为对移动端更为友好的 320x320 和 416x416;


修改了 anchor 的设置;


修改了 neck 和 head 的通道数,将通道数降低为 96,大幅减少了模型的计算量和参数量(Flops: 2.86 GFLOPs,Params: 3.74 M,mAP: 23.9);


修改了训练的 batch size 和初始学习率;


使用 RepeatDataset 加速训练。


最终得到了 MobileNetV2-YOLOV3-320 和 MobileNetV2-YOLOV3-416,它们的精度如下:

640.png

Anchor 超参搜索小工具


由于 MMDetection 中的配置文件里的 anchor 超参都是基于 COCO 数据集设置的,在业务场景下可能并不通用,因此我们也加入了非常实用的 YOLO anchor 超参搜索工具

tools/analysis_tools/optimize_anchors.py


在这个小工具中,我们加入了两种 anchor 超参优化的方法:YOLO 经典的 k-means anchor 聚类,以及基于差分进化算法(以下简称 DE 算法)的 anchor 优化。


第一种方法对于 YOLO 用户来说想必都已经非常熟悉了,这里就不再介绍,下面简单介绍基于 DE 算法的 anchor 优化


DE 算法是 Storn 和 Price 在1997年提出的一种求解优化问题的进化算法,使用突变、交叉和选择计算来演化优化问题的解,其具体的流程图如下图所示:

640.png

在这里,我们需要优化的目标是使 anchor 与所有 ground truth 标注框的平均 IOU 最大化,因此在代码中使用 avg_iou_cost 函数作为最小化目标函数(1 - avg_iou)。


由于 DE 算法不使用梯度进行优化,因此并不要求优化的函数是连续的或是可导的,如果使用的同学对优化的目标有特殊的需求,也可以继承小工具中的 YOLODEAnchorOptimizer 类并修改需要优化的函数,就可以很方便的控制 anchor 优化的结果。


如何使用这个小工具来优化自己数据集上的 anchor 超参呢?


首先需要准备好数据集的标注文件以及 config 文件,确保能够被 dataset 所读取(可以通过tools/misc/browse_dataset.py 工具进行验证),然后需要确保环境中安装了 scipy,然后运行命令:

python tools/analysis_tools/optimize_anchors.py ${CONFIG} --algorithm k-means --input-shape ${INPUT_SHAPE [WIDTH HEIGHT]} --output-dir ${OUTPUT_DIR}

来使用 k-means 进行 anchor 聚类。如果要切换成 DE 算法,只需要使用 --algorithm differential_evolution 即可。


al_evolution --input-shape ${INPUT_SHAPE [WIDTH HEIGHT]} --output-dir ${OUTPUT_DIR}


运行完之后会出现如下结果:

loading annotations into memory...
Done (t=9.70s)
creating index...
index created!
2021-07-19 19:37:20,951 - mmdet - INFO - Collecting bboxes from annotation...
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] 117266/117266, 15874.5 task/s, elapsed: 7s, ETA:     0s
2021-07-19 19:37:28,753 - mmdet - INFO - Collected 849902 bboxes.
differential_evolution step 1: f(x)= 0.506055
differential_evolution step 2: f(x)= 0.506055
......
differential_evolution step 489: f(x)= 0.386625
2021-07-19 19:46:40,775 - mmdet - INFO Anchor evolution finish. Average IOU: 0.6133754253387451
2021-07-19 19:46:40,776 - mmdet - INFO Anchor differential evolution result:[[10, 12], [15, 30], [32, 22], [29, 59], [61, 46], [57, 116], [112, 89], [154, 198], [349, 336]]
2021-07-19 19:46:40,798 - mmdet - INFO Result saved in work_dirs/anchor_optimize_result.json

最后,将结果中的 result 按格式添加到配置文件中,即可完成 anchor 的优化。


3. 如何部署



SSDLite 和 MobileNet YOLO 作为在工业界广泛应用的算法,光能够训练可不够,还需要部署到业务场景中,MMDetection 中实现的这两个模型也不例外!


我们提供了 pytorch2onnx 的导出方案,支持将模型转换为 ONNX 格式,并能够通过 ONNXRuntime 和 TensorRT 进行部署,导出后的模型的精度也已经经过了验证,是能够对齐的,大家可以放心大胆的使用。

如果有同学不满足于这两种部署后端,我们也提供了更为灵活的解决方案:支持导出不包含后处理的ONNX 模型,用于作为中间格式转换为其他 inference 框架的模型,只需要在运⾏tools/deployment/pytorch2onnx.py 脚本时加上 --skip-postprocess即可。


但需要注意的是,由于导出的模型不包含后处理,因此需要自己手动在对应的推理框架下实现后处理,这个功能就留给高端选⼿吧〜


本文介绍了 MMDetection 中新增的两种经典轻量级检测算法的使用和部署方法,同时也介绍了新增的一些实用工具。


在之后的更新中, MMDetection 也会增加更多实用的算法以及实用的功能,提升整个算法框架的易用性。如果有同学对 MMDetection 加入更多实用的模型或功能有一些期待或建议,欢迎在评论区留言


文章来源:公众号【OpenMMLab】

2021-08-23 19:34

目录
相关文章
|
6月前
|
人工智能
KOALA图像AI模型发布,低配电脑2秒生图
【2月更文挑战第13天】KOALA图像AI模型发布,低配电脑2秒生图
97 2
KOALA图像AI模型发布,低配电脑2秒生图
|
27天前
|
机器学习/深度学习 人工智能 算法
基于YOLOv8的工业安全帽实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
基于YOLOv8的工业安全帽实时检测系统,通过7581张图片训练,实现工作场所安全帽佩戴检测,降低工伤事故。系统支持图片、视频和摄像头实时检测,具备GUI界面,易于操作。使用Python和Pyside6开发,提供模型训练、评估和推理功能。
62 1
基于YOLOv8的工业安全帽实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
|
24天前
|
机器学习/深度学习 弹性计算 自然语言处理
前端大模型应用笔记(二):最新llama3.2小参数版本1B的古董机测试 - 支持128K上下文,表现优异,和移动端更配
llama3.1支持128K上下文,6万字+输入,适用于多种场景。模型能力超出预期,但处理中文时需加中英翻译。测试显示,其英文支持较好,中文则需改进。llama3.2 1B参数量小,适合移动端和资源受限环境,可在阿里云2vCPU和4G ECS上运行。
|
28天前
|
编解码 人工智能 并行计算
阿里妈妈技术开源FLUX图像修复&蒸馏加速模型
本文介绍了阿里妈妈技术团队基于FLUX开发的Controlnet修复模型和蒸馏加速模型,填补了社区空白并提升了FLUX的实用性和效率。
|
1月前
|
Shell Docker Python
LLM-02 大模型 本地部署运行 ChatGLM3-6B(13GB) 双卡2070Super8GB 环境配置 单机多卡 基于LLM-01章节 继续乘风破浪 为大模型微调做准备
LLM-02 大模型 本地部署运行 ChatGLM3-6B(13GB) 双卡2070Super8GB 环境配置 单机多卡 基于LLM-01章节 继续乘风破浪 为大模型微调做准备
46 1
|
3月前
|
机器学习/深度学习 TensorFlow 算法框架/工具
全面解析TensorFlow Lite:从模型转换到Android应用集成,教你如何在移动设备上轻松部署轻量级机器学习模型,实现高效本地推理
【8月更文挑战第31天】本文通过技术综述介绍了如何使用TensorFlow Lite将机器学习模型部署至移动设备。从创建、训练模型开始,详细演示了模型向TensorFlow Lite格式的转换过程,并指导如何在Android应用中集成该模型以实现预测功能,突显了TensorFlow Lite在资源受限环境中的优势及灵活性。
202 0
|
4月前
|
存储 人工智能 自然语言处理
社区供稿 | 源大模型的快速部署与高效推理——GGUF格式模型介绍与使用教程
在人工智能领域,大型语言模型的发展日新月异,它们在自然语言处理、机器翻译、智能助手等多个领域展现出了前所未有的能力。
社区供稿 | 源大模型的快速部署与高效推理——GGUF格式模型介绍与使用教程
|
6月前
|
存储 人工智能 达摩院
FunASR 语音大模型在 Arm Neoverse 平台上的优化实践
Arm 架构的服务器通常具备低功耗的特性,能带来更优异的能效比。相比于传统的 x86 架构服务器,Arm 服务器在相同功耗下能够提供更高的性能。这对于大模型推理任务来说尤为重要,因为大模型通常需要大量的计算资源,而能效比高的 Arm 架构服务器可以提供更好的性能和效率。
|
6月前
|
开发框架 API 决策智能
ModelScope-Agent框架再升级!新增一键配置多人聊天,配套开源多智能体数据集和训练
ModelScope-Agent是魔搭社区推出的适配开源大语言模型(LLM)的AI Agent(智能体)开发框架,借助ModelScope-Agent,所有开发者都可基于开源 LLM 搭建属于自己的智能体应用。在最新升级完Assistant API和Tool APIs之后,我们又迎来了多智能体聊天室的升级,通过几分钟快速配置即可搭建一个全新的聊天室。
|
6月前
|
机器学习/深度学习 存储 并行计算
YOLOv8改进 | 2023 | AKConv轻量级架构下的高效检测(既轻量又提点)
YOLOv8改进 | 2023 | AKConv轻量级架构下的高效检测(既轻量又提点)
280 0
下一篇
无影云桌面