Unverified Commit 6434d0d7 authored by AluminiumOxide's avatar AluminiumOxide Committed by GitHub
Browse files

[Docs] Translate understand_mmcv about registry.md and fix config.md (#1204)



* Add Chinese translation of config.md.

* Add Chinese translation of registry.md and fix config.md

* Update config.md

* Update registry.md

* Update config.md

* Update config.md

* Update registry.md

* Update config.md

* fix format

* polish translation

* polish translation

* polish translation
Co-authored-by: default avatarzhouzaida <zhouzaida@163.com>
parent b4bfeb53
## 配置
欢迎有兴趣的朋友一起翻译 MMCV 文档。如有兴趣,请在 [MMCV issue](https://github.com/open-mmlab/mmcv/issues) 提 issue 确定翻译的文档。
`Config` 类用于操作配置文件,它支持从多种文件格式中加载配置,包括 **python**, **json****yaml**
它提供了类似字典对象的接口来获取和设置值。
以配置文件 `test.py` 为例
```python
a = 1
b = dict(b1=[0, 1, 2], b2=None)
c = (1, 2)
d = 'string'
```
加载与使用配置文件
```python
>>> cfg = Config.fromfile('test.py')
>>> print(cfg)
>>> dict(a=1,
... b=dict(b1=[0, 1, 2], b2=None),
... c=(1, 2),
... d='string')
```
对于所有格式的配置文件,都支持一些预定义变量。它会将 `{{ var }}` 替换为实际值。
目前支持以下四个预定义变量:
`{{ fileDirname }}` - 当前打开文件的目录名,例如 /home/your-username/your-project/folder
`{{ fileBasename }}` - 当前打开文件的文件名,例如 file.ext
`{{ fileBasenameNoExtension }}` - 当前打开文件不包含扩展名的文件名,例如 file
`{{ fileExtname }}` - 当前打开文件的扩展名,例如 .ext
这些变量名引用自 [VS Code](https://code.visualstudio.com/docs/editor/variables-reference)
这里是一个带有预定义变量的配置文件的例子。
`config_a.py`
```python
a = 1
b = './work_dir/{{ fileBasenameNoExtension }}'
c = '{{ fileExtname }}'
```
```python
>>> cfg = Config.fromfile('./config_a.py')
>>> print(cfg)
>>> dict(a=1,
... b='./work_dir/config_a',
... c='.py')
```
对于所有格式的配置文件, 都支持继承。为了重用其他配置文件的字段,
需要指定 `_base_='./config_a.py'` 或者一个包含配置文件的列表 `_base_=['./config_a.py', './config_b.py']`
这里有 4 个配置继承关系的例子。
`config_a.py` 作为基类配置文件
```python
a = 1
b = dict(b1=[0, 1, 2], b2=None)
```
### 不含重复键值对从基类配置文件继承
`config_b.py`
```python
_base_ = './config_a.py'
c = (1, 2)
d = 'string'
```
```python
>>> cfg = Config.fromfile('./config_b.py')
>>> print(cfg)
>>> dict(a=1,
... b=dict(b1=[0, 1, 2], b2=None),
... c=(1, 2),
... d='string')
```
`config_b.py`里的新字段与在`config_a.py`里的旧字段拼接
### 含重复键值对从基类配置文件继承
`config_c.py`
```python
_base_ = './config_a.py'
b = dict(b2=1)
c = (1, 2)
```
```python
>>> cfg = Config.fromfile('./config_c.py')
>>> print(cfg)
>>> dict(a=1,
... b=dict(b1=[0, 1, 2], b2=1),
... c=(1, 2))
```
在基类配置文件:`config_a` 里的 `b.b2=None`被配置文件:`config_c.py`里的 `b.b2=1`替代。
### 从具有忽略字段的配置文件继承
`config_d.py`
```python
_base_ = './config_a.py'
b = dict(_delete_=True, b2=None, b3=0.1)
c = (1, 2)
```
```python
>>> cfg = Config.fromfile('./config_d.py')
>>> print(cfg)
>>> dict(a=1,
... b=dict(b2=None, b3=0.1),
... c=(1, 2))
```
您还可以设置 `_delete_=True`忽略基类配置文件中的某些字段。所有在`b`中的旧键 `b1, b2, b3` 将会被新键 `b2, b3` 所取代。
### 从多个基类配置文件继承(基类配置文件不应包含相同的键)
`config_e.py`
```python
c = (1, 2)
d = 'string'
```
`config_f.py`
```python
_base_ = ['./config_a.py', './config_e.py']
```
```python
>>> cfg = Config.fromfile('./config_f.py')
>>> print(cfg)
>>> dict(a=1,
... b=dict(b1=[0, 1, 2], b2=None),
... c=(1, 2),
... d='string')
```
### 从基类引用变量
您可以使用以下语法引用在基类中定义的变量。
`base.py`
```python
item1 = 'a'
item2 = dict(item3 = 'b')
```
`config_g.py`
```python
_base_ = ['./base.py']
item = dict(a = {{ _base_.item1 }}, b = {{ _base_.item2.item3 }})
```
```python
>>> cfg = Config.fromfile('./config_g.py')
>>> print(cfg.pretty_text)
item1 = 'a'
item2 = dict(item3='b')
item = dict(a='a', b='b')
```
## 注册器
MMCV 使用 [注册器](https://github.com/open-mmlab/mmcv/blob/master/mmcv/utils/registry.py) 来管理具有相似功能的不同模块, 例如, 检测器中的主干网络、头部、和模型颈部。
在 OpenMMLab 家族中的绝大部分开源项目使用注册器去管理数据集和模型的模块,例如 [MMDetection](https://github.com/open-mmlab/mmdetection), [MMDetection3D](https://github.com/open-mmlab/mmdetection3d), [MMClassification](https://github.com/open-mmlab/mmclassification), [MMEditing](https://github.com/open-mmlab/mmediting) 等。
欢迎有兴趣的朋友一起翻译 MMCV 文档。如有兴趣,请在 [MMCV issue](https://github.com/open-mmlab/mmcv/issues) 提 issue 确定翻译的文档。
### 什么是注册器
在MMCV中,注册器可以看作类到字符串的映射。
一个注册器中的类通常有相似的接口,但是可以实现不同的算法或支持不同的数据集。
借助注册器,用户可以通过使用相应的字符串查找并实例化该类,并根据他们的需要实例化对应模块。
一个典型的案例是,OpenMMLab 中的大部分开源项目的配置系统,这些系统通过配置文件来使用注册器创建钩子、执行器、模型和数据集。
可以在[这里](https://mmcv.readthedocs.io/en/latest/api.html?highlight=registry#mmcv.utils.Registry)找到注册器接口使用文档。
使用 `registry`(注册器)管理代码库中的模型,需要以下三个步骤。
1. 创建一个构建方法(可选,在大多数情况下您可以只使用默认方法)
2. 创建注册器
3. 使用此注册器来管理模块
`Registry`(注册器)的参数 `build_func`(构建函数) 用来自定以如何实例化类的实例,默认使用 [这里](https://mmcv.readthedocs.io/en/latest/api.html?highlight=registry#mmcv.utils.build_from_cfg)实现的`build_from_cfg`
### 一个简单的例子
这里是一个使用注册器管理包中模块的简单示例。您可以在 OpenMMLab 开源项目中找到更多实例。
假设我们要实现一系列数据集转换器(Dataset Converter),用于将不同格式的数据转换为标准数据格式。我们先创建一个名为converters的目录作为包,在包中我们创建一个文件来实现构建器(builder),命名为converters/builder.py,如下
```python
from mmcv.utils import Registry
# 创建转换器(converter)的注册器(registry)
CONVERTERS = Registry('converter')
```
然后我们在包中可以实现不同的转换器(converter)。例如,在 `converters/converter1.py` 中实现 `Converter1`
```python
from .builder import CONVERTERS
# 使用注册器管理模块
@CONVERTERS.register_module()
class Converter1(object):
def __init__(self, a, b):
self.a = a
self.b = b
```
使用注册器管理模块的关键步骤是,将实现的模块到注册到注册表 `CONVERTERS` 中。通过 `@CONVERTERS.register_module()` 装饰所实现的模块,字符串和类之间的映射就可以由 `CONVERTERS` 构建和维护,如下所示:
通过这种方式,就可以通过 `CONVERTERS` 建立字符串与类之间的映射,如下所示:
```python
'Converter1' -> <class 'Converter1'>
```
如果模块被成功注册了,你可以通过配置文件使用这个转换器(converter),如下所示:
```python
converter_cfg = dict(type='Converter1', a=a_value, b=b_value)
converter = CONVERTERS.build(converter_cfg)
```
### 自定义构建函数
假设我们想自定义 `converters` 的构建流程,我们可以实现一个自定义的 `build_func` (构建函数)并将其传递到注册器中。
```python
from mmcv.utils import Registry
# 创建一个构建函数
def build_converter(cfg, registry, *args, **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)``build_converter`` 函数
CONVERTERS = Registry('converter', build_func=build_converter)
```
```{note}
注:在这个例子中,我们演示了如何使用参数:`build_func` 自定义构建类的实例的方法。
该功能类似于默认的`build_from_cfg`。在大多数情况下,默认就足够了。
```
`build_model_from_cfg`也实现了在`nn.Sequentail`中构建PyTorch模块,你可以直接使用它们现。
### 注册器层结构
你也可以从多个 OpenMMLab 开源框架中构建模块,例如,你可以把所有 [MMClassification](https://github.com/open-mmlab/mmclassification) 中的主干网络(backbone)用到 [MMDetection](https://github.com/open-mmlab/mmdetection) 的目标检测中,你也可以融合 [MMDetection](https://github.com/open-mmlab/mmdetection) 中的目标检测模型 和 [MMSegmentation](https://github.com/open-mmlab/mmsegmentation) 语义分割模型。
下游代码库中所有 `MODELS` 注册器都是MMCV `MODELS` 注册器的子注册器。基本上,使用以下两种方法从子注册器或相邻兄弟注册器构建模块。
1. 从子注册器中构建
例如:
我们在 MMDetection 中定义:
```python
from mmcv.utils import Registry
from mmcv.cnn import MODELS as MMCV_MODELS
MODELS = Registry('model', parent=MMCV_MODELS)
@MODELS.register_module()
class NetA(nn.Module):
def forward(self, x):
return x
```
我们在 MMClassification 中定义:
```python
from mmcv.utils import Registry
from mmcv.cnn import MODELS as MMCV_MODELS
MODELS = Registry('model', parent=MMCV_MODELS)
@MODELS.register_module()
class NetB(nn.Module):
def forward(self, x):
return x + 1
```
我们可以通过以下代码在 MMDetection 或 MMClassification 中构建两个网络:
```python
from mmdet.models import MODELS
net_a = MODELS.build(cfg=dict(type='NetA'))
net_b = MODELS.build(cfg=dict(type='mmcls.NetB'))
```
```python
from mmcls.models import MODELS
net_a = MODELS.build(cfg=dict(type='mmdet.NetA'))
net_b = MODELS.build(cfg=dict(type='NetB'))
```
2. 从父注册器中构建
MMCV中的共享`MODELS`注册器是所有下游代码库的父注册器(根注册器):
```python
from mmcv.cnn import MODELS as MMCV_MODELS
net_a = MMCV_MODELS.build(cfg=dict(type='mmdet.NetA'))
net_b = MMCV_MODELS.build(cfg=dict(type='mmcls.NetB'))
```
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment