def _validate_v2(config, path): base_path = Path(path).parent try: conf = ExperimentConfig(_base_path=base_path, **config) return conf.json() except Exception as e: print_error(f'Config V2 validation failed: {repr(e)}')
def create_experiment(args): '''start a new experiment''' experiment_id = ''.join(random.sample(string.ascii_letters + string.digits, 8)) config_path = os.path.abspath(args.config) if not os.path.exists(config_path): print_error('Please set correct config path!') exit(1) config_yml = get_yml_content(config_path) try: config = ExperimentConfig(_base_path=Path(config_path).parent, **config_yml) config_v2 = config.json() except Exception as error_v2: print_warning('Validation with V2 schema failed. Trying to convert from V1 format...') try: validate_all_content(config_yml, config_path) except Exception as error_v1: print_error(f'Convert from v1 format failed: {repr(error_v1)}') print_error(f'Config in v2 format validation failed: {repr(error_v2)}') exit(1) from nni.experiment.config import convert config_v2 = convert.to_v2(config_yml).json() try: if getattr(config_v2['trainingService'], 'platform', None) in k8s_training_services: launch_experiment(args, config_yml, 'new', experiment_id, 1) else: launch_experiment(args, config_v2, 'new', experiment_id, 2) except Exception as exception: restServerPid = Experiments().get_all_experiments().get(experiment_id, {}).get('pid') if restServerPid: kill_command(restServerPid) print_error(exception) exit(1)
def test_all(): minimal = ExperimentConfig(**minimal_json) assert minimal.json() == minimal_canon assert minimal_class.json() == minimal_canon_2 detailed = ExperimentConfig.load(expand_path('assets/config.yaml')) assert detailed.json() == detailed_canon
def create_experiment(args): '''start a new experiment''' experiment_id = ''.join(random.sample(string.ascii_letters + string.digits, 8)) config_path = os.path.abspath(args.config) if not os.path.exists(config_path): print_error('Please set correct config path!') exit(1) experiment_config = get_yml_content(config_path) try: validate_all_content(experiment_config, config_path) except Exception: print_warning('Validation with V1 schema failed. Trying to convert from V2 format...') try: config = ExperimentConfig(**experiment_config) experiment_config = convert.to_v1_yaml(config) except Exception as e: print_error(f'Conversion from v2 format failed: {repr(e)}') try: validate_all_content(experiment_config, config_path) except Exception as e: print_error(f'Config in v1 format validation failed. {repr(e)}') exit(1) try: launch_experiment(args, experiment_config, 'new', experiment_id) except Exception as exception: restServerPid = Experiments().get_all_experiments().get(experiment_id, {}).get('pid') if restServerPid: kill_command(restServerPid) print_error(exception) exit(1)
def create_experiment(args): '''start a new experiment''' experiment_id = ''.join( random.sample(string.ascii_letters + string.digits, 8)) nni_config = Config(experiment_id) nni_config.set_config('experimentId', experiment_id) config_path = os.path.abspath(args.config) if not os.path.exists(config_path): print_error('Please set correct config path!') exit(1) experiment_config = get_yml_content(config_path) try: config = ExperimentConfig(**experiment_config) experiment_config = convert.to_v1_yaml(config) except Exception: pass try: validate_all_content(experiment_config, config_path) except Exception as e: print_error(e) exit(1) nni_config.set_config('experimentConfig', experiment_config) nni_config.set_config('restServerPort', args.port) try: launch_experiment(args, experiment_config, 'new', experiment_id) except Exception as exception: nni_config = Config(experiment_id) restServerPid = nni_config.get_config('restServerPid') if restServerPid: kill_command(restServerPid) print_error(exception) exit(1)
def test_remote(): config = ExperimentConfig(**minimal_json) assert config.json() == minimal_canon assert minimal_class.json() == minimal_canon config = ExperimentConfig(**detailed_json) assert config.json() == detailed_canon
def create_experiment(args): # to make it clear what are inside args config_file = Path(args.config) port = args.port debug = args.debug url_prefix = args.url_prefix foreground = args.foreground # it should finally be done in nnictl main function # but for now don't break routines without logging support init_logger_for_command_line() logging.getLogger('nni').setLevel(logging.INFO) if not config_file.is_file(): _logger.error(f'"{config_file}" is not a valid file.') exit(1) with config_file.open() as config: config_content = yaml.safe_load(config) v1_platform = config_content.get('trainingServicePlatform') if v1_platform: can_convert = True if v1_platform == 'adl': can_convert = False if v1_platform in ['kubeflow', 'frameworkcontroller']: reuse = config_content.get(v1_platform + 'Config', {}).get('reuse') can_convert = ( reuse != False ) # if user does not explicitly specify it, convert to reuse mode if not can_convert: legacy_launcher.create_experiment(args) exit() try: v2_config = convert.to_v2(config_content) except Exception: _logger.error( 'You are using legacy config format with incorrect fields or values, ' 'to get more accurate error message please update it to the new format.' ) _logger.error( 'Reference: https://nni.readthedocs.io/en/stable/reference/experiment_config.html' ) exit(1) _logger.warning( f'You are using legacy config file, please update it to latest format:' ) # use `print` here because logging will add timestamp and make it hard to copy paste print(Fore.YELLOW + '=' * 80 + Fore.RESET) print(yaml.dump(v2_config, sort_keys=False).strip()) print(Fore.YELLOW + '=' * 80 + Fore.RESET) print( Fore.YELLOW + 'Reference: https://nni.readthedocs.io/en/stable/reference/experiment_config.html' + Fore.RESET) utils.set_base_path(config_file.parent) config = ExperimentConfig(**v2_config) utils.unset_base_path() else: config = ExperimentConfig.load(config_file) if config.use_annotation: path = Path(tempfile.gettempdir(), getuser(), 'nni', 'annotation') path.mkdir(parents=True, exist_ok=True) path = tempfile.mkdtemp(dir=path) code_dir = expand_annotations(config.trial_code_directory, path) config.trial_code_directory = code_dir config.search_space = generate_search_space(code_dir) assert config.search_space, 'ERROR: Generated search space is empty' config.use_annotation = False exp = Experiment(config) exp.url_prefix = url_prefix run_mode = RunMode.Foreground if foreground else RunMode.Detach exp.start(port, debug, run_mode) _logger.info( f'To stop experiment run "nnictl stop {exp.id}" or "nnictl stop --all"' ) _logger.info( 'Reference: https://nni.readthedocs.io/en/stable/Tutorial/Nnictl.html')
import json from pathlib import Path import yaml from nni.experiment.config import ExperimentConfig, AlgorithmConfig, LocalConfig ## template ## config = ExperimentConfig(search_space_file='', trial_command='echo hello', trial_concurrency=1, tuner=AlgorithmConfig(name='randomm'), training_service=LocalConfig()) space_correct = { 'pool_type': { '_type': 'choice', '_value': ['max', 'min', 'avg'] }, '学习率': { '_type': 'loguniform', '_value': [1e-7, 0.1] } } # FIXME # PyYAML 6.0 (YAML 1.1) does not support tab and scientific notation # JSON does not support comment and extra comma # So some combinations will fail to load formats = [
## minimal config ## minimal_json = { 'searchSpace': {'a': 1}, 'trialCommand': 'python main.py', 'trialConcurrency': 2, 'tuner': { 'name': 'random', }, 'trainingService': { 'platform': 'local', }, } minimal_class = ExperimentConfig('local') minimal_class.search_space = {'a': 1} minimal_class.trial_command = 'python main.py' minimal_class.trial_concurrency = 2 minimal_class.tuner.name = 'random' minimal_canon = { 'searchSpace': {'a': 1}, 'trialCommand': 'python main.py', 'trialCodeDirectory': os.path.realpath('.'), 'trialConcurrency': 2, 'useAnnotation': False, 'debug': False, 'logLevel': 'info', 'experimentWorkingDirectory': str(Path.home() / 'nni-experiments'), 'tuner': {'name': 'random'},
'user': '******', 'password': '******', }, ], }, } minimal_class = ExperimentConfig( search_space = {'a': 1}, trial_command = 'python main.py', trial_concurrency = 2, tuner = AlgorithmConfig( name = 'random', ), training_service = RemoteConfig( machine_list = [ RemoteMachineConfig( host = '1.2.3.4', user = '******', password = '******', ), ], ), ) minimal_canon = { 'searchSpace': {'a': 1}, 'trialCommand': 'python main.py', 'trialCodeDirectory': os.path.realpath('.'), 'trialConcurrency': 2, 'useAnnotation': False,