翼度科技»论坛 编程开发 python 查看内容

python如何通过注册表动态管理组件

8

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
  1. mmengine.registry
复制代码
是一个在多个开源项目(如 MMEngine 和 MM系列工具包,例如 MMDetection、MMClassification 等)中使用的模块化管理机制,旨在通过注册表动态管理不同的组件,例如模型、算法、损失函数或插件等。这个机制极大地增强了项目的灵活性和扩展性。

1 基本概念


1.1 Registry 类

Registry是一个存储映射关系的容器,它将字符串类型的键(通常是组件的名字)映射到具体的 Python 对象(如类或函数)。使用注册表的主要优势是可以在运行时动态创建对象,从而实现高度可配置和可扩展的设计。

1.2 核心功能

注册机制
提供了一个
  1. register_module
复制代码
方法,允许开发者将类或函数注册到注册表中。这通常通过装饰器的形式实现,使得代码更加简洁和直观。注册时可以指定一个或多个名称作为键,关联到相应的 Python 类或函数。

动态创建实例
注册表可以使用
  1. build
复制代码
方法根据配置动态创建类的实例。这通常需要配置信息包括键名
  1. type
复制代码
(对应注册的名称)和其他用于初始化对象的参数。通过读取配置文件(通常是 JSON 或 YAML 格式),可以在不修改代码的情况下轻松切换使用的组件或调整参数。

作用域管理
在某些复杂的应用场景中,
  1. Registry
复制代码
可能需要处理多个域(scope)下的注册问题,例如不同的模块可能需要有各自独立的注册表。
  1. Registry
复制代码
类可以通过指定
  1. scope
复制代码
参数来实现作用域管理,使得同一个名字在不同的作用域下可以关联到不同的对象。

继承
注册表可以设置父注册表,使得查找过程可以在当前注册表未找到对应键值时回溯到父注册表中查找。这为模块间的依赖提供了方便,也允许更灵活的重载和扩展。

2 实现示例


2.1 简化的Registry类实现

展示了如何定义这个类,以及如何注册和创建对象:
  1. class Registry:
  2.     def __init__(self, name, scope=None, parent=None):
  3.         self.name = name
  4.         self.scope = scope
  5.         self.parent = parent
  6.         self._module_dict = {}
  7.     def register_module(self, name=None):
  8.         def _register(cls):
  9.             module_name = name or cls.__name__
  10.             if module_name in self._module_dict:
  11.                 raise KeyError(f'{module_name} is already registered in {self.scope}::{self.name}')
  12.             self._module_dict[module_name] = cls
  13.             return cls
  14.         return _register
  15.     def get(self, name):
  16.         if name in self._module_dict:
  17.             return self._module_dict[name]
  18.         elif self.parent:
  19.             return self.parent.get(name)
  20.         else:
  21.             raise KeyError(f'{name} is not registered in {self.scope}::{self.name} and no parent registry to fallback.')
  22.     def build(self, cfg):
  23.         module_name = cfg['type']
  24.         module_cls = self.get(module_name)
  25.         return module_cls(**{k: v for k, v in cfg.items() if k != 'type'})
复制代码
2.2 这个注册表类
  1. from torch import nn
  2. # 创建父注册表
  3. MODELS = Registry('models', scope='mmengine')
  4. # 注册一个模块到父注册表
  5. @MODELS.register_module()
  6. class ResNet(nn.Module):
  7.     def __init__(self, layers):
  8.         self.layers = layers
  9.     def forward(self, x):
  10.         return x
  11. # 创建子注册表,指定 MODELS 为父注册表
  12. DETECTORS = Registry('detectors', scope='mmengine', parent=MODELS)
  13. # 注册一个模块只到子注册表
  14. @DETECTORS.register_module()
  15. class FasterRCNN(nn.Module):
  16.     def __init__(self, num_classes):
  17.         self.num_classes = num_classes
  18.     def forward(self, x):
  19.         return x
  20. # 从子注册表构建 ResNet 实例,尽管它是在父注册表中注册的
  21. resnet_instance = DETECTORS.build({'type': 'ResNet', 'layers': 50})
  22. print(resnet_instance)
  23. # 直接从子注册表构建 FasterRCNN 实例
  24. fasterrcnn_instance = DETECTORS.build({'type': 'FasterRCNN', 'num_classes': 80})
  25. print(fasterrcnn_instance)
复制代码
到此这篇关于python如何通过注册表动态管理组件的文章就介绍到这了,更多相关python动态管理组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

来源:https://www.jb51.net/python/321094ek7.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具