Skip to content

Add Builde Func API comments #84

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 41 additions & 8 deletions mindocr/data/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,26 @@ def build_dataset(
**kwargs,
):
'''
Build dataset
Build dataset for training and evaluation.

Args:
dataset_config (dict): dataset parsing and processing configuartion containing the following keys
- type (str): dataset class name, please choose from `supported_dataset_types`.
- dataset_root (str): the root directory to store the (multiple) dataset(s)
- data_dir (Union[str, List[str]]): directory to the data, which is a subfolder path related to `dataset_root`. For multiple datasets, it is a list of subfolder paths.
- label_file (Union[str, List[str]]): file path to the annotation related to the `dataset_root`. For multiple datasets, it is a list of relative file paths.
- label_file (Union[str, List[str]], *optional*): file path to the annotation related to the `dataset_root`. For multiple datasets, it is a list of relative file paths. Not required if using LMDBDataset.
- sample_ratio (float): the sampling ratio of dataset.
- shuffle (boolean): whether to shuffle the order of data samples.
- transform_pipeline (list[dict]): each element corresponds to a transform operation on image and/or label
- output_columns (list[str]): list of output features for each sample.
- num_columns_to_net (int): num inputs for network forward func in output_columns
loader_config (dict): dataloader configuration containing keys:
- batch_size: batch size for data loader
- drop_remainder: whether to drop the data in the last batch when the total of data can not be divided by the batch_size
num_shards: num of devices for distributed mode
shard_id: device id
is_train: whether it is in training stage
- batch_size (int): batch size for data loader
- drop_remainder (boolean): whether to drop the data in the last batch when the total of data can not be divided by the batch_size
- num_workers (int): number of subprocesses used to fetch the dataset in parallel.
num_shards (int, *optional*): num of devices for distributed mode
shard_id (int, *optional*): device id
is_train (boolean): whether it is in training stage

Return:
data_loader (Dataset): dataloader to generate data batch
Expand All @@ -41,7 +47,34 @@ def build_dataset(
- The main data process pipeline in MindSpore contains 3 parts: 1) load data files and generate source dataset, 2) perform per-data-row mapping such as image augmentation, 3) generate batch and apply batch mapping.
- Each of the three steps supports multiprocess. Detailed machenism can be seen in https://www.mindspore.cn/docs/zh-CN/r2.0.0-alpha/api_python/mindspore.dataset.html
- A data row is a data tuple item containing multiple elements such as (image_i, mask_i, label_i). A data column corresponds to an element in the tuple like 'image', 'label'.
- The total number of `num_parallel_workers` used for data loading and processing should not be larger than the maximum threads of the CPU. Otherwise, it will lead to resource competing overhead. Especially for distributed training, `num_parallel_workers` should not be too large to avoid thread competition.
- The total number of `num_workers` used for data loading and processing should not be larger than the maximum threads of the CPU. Otherwise, it will lead to resource competing overhead. Especially for distributed training, `num_parallel_workers` should not be too large to avoid thread competition.

Example:
>>> # Load a DetDataset/RecDataset
>>> from mindocr.data import build_dataset
>>> data_config = {
>>> "type": "DetDataset",
>>> "dataset_root": "path/to/datasets/",
>>> "data_dir": "ic15/det/train/ch4_test_images",
>>> "label_file": "ic15/det/train/det_gt.txt",
>>> "sample_ratio": 1.0,
>>> "shuffle": False,
>>> "transform_pipeline": [
>>> {
>>> "DecodeImage": {
>>> "img_mode": "RGB",
>>> "to_float32": False
>>> }
>>> },
>>> {
>>> "DetLabelEncode": {},
>>> },
>>> ],
>>> "output_columns": ['image', 'polys', 'ignore_tags'],
>>> "num_columns_to_net": 1
>>> }
>>> loader_config = dict(shuffle=True, batch_size=16, drop_remainder=False, num_workers=1)
>>> data_loader = build_dataset(data_config, loader_config, num_shards=1, shard_id=0, is_train=True)
'''
# Check dataset paths (dataset_root, data_dir, and label_file) and update to absolute format
dataset_config = _check_dataset_paths(dataset_config)
Expand Down
16 changes: 15 additions & 1 deletion mindocr/losses/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,22 @@

def build_loss(name, **kwargs):
"""
Create the loss function.

Args:
name: loss name, exactly the same as one of the supported loss class names
name (str): loss function name, exactly the same as one of the supported loss class names

Return:
nn.LossBase

Example:
>>> # Create a CTC Loss module
>>> from mindocr.losses import build_loss
>>> loss_func_name = "CTCLoss"
>>> loss_func_config = {"pred_seq_len": 25, "max_label_len": 24, "batch_size": 32}
>>> loss_fn = build_loss(loss_func_name, **loss_func_config)
>>> loss_fn
CTCLoss<>
"""
assert name in supported_losses, f'Invalid loss name {name}, support losses are {supported_losses}'

Expand Down
19 changes: 19 additions & 0 deletions mindocr/metrics/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@

# TODO: support multiple metrics
def build_metric(config):
"""
Create the metric function.

Args:
config (dict): configuration for metric including metric `name` and also the kwargs specifically for each metric.
- name (str): metric function name, exactly the same as one of the supported metric class names

Return:
nn.Metric

Example:
>>> # Create a RecMetric module for text recognition
>>> from mindocr.metrics import build_metric
>>> metric_config = {"name": "RecMetric", "main_indicator": "acc", "character_dict_path": None, "ignore_space": True, "print_flag": False}
>>> metric = build_metric(metric_config)
>>> metric
<mindocr.metrics.rec_metrics.RecMetric>
"""

mn = config.pop('name')
if mn in supported_metrics:
metric = eval(mn)(**config)
Expand Down
14 changes: 9 additions & 5 deletions mindocr/models/backbones/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,30 @@

def build_backbone(name, **kwargs):
'''
Build the backbone network.

Args:
name (string): the backbone name, which can be a registered backbone class name
name (str): the backbone name, which can be a registered backbone class name
or a registered backbone (function) name.
kwargs: input args for the backbone
kwargs (dict): input args for the backbone
1) if `name` is in the registered backbones (e.g. det_resnet50), kwargs include args for backbone creating likes `pretrained`
2) if `name` is in the registered backbones class (e.g. DetResNet50), kwargs include args for the backbone configuration like `layers`.

Return:
nn.Cell for backbone moduel
nn.Cell for backbone module

Construct:
Input: Tensor
Output: List[Tensor]

Example:
>>> # build using backbone function name
>>> from mindocr.models.backbones import build_backbone
>>> backbone = build_backbone('det_resnet50', pretrained=True)
>>> # build using backbone class name
>>> cfg_from_class = dict(name='DetResNet', layers=[3,4,6,3])
>>> backbone = build_backbone(cfg_from_class)
>>> from mindcv.models.resnet import Bottleneck
>>> cfg_from_class = dict(name='DetResNet', block=Bottleneck, layers=[3,4,6,3])
>>> backbone = build_backbone(**cfg_from_class)
>>> print(backbone)
'''
#name = config.pop('name')
Expand Down
7 changes: 5 additions & 2 deletions mindocr/models/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@ def build_model(config: Union[dict, str], **kwargs): #config: Union[dict,str]):
2. build the model according to the detailed configuration of the each module (transform, backbone, neck and head), for lower-level architecture customization.

Args:
config: if it is a str, config is the model name. Predefined model with weights will be returned.
config (Union[dict, str]): if it is a str, config is the model name. Predefined model with weights will be returned.
if dict, config is a dictionary and the available keys are:
model_name: string, model name in the registered models
pretrained: bool, if True, download the pretrained weight for the preset url and load to the network.
backbone: dict, a dictionary containing the backbone config, the available keys are defined in backbones/builder.py
neck: dict,
head: dict,
kwargs: if config is a str of model name, kwargs contains the args for the model.


Return:
nn.Cell

Example:
>>> from mindocr.models import build_model
>>> net = build_model(cfg['model'])
>>> net = build_model(cfg['model'], ckpt_load_path='./r50_fpn_dbhead.ckpt') # build network and load checkpoint
>>> net = build_model('dbnet_r50', pretrained=True)
Expand Down
21 changes: 21 additions & 0 deletions mindocr/models/heads/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@


def build_head(head_name, **kwargs):
"""
Build Head network.

Args:
head_name (str): the head layer(s) name, which shoule be one of the supported_heads.
kwargs (dict): input args for the head network

Return:
nn.Cell for head module

Construct:
Input: Tensor
Output: Dict[Tensor]

Example:
>>> # build CTCHead
>>> from mindocr.models.heads import build_head
>>> config = dict(head_name='CTCHead', in_channels=256, out_channels=37)
>>> head = build_head(**config)
>>> print(head)
"""
assert head_name in supported_heads, f'Invalid head {head_name}. Supported heads are {supported_heads}'
head = eval(head_name)(**kwargs)
return head
21 changes: 21 additions & 0 deletions mindocr/models/necks/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@


def build_neck(neck_name, **kwargs):
"""
Build Neck network.

Args:
neck_name (str): the neck name, which shoule be one of the supported_necks.
kwargs (dict): input args for the neck network

Return:
nn.Cell for neck module

Construct:
Input: Tensor
Output: Dict[Tensor]

Example:
>>> # build RNNEncoder
>>> from mindocr.models.necks import build_neck
>>> config = dict(neck_name='RNNEncoder', in_channels=128, hidden_size=256)
>>> neck = build_neck(**config)
>>> print(neck)
"""
assert neck_name in supported_necks, f'Invalid neck: {neck_name}, Support necks are {supported_necks}'
neck = eval(neck_name)(**kwargs)
return neck
17 changes: 17 additions & 0 deletions mindocr/postprocess/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@
supported_postprocess = det_postprocess.__all__ + rec_postprocess.__all__

def build_postprocess(config: dict):
"""
Create postprocess function.

Args:
config (dict): configuration for postprocess including postprocess `name` and also the kwargs specifically for each postprocessor.
- name (str): metric function name, exactly the same as one of the supported postprocess class names

Return:
Object

Example:
>>> # Create postprocess function
>>> from mindocr.postprocess import build_postprocess
>>> config = dict(name="RecCTCLabelDecode", use_space_char=False)
>>> postprocess = build_postprocess(config)
>>> postprocess
"""
proc = config.pop('name')
if proc in supported_postprocess:
postprocessor = eval(proc)(**config)
Expand Down