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
temp save
  • Loading branch information
HAOCHENYE committed Jun 20, 2022
commit 69e41a056194a5a72e0e10748da1830e6503dc03
38 changes: 12 additions & 26 deletions mmengine/config/collect_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@
}


def _get_cfg_meta(package_path: str, cfg_file: str) -> dict:
def _get_cfg_meta(package_path: str, cfg_path: 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.
cfg_path (str): Name of experiment config.

Returns:
dict: Meta information of target experiment.
Expand All @@ -45,10 +45,10 @@ def _get_cfg_meta(package_path: str, cfg_file: str) -> dict:
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:
if cfg_path not in cfg_dict:
raise ValueError(f'Expected configs: {cfg_dict.keys()}, but got '
f'{cfg_file}')
return cfg_dict[cfg_file]
f'{cfg_path}')
return cfg_dict[cfg_path]


def _get_external_cfg_path(package_path: str, cfg_file: str):
Expand Down Expand Up @@ -82,41 +82,27 @@ def _get_external_cfg_base_path(package_path: str, cfg_name: str):
return cfg_path


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

Args:
cfg_name (str): External relative config path with 'package::'.
cfg_path (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:
if re.match(r'\w*::\w*/\w*', cfg_path) 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('::')
package_cfg = cfg_path.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
f'{cfg_path}')
package, cfg_path = 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
return package, cfg_path
29 changes: 20 additions & 9 deletions mmengine/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from mmengine.utils import (check_file_exist, check_install_package,
get_installed_path, import_modules_from_strings)
from .collect_meta import (_get_external_cfg_base_path, _get_external_cfg_path,
_parse_cfg_name, _parse_external_cfg_path)
_get_package_and_cfg_path)

BASE_KEY = '_base_'
DELETE_KEY = '_delete_'
Expand Down Expand Up @@ -442,8 +442,11 @@ def _file2dict(filename: str,
cfg_dict_list = list()
cfg_text_list = list()
for base_file in base_filename:
cfg_path = Config._get_cfg_path(base_file, filename)
cfg_path, scope = Config._get_cfg_path(base_file, filename)
_cfg_dict, _cfg_text = Config._file2dict(cfg_path)
# Add _scope_ to dict config with type.
if scope is not None:
Config._parse_scope(_cfg_dict, scope)
cfg_dict_list.append(_cfg_dict)
cfg_text_list.append(_cfg_text)

Expand All @@ -469,27 +472,35 @@ def _file2dict(filename: str,
return cfg_dict, cfg_text

@staticmethod
def _get_cfg_path(cfg_path: str, filename: str) -> str:
def _parse_scope(cfg_dict, scope):
for value in cfg_dict.values():
if isinstance(value, dict) and 'type' in value:
value['_scope_'] = scope
Config._parse_scope(value, scope)

@staticmethod
def _get_cfg_path(cfg_path: str,
filename: str) -> Tuple[str, Optional[str]]:
"""Get the config path from the current or external package.

Args:
cfg_name (str): Relative path of config.
cfg_path (str): Relative path of config.
filename (str): The config file being parsed.

Returns:
str: The absolute path of `cfg_name`.
Tuple[str, Optional[str]]: The absolute path of `cfg_path` and
scope if
"""
if '::' in cfg_path:
# `cfg_path` startswith '::' means an external config path.
# Get package name and relative config path.
package, cfg_path = _parse_external_cfg_path(cfg_path)
package, cfg_path = _get_package_and_cfg_path(cfg_path)
# Get installed package path.
check_install_package(package)
package_path = get_installed_path(package)
try:
# Get config path from meta file.
cfg_name = _parse_cfg_name(cfg_path)
cfg_path = _get_external_cfg_path(package_path, cfg_name)
cfg_path = _get_external_cfg_path(package_path, cfg_path)
except ValueError:
# Since base config does not have a metafile, it should be
# concatenated with package path and relative config path.
Expand All @@ -498,7 +509,7 @@ def _get_cfg_path(cfg_path: str, filename: str) -> str:
# Get local config path.
cfg_dir = osp.dirname(filename)
cfg_path = osp.join(cfg_dir, cfg_path)
return cfg_path
return cfg_path, None

@staticmethod
def _merge_a_into_b(a: dict,
Expand Down
38 changes: 16 additions & 22 deletions mmengine/config/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@
import torch.nn as nn

import mmengine.runner
from mmengine.registry import MODELS
from mmengine.utils import check_install_package, get_installed_path
from .collect_meta import (_get_cfg_meta, _get_external_cfg_base_path,
_parse_cfg_name, _parse_external_cfg_path)
_get_package_and_cfg_path)
from .config import Config


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

Args:
cfg_name (str): External relative config path with prefix
cfg_path (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
Expand All @@ -35,16 +36,15 @@ def get_config(cfg_name: str, pretrained: bool = False, suffix='.py', )\

Returns:
Config: A `Config` parsed from external package.
""" # noqa E301
""" # noqa E301
# Get package name and relative config path.
package, cfg_name = _parse_external_cfg_path(cfg_name)
package, cfg_path = _get_package_and_cfg_path(cfg_path)
# 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)
# Use `cfg_path` to search target config file.
cfg_meta = _get_cfg_meta(package_path, cfg_path)
cfg_path = osp.join(package_path, '.mim', cfg_meta['Config'])
cfg = Config.fromfile(cfg_path)
cfg.model_path = cfg_meta['Weights']
Expand All @@ -55,39 +55,33 @@ def get_config(cfg_name: str, pretrained: bool = False, suffix='.py', )\
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_path = _get_external_cfg_base_path(package_path, cfg_path + suffix)
cfg = Config.fromfile(cfg_path)
return cfg


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

Args:
cfg_name (str): External relative config path with prefix
cfg_path (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]
cfg = get_config(cfg_path, pretrained, suffix)
package = cfg_path.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)
models_module.register_all_modules()
model = MODELS.build(cfg, default_args=kwargs)
model = mmengine.runner.load_checkpoint(model, cfg.model_path)
return model
Loading