import argparse import os import yaml try: from lightning.pytorch.utilities.rank_zero import rank_zero_only except ModuleNotFoundError: def rank_zero_only(f): return f from utils.multiprocess_utils import is_main_process as mp_is_main_process global_print_hparams = True hparams = {} class Args: def __init__(self, **kwargs): for k, v in kwargs.items(): self.__setattr__(k, v) def override_config(old_config: dict, new_config: dict): for k, v in new_config.items(): if isinstance(v, dict) and k in old_config: override_config(old_config[k], new_config[k]) else: old_config[k] = v def set_hparams(config='', exp_name='', hparams_str='', print_hparams=True, global_hparams=True): """ Load hparams from multiple sources: 1. config chain (i.e. first load base_config, then load config); 2. if reset == True, load from the (auto-saved) complete config file ('config.yaml') which contains all settings and do not rely on base_config; 3. load from argument --hparams or hparams_str, as temporary modification. """ if config == '': parser = argparse.ArgumentParser(description='neural music') parser.add_argument('--config', type=str, default='', help='location of the data corpus') parser.add_argument('--exp_name', type=str, default='', help='exp_name') parser.add_argument('--hparams', type=str, default='', help='location of the data corpus') parser.add_argument('--infer', action='store_true', help='infer') parser.add_argument('--reset', action='store_true', help='reset hparams') args, unknown = parser.parse_known_args() tmp_args_hparams = args.hparams.split(',') if args.hparams.strip() != '' else [] tmp_args_hparams.extend(hparams_str.split(',') if hparams_str.strip() != '' else []) args.hparams = ','.join(tmp_args_hparams) else: args = Args(config=config, exp_name=exp_name, hparams=hparams_str, infer=False, reset=False) args_work_dir = '' if args.exp_name != '': args.work_dir = args.exp_name args_work_dir = os.path.join('checkpoints', args.work_dir) config_chains = [] loaded_config = set() def load_config(config_fn): # deep first with open(config_fn, encoding='utf-8') as f: hparams_ = yaml.safe_load(f) loaded_config.add(config_fn) if 'base_config' in hparams_: ret_hparams = {} if not isinstance(hparams_['base_config'], list): hparams_['base_config'] = [hparams_['base_config']] for c in hparams_['base_config']: if c not in loaded_config: if c.startswith('.'): c = f'{os.path.dirname(config_fn)}/{c}' c = os.path.normpath(c) override_config(ret_hparams, load_config(c)) override_config(ret_hparams, hparams_) else: ret_hparams = hparams_ config_chains.append(config_fn) return ret_hparams global hparams assert args.config != '' or args_work_dir != '', 'Either config or exp name should be specified.' saved_hparams = {} ckpt_config_path = os.path.join(args_work_dir, 'config.yaml') if args_work_dir != '' and os.path.exists(ckpt_config_path): with open(ckpt_config_path, encoding='utf-8') as f: saved_hparams.update(yaml.safe_load(f)) hparams_ = {} if args.config != '': hparams_.update(load_config(args.config)) if not args.reset: hparams_.update(saved_hparams) hparams_['work_dir'] = args_work_dir if args.hparams != "": for new_hparam in args.hparams.split(","): if new_hparam.strip() == "": continue k, v = new_hparam.split("=") if k not in hparams_: hparams_[k] = eval(v) if v in ['True', 'False'] or type(hparams_[k]) == bool: hparams_[k] = eval(v) else: hparams_[k] = type(hparams_[k])(v) @rank_zero_only def dump_hparams(): if args_work_dir != '' and (not os.path.exists(ckpt_config_path) or args.reset) and not args.infer: os.makedirs(hparams_['work_dir'], exist_ok=True) if mp_is_main_process: # Only the main process will save the config file with open(ckpt_config_path, 'w', encoding='utf-8') as f: hparams_non_recursive = hparams_.copy() hparams_non_recursive['base_config'] = [] yaml.safe_dump(hparams_non_recursive, f, allow_unicode=True, encoding='utf-8') dump_hparams() hparams_['infer'] = args.infer if global_hparams: hparams.clear() hparams.update(hparams_) if hparams.get('exp_name') is None: hparams['exp_name'] = args.exp_name if hparams_.get('exp_name') is None: hparams_['exp_name'] = args.exp_name @rank_zero_only def print_out_hparams(): global global_print_hparams if mp_is_main_process and print_hparams and global_print_hparams and global_hparams: print('| Hparams chains: ', config_chains) print('| Hparams: ') for i, (k, v) in enumerate(sorted(hparams_.items())): print(f"\033[0;33m{k}\033[0m: {v}, ", end="\n" if i % 5 == 4 else "") print("") global_print_hparams = False print_out_hparams() return hparams_