class TrainingRuns(Mapping): """A map from integers to TrainingRuns.""" def __init__(self, root_dir, src_dir, run_factory, check_commit=True): """Create TrainingRuns object. Args: root_dir (str): directory where all training run data will be stored src_dir (str): a Git repository path (used to check commits) run_factory (Callable[[Config, str], TrainingRun]): a Callable, which takes a Config and a save_dir as arguments, and creates a new TrainingRun. check_commit (bool): if True, checks that current working directory is on same commit as when the run was originally created. """ self._int_dirs = IntegerDirectories(root_dir) self._src_dir = src_dir self._run_factory = run_factory self._check_commit = check_commit def _config_path(self, save_dir): return join(save_dir, 'config.txt') def __getitem__(self, i): """Reload an existing TrainingRun.""" save_dir = self._int_dirs[i] config = Config.from_file(self._config_path(save_dir)) run = self._run_factory(config, save_dir) if self._check_commit: run.match_commit(self._src_dir) logging.info('Reloaded TrainingRun #{}'.format(i)) return run def new(self, config, name=None): """Create a new TrainingRun.""" print('TrainingRun configuration:\n{}'.format(config)) save_dir = self._int_dirs.new_dir(name=name) cfg_path = self._config_path(save_dir) config.to_file(cfg_path) # save the config run = self._run_factory(config, save_dir) try: run.record_commit(self._src_dir) run.dump_diff(self._src_dir) except InvalidGitRepositoryError: print('WARNING: could not obtain Git information.') run.metadata[ 'config'] = config._config_tree # save config in metadata, for programmatic access print('New TrainingRun created at: {}'.format(run.workspace.root)) return run def __iter__(self): return iter(self._int_dirs) def __len__(self): return len(self._int_dirs) def paths(self): return list(self._int_dirs.values())
class Experiments(Mapping): """A map from integers to Experiments.""" def __init__(self, root_dir, src_dir, experiment_factory, default_config_path, check_commit=True): """Create Experiments object. Args: root_dir (str): directory where all experiment data will be stored src_dir (str): a Git repository path (used to check commits) experiment_factory (Callable[[Config, str], Experiment]): a Callable, which takes a Config and a save_dir as arguments, and creates a new Experiment. default_config_path (str): path to a default config, to be used when no config is specified check_commit (bool): if True, checks that current working directory is on same commit as when the experiment was originally created. """ self._int_dirs = IntegerDirectories(root_dir) self._src_dir = src_dir self._exp_factory = experiment_factory self._check_commit = check_commit self._default_config_path = default_config_path def _config_path(self, save_dir): return join(save_dir, 'config.txt') def __getitem__(self, i): """Reload an existing Experiment.""" save_dir = self._int_dirs[i] config = Config.from_file(self._config_path(save_dir)) exp = self._exp_factory(config, save_dir) if self._check_commit: exp.match_commit(self._src_dir) logging.info('Reloaded experiment #{}'.format(i)) return exp def new(self, config=None, name=None): """Create a new Experiment.""" if config is None: config = Config.from_file(self._default_config_path) save_dir = self._int_dirs.new_dir(name=name) cfg_path = self._config_path(save_dir) config.to_file(cfg_path) # save the config exp = self._exp_factory(config, save_dir) exp.record_commit(self._src_dir) logging.info('New experiment created at: {}'.format( exp.workspace.root)) logging.info('Experiment configuration:\n{}'.format(config)) return exp def __iter__(self): return iter(self._int_dirs) def __len__(self): return len(self._int_dirs) def paths(self): return self._int_dirs.values()