mmlab

MMCV/MMDETECT 架构分析

mmcv 是 mmdet 的主要依赖包。mmcv 的特点是广泛地使用配置文件来规范化模型的构建、训练等。实现这一特性的核心是 mmcv 的 Config 类与 Registry 类。分别定义于 mmcv/utils/config.pymmcv/utils/registry.py 文件中。以下架构分析针对的版本为

  • mmcv-full 1.3.9

  • mmdetection (git commit id: 522eb9ebd7df0944b2a659354f01799895df74ce,版本为2.14~2.15之间)

与许多优秀的开源项目一样,mmlab 的项目也会存在 API 变化的现象,大多数时候 mmlab 会对之前的 API 兼容,但给出警告。对于源码分析而言,这种代码是一种干扰。

安装

源码安装 mmcv-full,可能需要修改 setup.py

# cmd_class = {'build_ext': torch.utils.cpp_extension.BuildExtension}
cmd_class = {'build_ext': torch.utils.cpp_extension.BuildExtension.with_options(use_ninja=False)}

随后使用如下命令进行安装

MMCV_WITH_OPS=1 pip install -e .  # 开发模式安装
MMCV_WITH_OPS=1 python setup.py install  # 安装

典型用法(此处补充一个 mmdet 的例子):

dataset = DATASET.build(Config.fromfile("xxx.py"))
model = MODEL.build(Config.fromfile("xxx.py"))
runner = RUNNER.build(Config.fromfile("xxx.py"))

mmcv.utils.config.Config 类

动机

这个类的作用是配置的解析,mmlab 的项目通常是直接使用“python”文件作为配置文件的,

mmdetection 内置的模型通常使用配置文件,放置在 mmdetection/configs 文件夹下,

进阶:Config.fromfile 方法的实现细节

  • 注意:可以在配置文件中配置 custom_imports,这样可以不对源码进行修改添加自定义的模型或数据集

mmcv.utils.registry.Registry 类

目的是希望可以使用类似于如下的方式进行统一地初始化模型:

Register 的作用如下,假定 MODELS 为一个 Register 对象,通过对其他的类使用 MODELS.register_module 装饰,在 MODELS 内部维护一个映射表,例如:

而被装饰的类本身没有被进行任何的修改。

简化版:

源码:

2.16.0 版本 mmcv/utils/registry.py:Registry

Registry 的默认 build_func

如上所述,mmcv 1.3.16 版本

此处的 build_func 的默认值为 build_from_cfg(cfg, registry, default_args=None),而这个函数的作用就是利用 cfg"type" 字段取出,其余参数用于创建实例。

mmcv.cnn.MODELS 所使用的 build_func 使用的是如下:

即如果传入参数 cfg 是字典,则使用默认的 build_from_cfg,如果是列表则依次使用默认的 build_from_cfg

而 mmdetection 2.18.0 的 tools/train.py 中用如下方式调用

mmdet/models/builder.py:build_detector 源码如下

备注:在之前的 mmdetection 版本中,最初的 .py 配置文件里 modeltrain_cfgtest_cfg 是并列的关系。而在此 mmdetection 版本中,后两者被包在前者里面。此处仅仅是为了兼容性,因此实际上等同于调用

因此本质上是调用 DETECTOR.build

然而,mmdetection 中的迭代器实际上在 mmdet/models/builder.py 被一起定义了,其 build_func 直接沿用了 mmcv.cnn.MODELS

而 mmdetection 2.18.0 的 tools/train.py 中用如下方式调用

mmdet/datasets/builder.pybuild_dataset 源码为递归方式(如果 cfg 参数中的 "type" 为特殊取值,则特殊处理,这些特殊的类都被注册在 DATASETS 里):

  • 最常用的情况:cfg 本身为字典的列表,则逐个调用 build_dataset 后再包一层 ConcatDataset

  • ConcatDataset及其他情况基本都假定 cfg.datasets 是一个字典的列表

Registry 实例:

mmcv.runner.builder.Runner 类

mmdet/../tools/train.py 脚本源码解析

参见 notebook 里的注解

此脚本为训练脚本,通常利用这个脚本训练模型

兼容性:在 mmdet 之前的版本里,配置文件中通常按这种方式组织

但在此版本的 mmdet 现在的版本里,推荐用这种方式组织

真正复杂的逻辑发生在

运行实例:Yolov3

下面具体介绍一个模型,启动方式为:

而简化版的配置文件为(将配置文件的继承关系展平了):

因此,运行时,首先会执行到以下代码构建模型

而这行代码最终会执行的类似于:

YOLOV3 类是按如下方式定义的:

所以实际上只需理解 SingleStageDetectorBaseDetectorBaseModule 这三个类的逻辑即可。

首先,SingleStageDetector.__init__ 函数会依次调用

前面已经提到,伪代码如下,因此最终都回到了 build_model_from_cfg 函数的调用:

FP16 训练

使用方法:配置文件顶级位置加上即可

实现原理如下:

  • pytorch>=1.6.0 且配置 fp16 参数,此时的 Fp16OptimizerHookbefore_run 函数已经事先将模型的 fp16_enabled 设置为 True, 在每轮迭代时,@auto_fp16 装饰器内部首先将输入转为 fp16,然后在 torch.cuda.amp.autocast 下运行模型,此时无所谓输入是 fp16 还是 fp32,皆可正常运行。

  • pytorch<1.6.0 且配置 fp16 参数, 此时的 Fp16OptimizerHookbefore_run 函数已经事先将模型转为 fp16,在每轮迭代时,@auto_fp16 装饰器内部会将输入转换为 fp16,因此模型能正常运行

  • 不配置 fp16 参数时,将不会使用 Fp16OptimizerHook,因此模型将不会被设置 fp16_enabled=True,因此 @auto_fp16 将不会对输入做任何变换,即此时该装饰器完全无效

为理解原理,关键代码如下:

图解:

更详细的代码如下(待整理)

一些相对独立的底层代码

mmcv/runner/base_module.py:BaseModule

mmcv 中类似于 torch.nn.Module 的东西,完整源代码(注释有所修改)如下,可以发现本质上只是给 nn.Module 增加了个 init_weights 方法。

以下是一些继承 `mmcv/runner/base_

mmdet/models/detectors/base.py:BaseDetector

mask 标注

mmdet/core/mask/structures.py:PolygonMasks

通常一个物体的标注文件格式类似于:

mmdet/core/mask/structures.py:NitMapMasks

待续

记录

mmdetction 2.16.0

configs/_base_/schedules 里的区别只在于

一个把配置文件打印出来的工具

tools/train.py 可以同时支持分布式与非分布式的启动方式

分布式启动的脚本如下(tools/dist_train.sh):

直接单卡启动最简的启动方式为

以分布式的方式启动时,train.py脚本中存在以下语句,不知道是否写的太死

mmcv 1.3.16

mmocr 0.5.0

KIEDataset.__getitem__: (before pipeline)

Tricks and Discussion and Have Fun

为什么叫 mmdetection?

参考知乎,因为 mmlab 开源项目起源于香港中文大学的多媒体实验室,多媒体(multi-media)

字典

图像读取与变换

mmdetction 使用 opencv 进行图像的读取,变换。对于变换,借用了一些 albumentation 包(针对的是 opencv 格式的数据)的函数。但在进行完图像增强后,会将 BGR 格式转为 RGB 格式进行 Normalize。这是为了和 Torchvision 的预训练模型对齐。例如下面的配置:

MMDeploy 学习记录

实验准备: 使用anaconda管理环境, 操作系统为Windows 10, 显卡为NVIDIA GeForce GTX 1650(4G显存)

其余信息

使用预编译的包: 从mmdeploy-release下载并安装

Last updated

Was this helpful?