Skip to content
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

[Feature] add config new feature #105

Merged
merged 56 commits into from
Aug 8, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
8f2e7bc
update
HAOCHENYE Mar 6, 2022
af597a1
update
HAOCHENYE Mar 6, 2022
1ee2c59
update
HAOCHENYE Mar 6, 2022
db8df66
add config new feature
HAOCHENYE Mar 7, 2022
22a042a
update
HAOCHENYE Mar 7, 2022
fe61253
update
HAOCHENYE Mar 7, 2022
a9ad44d
remove unused file
HAOCHENYE Mar 7, 2022
d91aa0d
Update pretrained
HAOCHENYE Mar 7, 2022
89e15de
update
HAOCHENYE Mar 7, 2022
837128b
Fix as commetn
HAOCHENYE Mar 9, 2022
43b6eac
update
HAOCHENYE Mar 9, 2022
45c77c8
update
HAOCHENYE Mar 10, 2022
752ea85
Add get_config and get_model test
HAOCHENYE Mar 10, 2022
23b3720
update
HAOCHENYE Mar 10, 2022
d38004c
resolve conflict in mmengine.__init__.py
HAOCHENYE Mar 14, 2022
cb024df
clean code and add comment to config.py
HAOCHENYE Mar 14, 2022
c6d7ddf
fix cycle import
HAOCHENYE Mar 14, 2022
4591f41
fix as comment
HAOCHENYE Jun 10, 2022
69e41a0
temp save
HAOCHENYE Jun 20, 2022
69086c1
tmp
HAOCHENYE Jun 20, 2022
ab9d516
tmp
HAOCHENYE Jun 20, 2022
c754b4c
add unit test
HAOCHENYE Jun 21, 2022
23c4e93
support modify base variable and add unit test
HAOCHENYE Jun 21, 2022
14cfb57
refine build and docstring
HAOCHENYE Jun 21, 2022
f8940c7
move switch scope to build_from_cfg
HAOCHENYE Jun 22, 2022
33d9853
add docstring
HAOCHENYE Jun 22, 2022
da4e1ef
add build model from cfg
HAOCHENYE Jun 22, 2022
2ed530b
fix root registry
HAOCHENYE Jun 22, 2022
20b550d
Merge remote-tracking branch 'origin/main' into HAOCHENYE/config_new_…
HAOCHENYE Jun 22, 2022
313124c
fix docstring
HAOCHENYE Jun 22, 2022
34a7b14
fix remove scope bug
HAOCHENYE Jun 23, 2022
aa3d085
Merge remote-tracking branch 'origin/HAOCHENYE/config_new_feature' in…
HAOCHENYE Jun 23, 2022
b60ef05
fix bug in get model
HAOCHENYE Jun 23, 2022
a33bbae
fix get model bug
HAOCHENYE Jun 24, 2022
fa74795
Merge remote-tracking branch 'origin/HAOCHENYE/config_new_feature' in…
HAOCHENYE Jun 24, 2022
960feb7
add scope to list cfg
HAOCHENYE Jun 27, 2022
5f7a0f5
support get attribute of base variable in config
HAOCHENYE Jun 29, 2022
4afed70
add docstring to _dict_to_config_dict
HAOCHENYE Jun 29, 2022
5b8a2d8
minor refine
HAOCHENYE Jun 29, 2022
2114c25
fix lint
HAOCHENYE Jun 29, 2022
bc53cc8
update registry code
HAOCHENYE Jun 30, 2022
1db616b
add scope when access
HAOCHENYE Jul 4, 2022
aeaa4af
Merge branch 'main' into HAOCHENYE/config_new_feature
HAOCHENYE Jul 4, 2022
c07c0cd
remove unnecessary scope in local base config
HAOCHENYE Jul 4, 2022
b3ea3e3
upload test file
HAOCHENYE Jul 4, 2022
672f95d
fix circle import
HAOCHENYE Jul 4, 2022
2f86cbb
refine ut
HAOCHENYE Jul 6, 2022
912ed85
Merge branch 'main' into HAOCHENYE/config_new_feature
HAOCHENYE Jul 14, 2022
9d4e4c3
fix nested get external config bug
HAOCHENYE Jul 14, 2022
cf75c4e
add comments
HAOCHENYE Jul 14, 2022
aef5dbe
Merge branch 'main' into HAOCHENYE/config_new_feature
HAOCHENYE Jul 21, 2022
2cfb3fa
remove check install in switch_scope_and_registry
HAOCHENYE Jul 27, 2022
4815a55
Merge branch 'main' into HAOCHENYE/config_new_feature
HAOCHENYE Aug 4, 2022
620a36d
only pick first weight
HAOCHENYE Aug 5, 2022
9c20498
Merge branch 'main' into HAOCHENYE/config_new_feature
HAOCHENYE Aug 8, 2022
048c138
fix comment
HAOCHENYE Aug 8, 2022
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
Prev Previous commit
Next Next commit
fix as comment
  • Loading branch information
HAOCHENYE committed Jun 10, 2022
commit 4591f41d127ceacee9039b491b34aed093fdf82f
6 changes: 3 additions & 3 deletions mmengine/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ def _file2dict(filename: str,
check_file_exist(filename)
fileExtname = osp.splitext(filename)[1]
if fileExtname not in Config._valid_format:
raise IOError('Only py/yml/yaml/json type are supported now!')
raise OSError('Only py/yml/yaml/json type are supported now!')

with tempfile.TemporaryDirectory() as temp_config_dir:
temp_config_file = tempfile.NamedTemporaryFile(
Expand Down Expand Up @@ -429,8 +429,8 @@ def _file2dict(filename: str,
warnings.warn(warning_msg, DeprecationWarning)

cfg_text = filename + '\n'
with open(filename, 'r', encoding='utf-8') as f:
# Setting encoding explicitly to resolve coding issue on windows.
with open(filename, encoding='utf-8') as f:
# Setting encoding explicitly to resolve coding issue on windows
cfg_text += f.read()

if BASE_KEY in cfg_dict:
Expand Down
2 changes: 1 addition & 1 deletion mmengine/config/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def get_config(cfg_name: str, pretrained: bool = False, suffix='.py', )\
>>> cfg = get_config('mmdet::faster_rcnn/faster_rcnn_r50_fpn_1x_coco',
>>> pretrained=True)
>>> # Equivalent to
>>> Config.fromfile(/path/tofaster_rcnn_r50_fpn_1x_coco.py)
>>> Config.fromfile('/path/tofaster_rcnn_r50_fpn_1x_coco.py')
>>> cfg.model_path
https://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth

Expand Down
210 changes: 210 additions & 0 deletions mmengine/config/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
# Copyright (c) OpenMMLab. All rights reserved.
import importlib
import os.path as osp
import re
from typing import Tuple

import torch.nn as nn

import mmengine.runner
from mmengine.fileio import load
from mmengine.utils import (check_file_exist, check_install_package,
get_installed_path)
from .config import Config

PKG2PROJECT = {
'mmcls': 'mmcls',
'mmdet': 'mmdet',
'mmdet3d': 'mmdet3d',
'mmseg': 'mmsegmentation',
'mmaction2': 'mmaction2',
'mmtrack': 'mmtrack',
'mmpose': 'mmpose',
'mmedit': 'mmedit',
'mmocr': 'mmocr',
'mmgen': 'mmgen',
'mmfewshot': 'mmfewshot',
'mmrazor': 'mmrazor',
'mmflow': 'mmflow',
'mmhuman3d': 'mmhuman3d',
'mmrotate': 'mmrotate',
'mmselfsup': 'mmselfsup',
}


def _get_cfg_meta(package_path: str, cfg_file: str) -> dict:
"""Get target meta information from 'metafile.yml' of external package.

Args:
package_path (str): Path of external package.
cfg_file (str): Name of experiment config.

Returns:
dict: Meta information of target experiment.
"""
meta_index_path = osp.join(package_path, '.mim', 'model-index.yml')
meta_index = load(meta_index_path)
cfg_dict = dict()
for meta_path in meta_index['Import']:
meta_path = osp.join(package_path, '.mim', meta_path)
cfg_meta = load(meta_path)
for model_cfg in cfg_meta['Models']:
cfg_name = model_cfg['Config'].split('/')[-1].strip('.py')
cfg_dict[cfg_name] = model_cfg
if cfg_file not in cfg_dict:
raise ValueError(f'Expected configs: {cfg_dict.keys()}, but got '
f'{cfg_file}')
return cfg_dict[cfg_file]


def _get_external_cfg_path(package_path: str, cfg_file: str) -> str:
"""Get relative config path from 'metafile.yml' of external package.

Args:
package_path (str): Path of external package.
cfg_file (str): Name of experiment config.

Returns:
str: Absolute config path from external package.
"""
cfg_file = cfg_file.split('.')[0]
model_cfg = _get_cfg_meta(package_path, cfg_file)
cfg_path = osp.join(package_path, model_cfg['Config'])
check_file_exist(cfg_path)
return cfg_path


def _get_external_cfg_base_path(package_path: str, cfg_name: str):
""" Get base config path from external package.
Args:
package_path (str): Path of external package.
cfg_name (str): External relative config path with 'package::'.

Returns:
str: Absolute config path from external package.
"""
cfg_path = osp.join(package_path, '.mim', 'configs', cfg_name)
check_file_exist(cfg_path)
return cfg_path


def _parse_external_cfg_path(cfg_name: str) -> Tuple[str, str]:
"""Get package name and relative config path.

Args:
cfg_name (str): External relative config path with 'package::'.

Returns:
Tuple(str, str): Package name and relative config path.
"""
if re.match(r'\w*::\w*/\w*', cfg_name) is None:
raise ValueError('`_parse_external_cfg_path` is used for parse '
'external package, please specify the package name '
'and relative config path, just like '
'`mmdet::faster_rcnn/faster_rcnn_r50_fpn_1x_coco` ')
package_cfg = cfg_name.split('::')
if len(package_cfg) > 2:
raise ValueError('`::` should only be used to separate package and '
'config name, but found multiple `::` in '
f'{cfg_name}')
package, cfg_name = package_cfg
assert package in PKG2PROJECT, 'mmengine does not support to load ' \
f'{package} config.'
package = PKG2PROJECT[package]
return package, cfg_name


def _parse_cfg_name(cfg_name: str) -> str:
"""Get the econfig name.

Args:
cfg_name (str): External relative config path.

Returns:
str: The config name.
"""
cfg_path_list = cfg_name.split('/')
cfg_name = cfg_path_list[-1]
return cfg_name


def get_config(cfg_name: str, pretrained: bool = False, suffix='.py', )\
-> Config:
"""Get config from external package.

Args:
cfg_name (str): External relative config path with prefix
'package::' and without suffix.
pretrained (bool): Whether to save pretrained model path. If
``pretrained==True``, the url of pretrained model can be accessed
by ``cfg.model_path``. Defaults to False.
suffix (str): Suffix of ``cfg_name``. If cfg_name is a base
cfg, the `suffix` will be used to get the absolute config path.
Defaults to '.py'.

Examples:
>>> cfg = get_config('mmdet::faster_rcnn/faster_rcnn_r50_fpn_1x_coco',
>>> pretrained=True)
>>> # Equivalent to
>>> Config.fromfile('/path/tofaster_rcnn_r50_fpn_1x_coco.py')
>>> cfg.model_path
https://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth

Returns:
Config: A `Config` parsed from external package.
""" # noqa E301
# Get package name and relative config path.
package, cfg_name = _parse_external_cfg_path(cfg_name)
# Check package is installed.
check_install_package(package)
package_path = get_installed_path(package)
try:
# Use `cfg_name` to search target config file.
rel_cfg_file = _parse_cfg_name(cfg_name)
cfg_meta = _get_cfg_meta(package_path, rel_cfg_file)
cfg_path = osp.join(package_path, '.mim', cfg_meta['Config'])
cfg = Config.fromfile(cfg_path)
cfg.model_path = cfg_meta['Weights']
if pretrained:
assert 'Weights' in cfg_meta, ('Cannot find `Weights` in cfg_file'
'.metafile.yml, please check the'
'metafile')
except ValueError:
# Since the base config does not contain a metafile, the absolute
# config is `osp.join(package_path, cfg_path_prefix, cfg_name)`
cfg_path = _get_external_cfg_base_path(package_path, cfg_name + suffix)
cfg = Config.fromfile(cfg_path)
return cfg


def get_model(cfg_name: str,
pretrained=False,
build_func_name: str = 'build_model',
suffix='.py',
**kwargs) -> nn.Module:
"""Get built model from external package.

Args:
cfg_name (str): External relative config path with prefix
'package::' and without suffix.
pretrained (bool): Whether to load pretrained model. Defaults to False.
build_func_name (str): Name of model build function. Defaults to
'build_model'
suffix (str): Suffix of ``cfg_name``. If cfg_name is a base
cfg, the `suffix` will be used to get the absolute config path.
Defaults to '.py'.

Returns:
nn.Module: Built model.
"""
cfg = get_config(cfg_name, pretrained, suffix)
package = cfg_name.split('::')[0]

models_module = importlib.import_module(f'{package}.models')
build_func = getattr(models_module, build_func_name, None)
if build_func is None:
raise RuntimeError(f'`{build_func_name}` is not defined in '
f'`{package}.models`')
model = build_func(cfg.model, **kwargs)
model = mmengine.runner.load_checkpoint(model, cfg.model_path)
return model
5 changes: 3 additions & 2 deletions mmengine/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
'to_1tuple', 'to_2tuple', 'to_3tuple', 'to_4tuple', 'to_ntuple',
'is_method_overridden', 'has_method', 'mmcv_full_available',
'digit_version', 'get_git_hash', 'TORCH_VERSION', 'load_url',
'is_installed', 'call_command', 'get_installed_path',
'check_install_package', 'find_latest_checkpoint'
'find_latest_checkpoint', 'ManagerMeta', 'ManagerMixin',
'set_multi_processing', 'has_batch_norm', 'is_abs', 'is_installed',
'call_command', 'get_installed_path', 'check_install_package'
]
You are viewing a condensed version of this merge commit. You can view the full changes here.