Detectron2入门教程

0. 前言

  • 目标:走马观花,两天时间浏览Detectron2源码,稍微记录一下。
    • 与 TensorFlow Object Detection API、mmdetection 一样,Detectron2 也是通过配置文件来设置各种参数,所有的相关内容都像搭积木一样一点一点拼凑起来。
    • 我自己感觉,一般所有代码都可以分为三个部分,所以看Detectron2的源码也分为以下三个部分。
      • 数据处理:包括数据读取、数据增强以及其他数据预处理。
      • 模型构建:没啥好说的。
      • 模型训练、预测、评估:包括模型存取、优化器、学习率、损失函数、性能指标、TensorBoard等。
  • 资料汇总
  • 本文内容:
    • 第一章:概述,分为四个部分:看源码的过程、源码目录结构、注册机制、官方文档的阅读笔记。
    • 第二章:数据处理,介绍detectron2中数据处理相关源码的结构、基本运行流程等。
    • 第三章:模型搭建,介绍detectron2中模型搭建的基本流程。
    • 第四章:模型训练/预测/评估,重点介绍了模型训练相关类的结构以及实现思路。
  • TODO: 基于detectron2中的projects,阅读TensorMask/DensePose/TridentNet论文,并研究源码并训练模型。

1. 概述

1.1. 自己的源码阅读流程

  • 设定目标:
    • 刚刚从TF转向PyTorch,所以希望进一步熟悉PyTorch。
    • 进一步熟悉目标检测、实例分割、关键点检测等模型。
    • 寻找/研究源码中存在的一些tricks。
    • 后续需要通过detectron2来复现新论文。
  • 总结自己之前的一些步骤
    • 第一步:阅读所有官方文档。
    • 第二步:尝试根据 Getting Started 文档内容,运行 demo 中的脚本。
    • 第三步:从数据处理、模型构建、模型训练/预测/评估三个方面,分别浏览源码。
  • 个人感受:
    • PyTorch代码比TensorFlow代码容易多了。
    • Detectron2源码比TensorFlow Object Detection API源码直观多了,上手容易多了。
      • 当然,也可能是因为比较熟悉TensorFlow Object Detection API的源码,所以看Detectron2的就很容易。

1.2. 目录结构

  • configs示例配置文件合集。
  • datasets:数据集准备工作,主要就是各个数据集的基本结构,以及需要如何预处理。
  • demo:快速体验Detectron2,与Getting Started文档对应。如果想要体验Model ZOO中结果的内容就可以用这个。
  • detectron2:项目主要代码都在这里了。
  • dev:一些开发者会用到的脚本。
  • docker:没啥好介绍的。
  • docs:一些官方文档。
  • projects:基于Detectron2的三个项目,DensePose/TensorMask/TridentNet。
    • 在知乎里,Detectron2的开发人员介绍,如果想要利用detectron2直接复现所有论文可能比较困难(我的理解就是直接修改detectron2中的代码),一种比较好的方式就是将detectron2作为一个包来调用来构建新的模型。
    • 这里的三个项目就是利用detectron2复现模型的示例。
  • tests:单元测试类。
  • tools:常用脚本,如训练、benchmark、展示数据集等。

1.3. 搭积木过程

  • Detectron2 的基本思路就是利用配置文件搭积木。
    • 第一步,将模型拆分为多个模块,每个模块可以叫做一个类型的积木。
    • 第二步,构建配置文件。
    • 第三步,通过配置文件,选择对应的积木。
  • 配置文件概述
    • 有一个默认配置文件,即 detectron2/config/default.py 文件。
    • 示例配置文件放在 configs 文件夹中,且使用yaml形式。
    • 所有示例配置文件都是建立在默认配置文件基础上的,即所有示例配置文件中的配置其实都是不全的,缺失的配置需要到默认配置文件中寻找。
      • 感觉这也是为什么 detectron2 的配置文件比 mmdetection 看起来简洁很多。
      • 有得必有失,虽然简洁,但在看源码的时候经常需要查看默认配置文件,也不是特别方便。
    • 示例配置文件中有一个_BASE_属性,可以将其他示例配置文件作为基础,如果有冲突则用当前配置文件的信息覆盖。
  • 如何使用配置文件搭积木
    • 模型搭建的Registry机制
      • 调用了 fvcore.common.registry.Registry,该对象的作用是保存一个字典,key为方法/类的名称,value为方法/类,利用 @registry_object.register 修饰目标方法/类,这样可以在导入detectron2的同时将 key/value 保存起来。
      • 对于每一个类型的积木(如backbone, anchor generator, proposal generator, roi head等)都对应一个Registry对象。更多类型可以看 detectron2/modeling/__init__.py 文件。
      • 一般,一个Registry对应一个build.py,主要就是从Registry中通过名称获取方法/类,然后将示例配置文件中参数导入目标方法/类中。
    • 数据集的Registry机制
      • 主要使用了 detectron2/data/catalog.py 中的 MetadataCatalogDatasetCatalog,前者保存了数据集的元数据,后者保留了一个方法,该方法用于获取数据集 list(dict)
      • 使用了Registry机制,但不是通过注解实现的,而是在 detectron2/data/datasets/buildin.py 中调用了 register_all_coco() 等四个方法,这些方法调用了 MetadataCatalogDatasetCatalog的注册方法。
      • 一般建数据集会调用 build_detection_train_loader 方法,该方法会调用DatasetCatalog中的方法,获取 list(dict)
    • 模型训练/预测/评估的的搭积木不复杂,就是根据配置文件,直接创建对应的对象(如lr, optimizer等)。

1.4. 官方文档阅读

  • 官方文档地址,如果想了解Detectron2的源码,强烈建议先看看。
  • tutorials
    • Installation:安装,没啥好说的。
    • Getting Started with Detectron2:跑个Demo,没啥好说的。
    • Extend Detectron2's Defaults
      • 谈了谈Detectron2的基本设计思路。一方面要有足够的灵活性(做研究总是要做新东西),一方面要有较好的高层抽象。
      • 基本设计思路:所有的方法和类都可以从一个配置文件中获取所需要的参数(配置文件中没有的,就使用默认参数)。
      • 介绍了扩展detectron2的一些相关文档。
    • Use Custom Datasets
      • dataset只是解析数据集,而没有进行数据处理(数据处理在后面dataloader中进行)。
      • dataset的输出将会作为后续dataloader的输入。
      • 自定义数据集步骤:
        • 注册数据集(使用注释告诉detectron2如何获取该数据集),需要制定数据集名称以及一个 get_dict 方法,该方法用于获取一个 list[dict] 对象,每个字典就是一条输入数据,具体的key列表可以到文档中自己看。
        • 可以注册一些自定义 metadata。
      • 数据集的 metadata 介绍
        • 一个记录数据库相关信息的字典,比如primitive information that helps interpret what's in the dataset, e.g., names of classes, colors of classes, root of files, etc.
        • 可以通过 MetadataCatalog.get(dataset_name).set(name, value) 为新数据库添加元数据。
    • Use Custom Dataloaders
      • 介绍数据处理模块,其实就是一系列数据增强等操作,以上述dataset的结果作为输入,并作为后续Model的输入。
      • 具体过程如下:
        • 首先,根据数据集名称获取一个已经注册的数据集(就是上面的dataset),获取 list[dict] 对象。
        • 其次,数据增强等其他数据处理流程都内置于 DatasetMapeer 中。
        • 最后,需要batch数据,batch后的数据一般就作为 model.forward() 的输入。
      • 介绍如何自定义Dataloader、使用自定义Dataloader可以参考DensePose的代码。
    • Use Models
      • 主要介绍如何构建模型。
      • 构建模型方式:通过调用 build_model, build_backbonebuild_roi_heads 等方法来构建。
      • 要导入权重可以使用 DetectionCheckpointer(model).load(file_path)
      • 使用模型就是 outputs = model(inputs)
      • 模型输入使用的参数通过 list[dict] 来实现,即上面dataloader的输出,具体的key形式可以参考这个页面中的内容。
      • 模型输出也是一个 list[dict],具体的形式可以参考这篇文章中的内容。
    • Write Models
      • 自定义模型相关。
      • 举了个例子如果自定义backbone该怎么做。
    • Training
      • 就提了下训练相关的代码。
      • 一般使用 tools/plain_train_net.py 来训练模型。
      • 最简单的训练结构是 SimpleTrainer().train()
      • 一般使用的类是 DefaultTrainer().train()
    • Use Configs
      • 介绍了配置系统的基本结构,即使用yaml和yacs来配置。
      • 配置文件的使用,其实就是对 CfgNode 对象的使用。
      • 建议使用配置文件的方式,我比较在意的是 使用_BASE_参数来重复配置定义到一个文件中。
  • notes
  • API Documentation

2. 数据处理

2.1. 概述

  • 实现的功能:
    • 解析COCO、cityscapes等数据集。
    • 提供数据预处理以及增强的接口。
    • 通过配置文件即可实现数据集解析、预处理、增强等操作。
  • 主要入口: detectron2/data/build.py 中的 build_detection_train_loaderbuild_detection_test_loader 方法。
  • 相关代码:主要位于 detectron2/detectron2/data 目录下。
  • 相关配置:detectron2/config/defaults.py_C.INPUT _C.DATASETS _C.DATALOADER 开头的配置。

2.2. 基本流程

  • 第一步:在导入 detectron2 模块时,通过Register机制注册一些常用的数据集。
    • 注册机制可以参考 1.3. 中的内容。
    • 注册代码在 detectron2/detectron2/data/datasets/builtin.py
  • 第二步:通过数据集名称以及完成注册的 DatasetCatalog 对象以及 MetadataCatalog 对象,解析数据集并获取数据集基本信息。
    • 从源码角度看,就是调用了 DatasetCatalog 中的对应的方法,获取 list[dict] 对象。
  • 第三步:通过mapper函数,对解析完的数据集进行进一步处理,包括数据增强,并将修改数据的结构,使之可以直接作为后续模型的输入。
    • 从源码角度理解就是,从 DatasetCatalog 获取的是 list[dict],mapper函数输出的也是 list[dict],但前后两个字典的形式是不一样的,具体可以参考官方文档,里面都有具体的描述。

2.3. build_detection_train_loader 方法解析

  • 源码位于 detectron2/detectron2/data/build.py 中。
  • 流程:
    • 第一步:获取 list[dict] 对象。先根据数据库名称调用 DatasetCatalog 中的方法,获取原始 list[dict] 对象,再通过一些条件进行筛选。
    • 第二步:构建 DatasetFromList 对象,该类是 torch.utils.data.Dataset 的子类。
    • 第三步:根据mapper对上面的dataset对象进行进一步处理。
      • 浏览了下 DatasetMapper的源码,主要工作包括读取图像、resize、crop、flip、转换数据与标签的形式等。
    • 第四步:构建 torch.utils.data.sampler.Sampler 对象,实现的功能好像包括Repeat Sample、shuffle、batch功能。
    • 第五步:根据上面的 dataset, sampler 等对象构建 torch.utils.data.DataLoader 对象。
  • 感想:
    • 好像也没有什么特别的数据增强工作。
    • Detectron2实现的 DatasetFromListMapDataset等,有点 tf.data 的感觉,挺有意思。

2.4. 其他

  • 数据增强
    • 方法主要都在 detectron2/detectron2/data/transforms/transform_gen.py 中定义。
    • 调用的话主要是通过 from detectron2.data import transforms as T 以及 T.ResizeShortestEdge 来实现。
    • 在默认实现中,就没用到什么特别的数据增强。具体的可以到 DatasetMapper 的源码中看。

3. 模型搭建

3.1. 概述

  • 实现的功能:通过配置文件构建模型。
  • 主要入口:detectron2/detectron2/modeling/meta_arch/build.py 中的 def build_model(cfg) 方法。
  • 相关代码:detectron2/detectron2/modeling 目录下。
  • 相关配置:detectron2/config/defaults.py_C.MODEL 开头的配置。

3.2. 基本流程

  • 第一步:根据注册机制,在导入 detectron2 时,将各个类型的积木通过注解的方式保存到 Registry 对象中。
  • 第二步:根据配置文件中 META_ARCHITECTURE 参数,选择基本框架,也就是 meta arch。
    • 基本框架(meta arch)的类型没集中,包括 rcnn, retinanet, semantic seg, panoptic 四种。
    • 每个基本框架(meta arch)中都定义了一系列子部件,也都是用Register机制来管理(即通过配置文件与Register对象来构建)。
    • 基本框架的定义中,就包含了模型如何构建、如何训练、如何预测等相关功能。
  • 第三步:通过配置文件分别构建选中meta arch中各个部件。

3.3. 其他

  • Registry对象列表
    • ANCHOR_GENERATOR_REGISTRY:如何生成anchors。
    • BACKBONE_REGISTRY:主干网络,包括FPN。
    • META_ARCH_REGISTRY:基本网络,总体结构。
    • SEM_SEG_HEADS_REGISTRY:应该是用来做语义分隔的。
    • PROPOSAL_GENERATOR_REGISTRY:Faster RCNN中的Region proposal Network,即如何生成proposals。
    • RPN_HEAD_REGISTRY:第一阶段训练所需的输入。
    • ROI_BOX_HEAD_REGISTRY:ROI Head中的bbox分支。
    • ROI_HEADS_REGISTRY:通过特征图和第一阶段的proposals得到ROI。
    • ROI_KEYPOINT_HEAD_REGISTRY:ROI Head中的keypoint分支。
    • ROI_MASK_HEAD_REGISTRY:ROI Head中的mask分支。
  • 除了通过注册机制管理的部件外,还有一系列模型所需的部件,具体的可以参考 meta_arch 中的相关源码。

4. 训练/评估/预测

4.1. 概述

  • 实现的功能:通过配置文件构建模型。
  • 主要入口:detectron2/detectron2/engine/defaults.py 中的 DefaultTrainer, DefaultPredictor
  • 相关代码:主要在 detectron2/detectron2/enginedetectron2/detectron2/solver
  • 相关配置:detectron2/config/defaults.py_C.SOLVER _C.TEST 开头的配置。

4.2. 训练代码结构

  • 主要包括了:TrainerBase, SimpleTrainer, DefaultTrainer 三个类。
  • TrainerBase
    • 定义在 detectron2/detectron2/engine/train_loop.py 中。
    • 主要功能:
      • 提供了 hooks 机制,可以通过导入 HookBase 对象,在训练过程的各个时间点进行自定义处理。
      • 定义了训练函数为 train(self, start_iter: int, max_iter: int),且维训练提供了一个 EventStorage 对象。
    • 这个与TF中的SessionRunHook类似,只不过TF已经实现在源码里,而Detectron2中是自己实现的。
  • SimpleTrainer
    • 定义在 detectron2/detectron2/engine/train_loop.py 中。
    • 主要功能:在 TrainerBase 的基础上添加了训练所需的基本参数以及最基本的训练过程代码。
    • 基本训练参数指的是 model/data_loader/optimizer
    • 基本训练过程包括位于 run_step 函数中,主要包括的功能是:
      • 导入数据。
      • 计算损失函数(并确保损失函数是有效的)。
      • 记录一些性能指标(包括损失函数、时间点),保存到 EventStorage 对象中。
      • 进行梯度下降操作。
  • DefaultTrainer
    • 定义在 detectron2/detectron2/engine/defaults.py 中。
    • 主要功能:
      • SimpleTrainer 的基础上,提供了通过配置文件创建模型、数据集、优化器、学习率等一系列操作。
      • 提供了 checkpoint 功能。
      • 使用了一系列常见的 hooks。
    • hooks的定义都在 detectron2/detectron2/engine/hooks.py 中。
发布了888 篇原创文章 · 获赞 93 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/weixin_36670529/article/details/104021823