Detectron2源码阅读笔记-(二)Registry&build_*方法
Trainer解析
我们继续Detectron2代码阅读笔记-(一)中的内容。

上图画出了detectron2文件夹中的三个子文件夹(tools,config,engine)之间的关系。那么剩下的文件夹又是如何起作用的呢?
def main(args):
cfg = setup(args)
if args.eval_only:
...
trainer = Trainer(cfg)
trainer.resume_or_load(resume=args.resume)
if cfg.TEST.AUG.ENABLED:
trainer.register_hooks(
[hooks.EvalHook(0, lambda: trainer.test_with_TTA(cfg, trainer.model))]
)
return trainer.train()
build_*方法
我们从trainer = Trainer(cfg)开始进一步了解。
Detectron2代码阅读笔记-(一)中已经提到过一连串的Trainer的继承关系如下:
tools.train_net.Trainer->detectron2.engine.default.DefaultTrainer->detectron2.engine.train_loop.SimpleTrainer->detectron2.engine.train_loop.TrainerBase,而detectron2.engine.default.DefaultTrainer在其__init__(self, cfg)函数中定义了解析cfg。如下面代码所示,cfg会作为参数倍若干个build_*方法解析,得到解析后的model,optimizer,data_loader等。
from detectron2.modeling import build_model
class DefaultTrainer(SimpleTrainer):
def __init__(self, cfg):
"""
Args:
cfg (CfgNode):
"""
# Assume these objects must be constructed in this order.
model = self.build_model(cfg)
optimizer = self.build_optimizer(cfg, model)
data_loader = self.build_train_loader(cfg)
...
self.register_hooks(self.build_hooks())
@classmethod
def build_model(cls, cfg):
"""
Returns:
torch.nn.Module:
"""
model = build_model(cfg)
logger = logging.getLogger(__name__)
logger.info("Model:\n{}".format(model))
return model
下面我们以DefaultTrainer.build_model为例来介绍注册机制,该方法调用了detectron2/modeling/meta_arch/build_model.py的build_model函数,其源代码如下:
from detectron2.utils.registry import Registry
META_ARCH_REGISTRY = Registry("META_ARCH")
META_ARCH_REGISTRY.__doc__ = """
def build_model(cfg):
"""
Built the whole model, defined by `cfg.MODEL.META_ARCHITECTURE`.
"""
meta_arch = cfg.MODEL.META_ARCHITECTURE
return META_ARCH_REGISTRY.get(meta_arch)(cfg)
- meta_arch = cfg.MODEL.META_ARCHITECTURE: 根据超参数获得网络结构的名字
- return META_ARCH_REGISTRY.get(meta_arch)(cfg):META_ARCH_REGISTRY是一个
Registry类(这个在后面会详细介绍),可以将这一行代码拆成如下几个步骤:
model = META_ARCH_REGISTRY.get(meta_arch)
return model(cfg)
注册机制Registry
那么Registry到底是什么呢?在分析源代码之前我们先了解一下如何使用它,假如你想自己实现一个新的backbone网络,那么你可以这样做:
首先在detectron2中定义好如下(实际上已经定义了):
# detectron2/modeling/backbone/build.py
BACKBONE_REGISTRY = Registry('BACKBONE')
之后在你创建的新的文件下按如下方式创建你的backbone
# detectron2/modeling/backbone/your_backbone.py
from .build import BACKBONE_REGISTRY
# 方式1
@BACKBONE_REGISTRY.register()
class MyBackbone():
...
# 方式2
class MyBackbone():
...
BACKBONE_REGISTRY.register(MyBackbone)
Registry源代码如下(有删减):
class Registry(object):
def __init__(self, name):
self._name = name
self._obj_map = {}
def _do_register(self, name, obj):
assert (
name not in self._obj_map
), "An object named '{}' was already registered in '{}' registry!".format(name, self._name)
self._obj_map[name] = obj
def register(self, obj=None):
if obj is None:
# used as a decorator
def deco(func_or_class):
name = func_or_class.__name__
self._do_register(name, func_or_class)
return func_or_class
return deco
# used as a function call
name = obj.__name__
self._do_register(name, obj)
def get(self, name):
ret = self._obj_map.get(name)
if ret is None:
raise KeyError("No object named '{}' found in '{}' registry!".format(name, self._name))
return ret
- 首先是
__init__部分:self._name则是你要注册的名字,例如对于完整的模型而言,name一般取META_ARCH。当然如果你需要自定义backbone网络,你也可以定义一个Registry('BACKBONE')self._obj_map:其实就是一个字典。以模型为例,key就是你的模型名字,而value就是对应的模型类。这样你在传参时只需要修改一下模型名字就能使用不同的模型了。具体实现方法就是后面这几个函数。
register: 可以看到该方法定义了注册的两种方式,一种是当obj==None的时候,使用装饰器的方式注册,另外一种就是直接将obj作为参数调用_do_register进行注册。_do_register:真正注册的函数,可以看到它首先会判断name是否已经存在于self._obj_map了。什么意思呢?还是以backbone为例,我们定义了一个BACKBONE_REGISTRY = Registry('BACKBONE'),然后又定义了很多种backbone,而这些backbone都使用@BACKBONE_REGISTRY.register()的方式注册到了BACKBONE_REGISTRY._obj_map中了,所以才取名为Registry,还是蛮形象的吼。get: 这个其实就是根据key值对字典进行取值。
Detectron2 整体代码架构
虽然Detectron2还有很多部分没有介绍到,但是源代码分析到这应该对整体架构有了一定的理解了,具体的一些细节会在后续的文章中进行分析。现对Detectron2 整体代码架构总结一下:

Detectron2源码阅读笔记-(二)Registry&build_*方法的更多相关文章
- Detectron2源码阅读笔记-(一)Config&Trainer
代码结构概览 核心部分 configs:储存各种网络的yaml配置文件 datasets:存放数据集的地方 detectron2:运行代码的核心组件 tools:提供了运行代码的入口以及一切可视化的代 ...
- werkzeug源码阅读笔记(二) 下
wsgi.py----第二部分 pop_path_info()函数 先测试一下这个函数的作用: >>> from werkzeug.wsgi import pop_path_info ...
- Detectron2源码阅读笔记-(三)Dataset pipeline
构建data_loader原理步骤 # engine/default.py from detectron2.data import ( MetadataCatalog, build_detection ...
- werkzeug源码阅读笔记(二) 上
因为第一部分是关于初始化的部分的,我就没有发布出来~ wsgi.py----第一部分 在分析这个模块之前, 需要了解一下WSGI, 大致了解了之后再继续~ get_current_url()函数 很明 ...
- Android源码阅读笔记二 消息处理机制
消息处理机制: .MessageQueue: 用来描述消息队列2.Looper:用来创建消息队列3.Handler:用来发送消息队列 初始化: .通过Looper.prepare()创建一个Loope ...
- Apollo源码阅读笔记(二)
Apollo源码阅读笔记(二) 前面 分析了apollo配置设置到Spring的environment的过程,此文继续PropertySourcesProcessor.postProcessBeanF ...
- 【原】FMDB源码阅读(二)
[原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...
- Three.js源码阅读笔记-5
Core::Ray 该类用来表示空间中的“射线”,主要用来进行碰撞检测. THREE.Ray = function ( origin, direction ) { this.origin = ( or ...
- jdk源码阅读笔记-LinkedHashMap
Map是Java collection framework 中重要的组成部分,特别是HashMap是在我们在日常的开发的过程中使用的最多的一个集合.但是遗憾的是,存放在HashMap中元素都是无序的, ...
随机推荐
- Python爬虫爬取BT之家找电影资源
一.写在前面 最近看新闻说圣城家园(SCG)倒了,之前BT天堂倒了,暴风影音也不行了,可以说看个电影越来越费力,国内大厂如企鹅和爱奇艺最近也出现一些幺蛾子,虽然目前版权意识虽然越来越强,但是很多资源在 ...
- VUE:页面跳转时传递参数,及参数获取
https://www.cnblogs.com/zhongchao666/p/9679807.html https://blog.csdn.net/mf_717714/article/details/ ...
- windows上svn图标不显示 绿色对号
http://blog.csdn.net/fengyupeng/article/details/12514449 症状1:项目左侧导航栏表不能正常显示图标 方法:windows->prefere ...
- Beta冲刺(2/7)——2019.5.24
作业描述 课程 软件工程1916|W(福州大学) 团队名称 修!咻咻! 作业要求 项目Beta冲刺(团队) 团队目标 切实可行的计算机协会维修预约平台 开发工具 Eclipse 团队信息 队员学号 队 ...
- Prometheus安装部署说明
本文主要介绍了如何二进制安装Prometheus.使用 Node Exporter 采集主机信息并使用Grafana来进行图形化的展示. 1. 安装Prometheus Server Promethe ...
- win10 .net framework 3.5 离线安装 不需要外网
win 10如果安装系统时没有安装.net 3.5 那么在以后安装时就必须联网. win10 .net framework 3.5 离线安装工具: 链接: https://pan.baidu.com/ ...
- [转帖]分布式锁-redLock And Redisson
分布式锁-redLock And Redisson 2019-03-01 16:51:48 淹不死的水 阅读数 372更多 分类专栏: 分布式锁 版权声明:本文为博主原创文章,遵循CC 4.0 B ...
- 贪心 + 计算几何 --- Radar Installation
Radar Installation Description Assume the coasting is an infinite straight line. Land is in one side ...
- drf面试题及总结
drf面试题及总结 1.什么是前后端分离 2.什么是restful规范 3.模拟浏览器进行发送请求的工具 4.查找模板的顺序 5.什么是drf组件 6.drf组件提供的功能 7.drf继承过哪些视图类 ...
- 给Go程序加入编译版本时间等信息
先看效果 $./myapp -v GitCommitLog=d97d098e5bb4ad38a2a7968f273a256e10a0108f mod bininfo comment GitStatus ...