Unverified Commit f46f0cf4 authored by liuzhe-lz's avatar liuzhe-lz Committed by GitHub
Browse files

Split built-in and custom algorithm manifests to fix upgrading issue (#4403)

parent 428ade24
......@@ -31,6 +31,12 @@ def get_config_file(name: str) -> Path:
"""
config_file = get_config_directory() / name
if not config_file.exists():
default = Path(nni.__path__[0], 'runtime/default_config', name)
default = get_builtin_config_file(name)
shutil.copyfile(default, config_file)
return config_file
def get_builtin_config_file(name: str) -> Path:
"""
Get a readonly builtin config file.
"""
return Path(nni.__path__[0], 'runtime/default_config', name)
advisors:
- builtinName: Hyperband
classArgsValidator: nni.algorithms.hpo.hyperband_advisor.HyperbandClassArgsValidator
className: nni.algorithms.hpo.hyperband_advisor.Hyperband
source: nni
- builtinName: BOHB
classArgsValidator: nni.algorithms.hpo.bohb_advisor.BOHBClassArgsValidator
className: nni.algorithms.hpo.bohb_advisor.BOHB
source: nni
assessors:
- builtinName: Medianstop
classArgsValidator: nni.algorithms.hpo.medianstop_assessor.MedianstopClassArgsValidator
className: nni.algorithms.hpo.medianstop_assessor.MedianstopAssessor
source: nni
- builtinName: Curvefitting
classArgsValidator: nni.algorithms.hpo.curvefitting_assessor.CurvefittingClassArgsValidator
className: nni.algorithms.hpo.curvefitting_assessor.CurvefittingAssessor
source: nni
tuners:
- builtinName: PPOTuner
classArgsValidator: nni.algorithms.hpo.ppo_tuner.PPOClassArgsValidator
className: nni.algorithms.hpo.ppo_tuner.PPOTuner
source: nni
- builtinName: SMAC
classArgsValidator: nni.algorithms.hpo.smac_tuner.SMACClassArgsValidator
className: nni.algorithms.hpo.smac_tuner.SMACTuner
source: nni
- builtinName: TPE
className: nni.algorithms.hpo.tpe_tuner.TpeTuner
source: nni
- builtinName: TPE_legacy
classArgs:
algorithm_name: tpe
classArgsValidator: nni.algorithms.hpo.hyperopt_tuner.HyperoptClassArgsValidator
className: nni.algorithms.hpo.hyperopt_tuner.HyperoptTuner
source: nni
- builtinName: Random
className: nni.algorithms.hpo.random_tuner.RandomTuner
classArgsValidator: nni.algorithms.hpo.random_tuner.RandomClassArgsValidator
source: nni
- builtinName: Anneal
classArgs:
algorithm_name: anneal
classArgsValidator: nni.algorithms.hpo.hyperopt_tuner.HyperoptClassArgsValidator
className: nni.algorithms.hpo.hyperopt_tuner.HyperoptTuner
source: nni
- builtinName: Evolution
classArgsValidator: nni.algorithms.hpo.evolution_tuner.EvolutionClassArgsValidator
className: nni.algorithms.hpo.evolution_tuner.EvolutionTuner
source: nni
- acceptClassArgs: false
builtinName: BatchTuner
className: nni.algorithms.hpo.batch_tuner.BatchTuner
source: nni
- acceptClassArgs: false
builtinName: GridSearch
className: nni.algorithms.hpo.gridsearch_tuner.GridSearchTuner
source: nni
- builtinName: NetworkMorphism
classArgsValidator: nni.algorithms.hpo.networkmorphism_tuner.NetworkMorphismClassArgsValidator
className: nni.algorithms.hpo.networkmorphism_tuner.NetworkMorphismTuner
source: nni
- builtinName: MetisTuner
classArgsValidator: nni.algorithms.hpo.metis_tuner.MetisClassArgsValidator
className: nni.algorithms.hpo.metis_tuner.MetisTuner
source: nni
- builtinName: GPTuner
classArgsValidator: nni.algorithms.hpo.gp_tuner.GPClassArgsValidator
className: nni.algorithms.hpo.gp_tuner.GPTuner
source: nni
- builtinName: PBTTuner
classArgsValidator: nni.algorithms.hpo.pbt_tuner.PBTClassArgsValidator
className: nni.algorithms.hpo.pbt_tuner.PBTTuner
source: nni
- builtinName: RegularizedEvolutionTuner
classArgsValidator: nni.algorithms.hpo.regularized_evolution_tuner.EvolutionClassArgsValidator
className: nni.algorithms.hpo.regularized_evolution_tuner.RegularizedEvolutionTuner
source: nni
- builtinName: DNGOTuner
classArgsValidator: nni.algorithms.hpo.dngo_tuner.DNGOClassArgsValidator
className: nni.algorithms.hpo.dngo_tuner.DNGOTuner
source: nni
advisors:
- builtinName: Hyperband
classArgsValidator: nni.algorithms.hpo.hyperband_advisor.HyperbandClassArgsValidator
className: nni.algorithms.hpo.hyperband_advisor.Hyperband
source: nni
- builtinName: BOHB
classArgsValidator: nni.algorithms.hpo.bohb_advisor.BOHBClassArgsValidator
className: nni.algorithms.hpo.bohb_advisor.BOHB
source: nni
assessors:
- builtinName: Medianstop
classArgsValidator: nni.algorithms.hpo.medianstop_assessor.MedianstopClassArgsValidator
className: nni.algorithms.hpo.medianstop_assessor.MedianstopAssessor
source: nni
- builtinName: Curvefitting
classArgsValidator: nni.algorithms.hpo.curvefitting_assessor.CurvefittingClassArgsValidator
className: nni.algorithms.hpo.curvefitting_assessor.CurvefittingAssessor
source: nni
tuners:
- builtinName: PPOTuner
classArgsValidator: nni.algorithms.hpo.ppo_tuner.PPOClassArgsValidator
className: nni.algorithms.hpo.ppo_tuner.PPOTuner
source: nni
- builtinName: SMAC
classArgsValidator: nni.algorithms.hpo.smac_tuner.SMACClassArgsValidator
className: nni.algorithms.hpo.smac_tuner.SMACTuner
source: nni
- builtinName: TPE
className: nni.algorithms.hpo.tpe_tuner.TpeTuner
source: nni
- builtinName: TPE_legacy
classArgs:
algorithm_name: tpe
classArgsValidator: nni.algorithms.hpo.hyperopt_tuner.HyperoptClassArgsValidator
className: nni.algorithms.hpo.hyperopt_tuner.HyperoptTuner
source: nni
- builtinName: Random
className: nni.algorithms.hpo.random_tuner.RandomTuner
classArgsValidator: nni.algorithms.hpo.random_tuner.RandomClassArgsValidator
source: nni
- builtinName: Anneal
classArgs:
algorithm_name: anneal
classArgsValidator: nni.algorithms.hpo.hyperopt_tuner.HyperoptClassArgsValidator
className: nni.algorithms.hpo.hyperopt_tuner.HyperoptTuner
source: nni
- builtinName: Evolution
classArgsValidator: nni.algorithms.hpo.evolution_tuner.EvolutionClassArgsValidator
className: nni.algorithms.hpo.evolution_tuner.EvolutionTuner
source: nni
- acceptClassArgs: false
builtinName: BatchTuner
className: nni.algorithms.hpo.batch_tuner.BatchTuner
source: nni
- acceptClassArgs: false
builtinName: GridSearch
className: nni.algorithms.hpo.gridsearch_tuner.GridSearchTuner
source: nni
- builtinName: NetworkMorphism
classArgsValidator: nni.algorithms.hpo.networkmorphism_tuner.NetworkMorphismClassArgsValidator
className: nni.algorithms.hpo.networkmorphism_tuner.NetworkMorphismTuner
source: nni
- builtinName: MetisTuner
classArgsValidator: nni.algorithms.hpo.metis_tuner.MetisClassArgsValidator
className: nni.algorithms.hpo.metis_tuner.MetisTuner
source: nni
- builtinName: GPTuner
classArgsValidator: nni.algorithms.hpo.gp_tuner.GPClassArgsValidator
className: nni.algorithms.hpo.gp_tuner.GPTuner
source: nni
- builtinName: PBTTuner
classArgsValidator: nni.algorithms.hpo.pbt_tuner.PBTClassArgsValidator
className: nni.algorithms.hpo.pbt_tuner.PBTTuner
source: nni
- builtinName: RegularizedEvolutionTuner
classArgsValidator: nni.algorithms.hpo.regularized_evolution_tuner.EvolutionClassArgsValidator
className: nni.algorithms.hpo.regularized_evolution_tuner.RegularizedEvolutionTuner
source: nni
- builtinName: DNGOTuner
classArgsValidator: nni.algorithms.hpo.dngo_tuner.DNGOClassArgsValidator
className: nni.algorithms.hpo.dngo_tuner.DNGOTuner
source: nni
{}
......@@ -3,8 +3,8 @@
import importlib
import json
from nni.tools.package_utils import read_registerd_algo_meta, get_registered_algo_meta, \
write_registered_algo_meta, ALGO_TYPES, parse_full_class_name
import nni
from nni.tools import package_utils
from .common_utils import print_error, print_green, get_yml_content
def read_reg_meta_list(meta_path):
......@@ -18,89 +18,69 @@ def read_reg_meta_list(meta_path):
assert meta['algoType'] in ['tuner', 'assessor', 'advisor']
assert 'builtinName' in meta
assert 'className' in meta
return meta_list
meta['nniVersion'] = nni.__version__
return [package_utils.AlgoMeta.load(meta) for meta in meta_list]
def verify_algo_import(meta):
def _do_verify_import(fullName):
module_name, class_name = parse_full_class_name(fullName)
def _do_verify_import(full_name):
module_name, class_name = full_name.rsplit('.', 1)
class_module = importlib.import_module(module_name)
getattr(class_module, class_name)
_do_verify_import(meta['className'])
_do_verify_import(meta.class_name)
if meta.get('classArgsValidator'):
_do_verify_import(meta['classArgsValidator'])
if meta.validator_class_name is not None:
_do_verify_import(meta.validator_class_name)
def algo_reg(args):
meta_list = read_reg_meta_list(args.meta_path)
for meta in meta_list:
old = get_registered_algo_meta(meta['builtinName'])
if old is None:
verify_algo_import(meta)
save_algo_meta_data(meta)
elif old['source'] != 'nni':
old = package_utils.get_algo_meta(meta.name)
if old is not None and old.is_builtin:
print_error(f'Cannot overwrite builtin algorithm {meta.name}')
continue
verify_algo_import(meta)
if old is not None:
print_green(f'Updating exist algorithm')
remove_algo_meta_data(meta['builtinName'])
save_algo_meta_data(meta)
else:
print_error(f'Cannot overwrite builtin algorithm')
print_green('{} registered sucessfully!'.format(meta['builtinName']))
package_utils.register_algo_meta(meta)
print_green(f'{meta.name} registered sucessfully!')
def algo_unreg(args):
name = args.name[0]
meta = get_registered_algo_meta(name)
meta = package_utils.get_algo_meta(name)
if meta is None:
print_error('builtin algorithms {} not found!'.format(name))
return
if meta['source'] == 'nni':
if meta.is_builtin:
print_error('{} is provided by nni, can not be unregistered!'.format(name))
return
if remove_algo_meta_data(name):
package_utils.unregister_algo_meta(name)
print_green('{} unregistered sucessfully!'.format(name))
else:
print_error('Failed to unregistered {}!'.format(name))
def algo_show(args):
builtin_name = args.name[0]
meta = get_registered_algo_meta(builtin_name)
if meta:
print(json.dumps(meta, indent=4))
meta = package_utils.get_algo_meta(builtin_name)
if meta is not None:
print(json.dumps(meta.dump(), indent=4))
else:
print_error('package {} not found'.format(builtin_name))
def algo_list(args):
meta = read_registerd_algo_meta()
print('+-----------------+------------+-----------+--------=-------------+------------------------------------------+')
print('| Name | Type | source | Class Name | Module Name |')
print('+-----------------+------------+-----------+----------------------+------------------------------------------+')
MAX_MODULE_NAME = 38
for t in ['tuners', 'assessors', 'advisors']:
for p in meta[t]:
module_name = '.'.join(p['className'].split('.')[:-1])
for meta in package_utils.get_all_algo_meta():
module_name, class_name = meta.class_name.rsplit('.', 1)
if len(module_name) > MAX_MODULE_NAME:
module_name = module_name[:MAX_MODULE_NAME-3] + '...'
class_name = p['className'].split('.')[-1]
print('| {:15s} | {:10s} | {:9s} | {:20s} | {:40s} |'.format(p['builtinName'], t, p['source'], class_name, module_name[:38]))
fields = [
meta.name,
meta.algo_type,
'nni' if meta.is_builtin else 'user',
class_name,
module_name
]
print('| {:15s} | {:10s} | {:9s} | {:20s} | {:40s} |'.format(*fields))
print('+-----------------+------------+-----------+----------------------+------------------------------------------+')
def save_algo_meta_data(meta_data):
meta_data['source'] = 'user'
config = read_registerd_algo_meta()
config[meta_data['algoType']+'s'].append(meta_data)
write_registered_algo_meta(config)
def remove_algo_meta_data(name):
config = read_registerd_algo_meta()
updated = False
for t in ALGO_TYPES:
for meta in config[t]:
if meta['builtinName'] == name:
config[t].remove(meta)
updated = True
if updated:
write_registered_algo_meta(config)
return True
return False
......@@ -6,7 +6,7 @@ import logging
import os
from schema import And, Optional, Or, Regex, Schema, SchemaError
from nni.tools.package_utils import (
from nni.tools.package_utils.tuner_factory import (
create_validator_instance,
get_all_builtin_names,
get_registered_algo_meta,
......
......@@ -13,7 +13,7 @@ import re
from subprocess import Popen, check_call, CalledProcessError, PIPE, STDOUT
from nni.experiment.config import ExperimentConfig, convert
from nni.tools.annotation import expand_annotations, generate_search_space
from nni.tools.package_utils import get_builtin_module_class_name
from nni.tools.package_utils.tuner_factory import get_builtin_module_class_name
import nni_node # pylint: disable=import-error, wrong-import-order
from .launcher_utils import validate_all_content
from .rest_utils import rest_put, rest_post, check_rest_server, check_response
......
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
from collections import defaultdict
import importlib
import os
from pathlib import Path
import sys
import yaml
from nni.runtime.config import get_config_file
ALGO_TYPES = ['tuners', 'assessors', 'advisors']
def get_all_builtin_names(algo_type):
"""Get all builtin names of registered algorithms of specified type
Parameters
----------
algo_type: str
can be one of 'tuners', 'assessors' or 'advisors'
Returns: list of string
-------
All builtin names of specified type, for example, if algo_type is 'tuners', returns
all builtin tuner names.
"""
assert algo_type in ALGO_TYPES
return [x['builtinName'] for x in read_registerd_algo_meta()[algo_type]]
def get_registered_algo_meta(builtin_name, algo_type=None):
""" Get meta information of registered algorithms.
Parameters
----------
builtin_name: str
builtin name.
algo_type: str | None
can be one of 'tuners', 'assessors', 'advisors' or None
Returns: dict | None
-------
Returns meta information of speicified builtin alogorithms, for example:
{
'classArgsValidator': 'nni.smac_tuner.SMACClassArgsValidator',
'className': 'nni.smac_tuner.SMACTuner',
'builtinName': 'SMAC'
}
"""
assert builtin_name is not None
if algo_type:
assert algo_type in ALGO_TYPES
config = read_registerd_algo_meta()
candidates = []
if algo_type:
candidates = config[algo_type]
else:
for algo_type in ALGO_TYPES:
candidates.extend(config[algo_type])
for meta in candidates:
if meta['builtinName'] == builtin_name:
return meta
return None
def parse_full_class_name(full_class_name):
if not full_class_name:
return None, None
parts = full_class_name.split('.')
module_name, class_name = '.'.join(parts[:-1]), parts[-1]
return module_name, class_name
def get_builtin_module_class_name(algo_type, builtin_name):
"""Get module name and class name of all builtin algorithms
Parameters
----------
algo_type: str
can be one of 'tuners', 'assessors', 'advisors'
builtin_name: str
builtin name.
Returns: tuple
-------
tuple of (module name, class name)
"""
assert algo_type in ALGO_TYPES
assert builtin_name is not None
meta = get_registered_algo_meta(builtin_name, algo_type)
if not meta:
return None, None
return parse_full_class_name(meta['className'])
def create_validator_instance(algo_type, builtin_name):
"""Create instance of validator class
Parameters
----------
algo_type: str
can be one of 'tuners', 'assessors', 'advisors'
builtin_name: str
builtin name.
Returns: object | None
-------
Returns validator class instance.
If specified validator class does not exist, returns None.
"""
assert algo_type in ALGO_TYPES
assert builtin_name is not None
meta = get_registered_algo_meta(builtin_name, algo_type)
if not meta or 'classArgsValidator' not in meta:
return None
module_name, class_name = parse_full_class_name(meta['classArgsValidator'])
class_module = importlib.import_module(module_name)
class_constructor = getattr(class_module, class_name)
return class_constructor()
def create_builtin_class_instance(builtin_name, input_class_args, algo_type):
"""Create instance of builtin algorithms
Parameters
----------
builtin_name: str
builtin name.
input_class_args: dict
kwargs for builtin class constructor
algo_type: str
can be one of 'tuners', 'assessors', 'advisors'
Returns: object
-------
Returns builtin class instance.
"""
assert algo_type in ALGO_TYPES
if builtin_name not in get_all_builtin_names(algo_type):
raise RuntimeError('Builtin name is not found: {}'.format(builtin_name))
def parse_algo_meta(algo_meta, input_class_args):
"""
1. parse class_name field in meta data into module name and class name,
for example:
parse class_name 'nni.hyperopt_tuner.hyperopt_tuner.HyperoptTuner' in meta data into:
module name: nni.hyperopt_tuner.hyperopt_tuner
class name: HyperoptTuner
2. merge user specified class args together with builtin class args.
"""
assert algo_meta
module_name, class_name = parse_full_class_name(algo_meta['className'])
class_args = {}
if 'classArgs' in algo_meta:
class_args = algo_meta['classArgs']
if input_class_args is not None:
class_args.update(input_class_args)
return module_name, class_name, class_args
algo_meta = get_registered_algo_meta(builtin_name, algo_type)
module_name, class_name, class_args = parse_algo_meta(algo_meta, input_class_args)
if importlib.util.find_spec(module_name) is None:
raise RuntimeError('Builtin module can not be loaded: {}'.format(module_name))
class_module = importlib.import_module(module_name)
class_constructor = getattr(class_module, class_name)
instance = class_constructor(**class_args)
return instance
def create_customized_class_instance(class_params):
"""Create instance of customized algorithms
Parameters
----------
class_params: dict
class_params should contains following keys:
codeDirectory: code directory
className: qualified class name
classArgs (optional): kwargs pass to class constructor
Returns: object
-------
Returns customized class instance.
"""
code_dir = class_params.get('codeDirectory')
qualified_class_name = class_params.get('className')
class_args = class_params.get('classArgs')
if code_dir and not os.path.isdir(code_dir):
raise ValueError(f'Directory not found: {code_dir}')
sys.path.append(code_dir)
module_name, class_name = qualified_class_name.rsplit('.', 1)
class_module = importlib.import_module(module_name)
class_constructor = getattr(class_module, class_name)
if class_args is None:
class_args = {}
instance = class_constructor(**class_args)
return instance
def _using_conda_or_virtual_environment():
return sys.prefix != sys.base_prefix or os.path.isdir(os.path.join(sys.prefix, 'conda-meta'))
def get_registered_algo_config_path():
return str(get_config_file('registered_algorithms.yml'))
def read_registerd_algo_meta():
config_file = get_registered_algo_config_path()
if os.path.exists(config_file):
with open(config_file, 'r') as f:
config = yaml.safe_load(f)
else:
config = defaultdict(list)
for t in ALGO_TYPES:
if t not in config:
config[t] = []
return config
def write_registered_algo_meta(config):
config_file = get_registered_algo_config_path()
with open(config_file, 'w') as f:
f.write(yaml.safe_dump(dict(config), default_flow_style=False))
from .common import *
from .config_manager import *
from .tuner_factory import *
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
__all__ = ['AlgoMeta']
from typing import Dict, NamedTuple, Optional
class AlgoMeta(NamedTuple):
name: str
class_name: Optional[str]
accept_class_args: bool
class_args: Optional[dict]
validator_class_name: Optional[str]
algo_type: str # 'tuner' | 'assessor' | 'advisor'
is_builtin: bool
nni_version: Optional[str]
@staticmethod
def load(meta: Dict, algo_type: Optional[str] = None) -> 'AlgoMeta':
if algo_type is None:
algo_type = meta['algoType']
return AlgoMeta(
name=meta['builtinName'],
class_name=meta['className'],
accept_class_args=meta.get('acceptClassArgs', True),
class_args=meta.get('classArgs'),
validator_class_name=meta.get('classArgsValidator'),
algo_type=algo_type,
is_builtin=(meta.get('source') == 'nni'),
nni_version=meta.get('nniVersion')
)
def dump(self) -> Dict:
ret = {}
ret['builtinName'] = self.name
ret['className'] = self.class_name
if not self.accept_class_args:
ret['acceptClassArgs'] = False
if self.class_args is not None:
ret['classArgs'] = self.class_args
if self.validator_class_name is not None:
ret['classArgsValidator'] = self.validator_class_name
ret['source'] = 'nni' if self.is_builtin else 'user'
if self.nni_version is not None:
ret['nniVersion'] = self.nni_version
return ret
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
__all__ = [
'get_algo_meta',
'get_all_algo_meta',
'register_algo_meta',
'unregister_algo_meta',
]
from collections import defaultdict
from typing import List, Optional
import yaml
from nni.runtime.config import get_builtin_config_file, get_config_file
from .common import AlgoMeta
def get_algo_meta(name: AlgoMeta) -> Optional[AlgoMeta]:
"""
Get meta information of a built-in or registered algorithm.
Return None if not found.
"""
for algo in get_all_algo_meta():
if algo.name == name:
return algo
return None
def get_all_algo_meta() -> List[AlgoMeta]:
"""
Get meta information of all built-in and registered algorithms.
"""
return _load_builtin_config() + _load_custom_config()
def register_algo_meta(algo_meta: AlgoMeta) -> None:
"""
Register a custom algorithm.
If it already exists, overwrite it.
"""
algos = {algo.name: algo for algo in _load_custom_config()}
algos[algo_meta.name] = algo_meta
_save_custom_config(algos.values())
def unregister_algo_meta(algo_name: str) -> None:
"""
Unregister a custom algorithm.
If it does not exist, do nothing.
"""
algos = [algo for algo in _load_custom_config() if algo.name != algo_name]
_save_custom_config(algos)
def _load_builtin_config():
path = get_builtin_config_file('builtin_algorithms.yml')
return _load_config_file(path)
def _load_custom_config():
path = get_config_file('registered_algorithms.yml')
# for backward compatibility, NNI v2.5- stores all algorithms in this file
return [algo for algo in _load_config_file(path) if not algo.is_builtin]
def _load_config_file(path):
with open(path) as f:
config = yaml.safe_load(f)
algos = []
for algo_type in ['tuner', 'assessor', 'advisor']:
for algo in config.get(algo_type + 's', []):
algos.append(AlgoMeta.load(algo, algo_type))
return algos
def _save_custom_config(custom_algos):
config = defaultdict(list)
for algo in custom_algos:
config[algo.algo_type + 's'].append(algo.dump())
text = yaml.dump(dict(config), default_flow_style=False)
get_config_file('registered_algorithms.yml').write_text(text)
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
__all__ = [
'create_builtin_class_instance',
'create_customized_class_instance',
]
import importlib
import os
import sys
from . import config_manager
ALGO_TYPES = ['tuners', 'assessors', 'advisors']
def get_all_builtin_names(algo_type):
"""Get all builtin names of registered algorithms of specified type
Parameters
----------
algo_type: str
can be one of 'tuners', 'assessors' or 'advisors'
Returns: list of string
-------
All builtin names of specified type, for example, if algo_type is 'tuners', returns
all builtin tuner names.
"""
algos = config_manager.get_all_algo_meta()
return [meta.name for meta in algos if meta.algo_type == algo_type.rstrip('s')]
def get_registered_algo_meta(builtin_name, algo_type=None):
""" Get meta information of registered algorithms.
Parameters
----------
builtin_name: str
builtin name.
algo_type: str | None
can be one of 'tuners', 'assessors', 'advisors' or None
Returns: dict | None
-------
Returns meta information of speicified builtin alogorithms, for example:
{
'classArgsValidator': 'nni.smac_tuner.SMACClassArgsValidator',
'className': 'nni.smac_tuner.SMACTuner',
'builtinName': 'SMAC'
}
"""
algo = config_manager.get_algo_meta(builtin_name)
if algo is None:
return None
if algo_type is not None and algo.algo_type != algo_type.rstrip('s'):
return None
return algo.dump()
def parse_full_class_name(full_class_name):
if not full_class_name:
return None, None
parts = full_class_name.split('.')
module_name, class_name = '.'.join(parts[:-1]), parts[-1]
return module_name, class_name
def get_builtin_module_class_name(algo_type, builtin_name):
"""Get module name and class name of all builtin algorithms
Parameters
----------
algo_type: str
can be one of 'tuners', 'assessors', 'advisors'
builtin_name: str
builtin name.
Returns: tuple
-------
tuple of (module name, class name)
"""
assert algo_type in ALGO_TYPES
assert builtin_name is not None
meta = get_registered_algo_meta(builtin_name, algo_type)
if not meta:
return None, None
return parse_full_class_name(meta['className'])
def create_validator_instance(algo_type, builtin_name):
"""Create instance of validator class
Parameters
----------
algo_type: str
can be one of 'tuners', 'assessors', 'advisors'
builtin_name: str
builtin name.
Returns: object | None
-------
Returns validator class instance.
If specified validator class does not exist, returns None.
"""
assert algo_type in ALGO_TYPES
assert builtin_name is not None
meta = get_registered_algo_meta(builtin_name, algo_type)
if not meta or 'classArgsValidator' not in meta:
return None
module_name, class_name = parse_full_class_name(meta['classArgsValidator'])
class_module = importlib.import_module(module_name)
class_constructor = getattr(class_module, class_name)
return class_constructor()
def create_builtin_class_instance(builtin_name, input_class_args, algo_type):
"""Create instance of builtin algorithms
Parameters
----------
builtin_name: str
builtin name.
input_class_args: dict
kwargs for builtin class constructor
algo_type: str
can be one of 'tuners', 'assessors', 'advisors'
Returns: object
-------
Returns builtin class instance.
"""
assert algo_type in ALGO_TYPES
if builtin_name not in get_all_builtin_names(algo_type):
raise RuntimeError('Builtin name is not found: {}'.format(builtin_name))
def parse_algo_meta(algo_meta, input_class_args):
"""
1. parse class_name field in meta data into module name and class name,
for example:
parse class_name 'nni.hyperopt_tuner.hyperopt_tuner.HyperoptTuner' in meta data into:
module name: nni.hyperopt_tuner.hyperopt_tuner
class name: HyperoptTuner
2. merge user specified class args together with builtin class args.
"""
assert algo_meta
module_name, class_name = parse_full_class_name(algo_meta['className'])
class_args = {}
if 'classArgs' in algo_meta:
class_args = algo_meta['classArgs']
if input_class_args is not None:
class_args.update(input_class_args)
return module_name, class_name, class_args
algo_meta = get_registered_algo_meta(builtin_name, algo_type)
module_name, class_name, class_args = parse_algo_meta(algo_meta, input_class_args)
if importlib.util.find_spec(module_name) is None:
raise RuntimeError('Builtin module can not be loaded: {}'.format(module_name))
class_module = importlib.import_module(module_name)
class_constructor = getattr(class_module, class_name)
instance = class_constructor(**class_args)
return instance
def create_customized_class_instance(class_params):
"""Create instance of customized algorithms
Parameters
----------
class_params: dict
class_params should contains following keys:
codeDirectory: code directory
className: qualified class name
classArgs (optional): kwargs pass to class constructor
Returns: object
-------
Returns customized class instance.
"""
code_dir = class_params.get('codeDirectory')
qualified_class_name = class_params.get('className')
class_args = class_params.get('classArgs')
if code_dir and not os.path.isdir(code_dir):
raise ValueError(f'Directory not found: {code_dir}')
sys.path.append(code_dir)
module_name, class_name = qualified_class_name.rsplit('.', 1)
class_module = importlib.import_module(module_name)
class_constructor = getattr(class_module, class_name)
if class_args is None:
class_args = {}
instance = class_constructor(**class_args)
return instance
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