Mecanismo de registro MMCV

Tabla de contenido

introducción

1. Introducción

2. Componentes principales de MMCV: configuración y registro 

2.1 Clase de configuración

2.2 Generar clase de configuración desde el archivo de configuración

2.3 Análisis de variables predefinidas

2.4 Herencia de archivos de configuración

2.5 Registro

2.6 Ejemplos 

2.7 Función de compilación personalizada (Función de compilación)

2.8 Registro Jerárquico


introducción

      Aprendizaje de MMCV Estoy aprendiendo la biblioteca básica de mmcv recientemente, así que escriba un blog para registrarlo. Uno es como una nota de estudio para futuras referencias y el otro es para compartir e intercambiar mi experiencia de aprendizaje con ustedes. mmcv es una biblioteca básica de visión artificial de código abierto de OpenMMLab, que admite muchos almacenes de código abierto excelentes de OpenMMLab (como MMDetection, MMSegmentation, MMSelfSup, etc.).

1. Introducción

  Como biblioteca básica, mmcv proporciona principalmente los siguientes módulos funcionales:

  • API io unificada y escalable
  • Admite operadores de procesamiento de imagen/video muy ricos
  • Visualización de archivos de anotaciones de imagen/video
  • Clases de herramientas comunes como temporizador y barra de progreso, etc.
  • El mecanismo de gancho requerido por el marco superior y el corredor que se puede usar directamente
  • Mecanismo de registro y esquema cfg altamente flexible
  • cuda op eficiente y de alta calidad

2. Componentes principales de MMCV: configuración y registro 

2.1 Clase de configuración

El sitio web oficial explica:

  Config La clase se usa para manipular archivos de configuración y configuración. Admite la carga de configuraciones desde múltiples formatos de archivo, incluidos  pythonjson  y  yaml . Proporciona  API similares a dictados  para  obtener  y  establecer  valores.

2.2 Generar clase de configuración desde el archivo de configuración

Supongamos que tenemos un archivo config.py definido de la siguiente manera:

a = 1
b = dict(b1=[0, 1, 2], b2=None)
c = (1, 2)
d = 'string'

Leemos este archivo python directamente y lo imprimimos:

config = Config.fromfile("config.py")
print(config)
print(type(config))
# Output
# Config (path: config.py): {'a': 1, 'b': {'b1': [0, 1, 2], 'b2': None}, 'c': (1, 2), 'd': 'string'}
# <class 'mmcv.utils.config.Config'>

2.3 Análisis de variables predefinidas

      Además de definir directamente las variables de configuración, Config también admite el análisis de variables predefinidas, cuyo formato es el siguiente { { var } } \{\{ var \}\} { {var}} . Actualmente, Config admite el análisis de cuatro variables predefinidas, que pueden obtener fácilmente las distintas partes de la ruta absoluta del archivo de configuración abierto:

  • { { file D irname } } \{\{ \mathrm{fileDirname} \}\} { {fileDirname}}: el directorio donde se encuentra el archivo de configuración actualmente abierto.
  • { { file Basename } } \{\{ \mathrm{fileBasename} \}\} { {fileBasename}}: el nombre del archivo de configuración abierto actualmente, con sufijo.
  • { { file Basename N o Extension } } \{\{ \mathrm{fileBasenameNoExtension} \}\} {{ fileBasenameNoExtension}}: el nombre del archivo de configuración abierto actualmente sin extensión.
  • { { file Extname } } \{\{ \mathrm{fileExtname } \}\} { {fileExtname}}: el sufijo del archivo de configuración abierto actualmente.

 Sin embargo, de hecho, a partir de la impresión anterior del objeto de ejemplo de configuración, podemos ver que el mmcv actual proporciona la ruta del atributo de objeto para el ejemplo de configuración , y podemos usar directamente el atributo de ruta para obtener la ruta absoluta de la configuración abierta.

2.4 Herencia de archivos de configuración

 Teniendo en cuenta la reutilización de los archivos de configuración, mmcv proporciona una serie de operaciones de herencia de archivos de configuración y permite a los usuarios seleccionar de manera flexible las partes heredadas.

 Para hacer que un archivo de configuración herede otro archivo de configuración, solo necesita especificar la variable _base_ en el archivo de subconfiguración como la  ruta relativa del archivo de configuración principal (relativa a config_b)  . Por ejemplo, tenemos un archivo de configuración config_a.py de la siguiente manera:

# config_a.py
a = 1
b = dict(b1=[0, 1, 2], b2=None)

 Para heredar config_a, podemos especificar la variable _base_ en el archivo config_b:

# config_b.py
_base_ = './config_a.py'
b = dict(b2=1)
c = (1, 2)
config = Config.fromfile("./config_b.py")
print(config)
# Output
# Config (path: ./config_b.py): {'a': 1, 'b': {'b1': [0, 1, 2], 'b2': 1}, 'c': (1, 2)}

        Como se puede ver en el resultado anterior, cuando hay un conflicto clave entre el archivo de configuración secundaria y el archivo de configuración principal (b.b2), el archivo de configuración secundaria será el principal. Este comportamiento es muy similar al proceso de herencia en la orientación a objetos, por lo que también se denomina herencia de archivos de configuración en lugar de síntesis de archivos de configuración. PD:  Config admite la herencia de varios archivos, solo necesita definir _base_ como una lista de ['config1.py', 'config2.py', ...], pero la misma configuración base no puede existir clave , de lo contrario Config no lo hará saber qué base usar.

 Veamos una sintaxis más útil en la herencia de configuración , que nos permite usar directamente las variables definidas en el archivo de configuración principal en el archivo de configuración secundario. Por ejemplo, queremos usar variables en el archivo de configuración principal config_a.py en el archivo de configuración secundario config_c.py:

# config_c.py
_base_ = ['./config_a.py']
item = dict(a = {
   
   { _base_.a}}, b = {
   
   {_base_.b.b1}})
config = Config.fromfile("./config_c.py")
print(config)
# Output:
# Config (path: ./config_c.py): {'a': 1, 'b': {'b1': [0, 1, 2], 'b2': None}, 'item': {'a': 1, 'b': [0, 1, 2]}}

2.5 Registro

Explicación oficial:

MMCV implementa  registry para administrar diferentes módulos que comparten  funcionalidades similares , por ejemplo, backbones, cabeza y cuello, en detectores.

En MMCV, el registro puede considerarse como un mapeo entre cadenas y clases.Estas clases bajo el mismo registro tienen funciones similares, que son algo similares al polimorfismo orientado a objetos. Con el registro, los usuarios pueden llamar e instanciar esas clases usando cadenas. El proceso de uso del Registro se divide principalmente en los siguientes tres pasos:

  • Crear un constructor (opcional)
  • crear registro
  • El registro se utiliza para administrar estos módulos.

2.6 Ejemplos 

      Tomemos un ejemplo simple para ver cómo usar el Registro para administrar los módulos en un paquete. Suponiendo que tenemos un paquete convertidor, existen clases convertidoras con diferentes funciones que implementamos.
 Primero, ahora crearemos el archivo converter/builder.py para crear el registro para el convertidor:

# converter/builder.py
from mmcv.utils import Registry
CONVERTERS = Registry("converter")

 Luego use CONVERTERS para registrar la clase Converter1 que queremos administrar:

# converter/conerter1.py
from .builder import CONVERTERS

# 这里需要说明一下, 由于python的装饰器机制是在类定义被加载时触发,所以一般需要在converter/__init__.py里面去import这个类。
@CONVERTERS.register_module()
class Converter1(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

Suponiendo que hay un archivo principal externo, si se usa la clase Converter1, entonces nuestro método de escritura puede volverse más elegante en lugar de importar en todas partes:

# main.py
from converter import CONVERTERS

if __name__ == "__main__":
    converter_cfg = dict(type='Converter1', a=1, b=2)
    converter = CONVERTERS.build(converter_cfg)  # 这里的build是mmcv帮我们默认实现了
    print(converter)

2.7 Función de compilación personalizada (Función de compilación)

 El ejemplo introductorio anterior acaba de explicar cómo usar el Registro para instanciar la clase administrada. De forma predeterminada, es suficiente usar la función de compilación implementada por mmcv para leer el archivo de configuración e instanciarlo. Este tipo de método de administración realiza el proceso desde el archivo de configuración hasta la clase de creación de instancias directamente, de modo que si desea modificar algunos parámetros en el futuro, solo necesita modificar el archivo de configuración, lo cual es muy conveniente.
 Si necesitamos personalizar el constructor, podemos personalizarlo de la siguiente manera:

# converter/builder.py
from mmcv.utils import Registry


def build_converter(cfg, registry, *args, **kwargs):
    # print(args)
    # print(kwargs)
    cfg_ = cfg.copy()
    converter_type = cfg_.pop("type")
    if converter_type not in registry:
        raise KeyError(f"Unrecognized converter type {converter_type}")
    else:
        converter_cls = registry.get(converter_type)
    converter = converter_cls(*args, **kwargs, **cfg_)
    return converter


CONVERTERS = Registry("converter", build_func=build_converter)

2.8 Registro Jerárquico

 El registro de todos los modelos de base de código aguas abajo de MMCV es MODELSun subregistro de mmcv. Generalmente, hay dos formas de instanciar el modelo desde el registro hermano y el registro principal:

(1) Instanciar desde el registro hermano:

# 假设我们有一个classfication的代码库叫mmcls.py
from mmcv.utils import Registry
from mmcv.cnn import MODELS as MMCV_MODELS
from torch import nn

# Create a register
MODELS = Registry("model", parent=MMCV_MODELS)

# classification net
@MODELS.register_module()
class ClsNet(nn.Module):

    def __init__(self) -> None:
        super().__init__()
# detection的代码库叫mmdet.py
from mmcv.utils import Registry
from mmcv.cnn import MODELS as MMCV_MODELS
import mmcls
from torch import nn

# Create a register
MODELS = Registry("model", parent=MMCV_MODELS)

# Detection net
@MODELS.register_module()
class DetNet(nn.Module):

    def __init__(self) -> None:
        super().__init__()

# 这里我们使用mmdet的registry去实例化cls_net和det_net, 所以det_net不加模块名而cls_net要加
if __name__ == "__main__":
    det_net = MODELS.build({"type": "DetNet"})
    cls_net = MODELS.build({"type": "mmcls.ClsNet"})
    print(det_net)
    print(cls_net)

(2) Crear una instancia del registro de la clase padre:

# 外部父类的文件hierarchy_reg.py实例化
from mmcv.cnn import MODELS as MMCV_MODELS
import mmcls
import mmdet


if __name__ == "__main__":
    det_net = MMCV_MODELS.build({"type": "mmdet.DetNet"})
    cls_net = MMCV_MODELS.build({"type": "mmcls.ClsNet"})
    print(det_net)
    print(cls_net)

Supongo que te gusta

Origin blog.csdn.net/m0_53675977/article/details/130783257
Recomendado
Clasificación