def test_set_all_curriculums_to_lesson_num(): meta_curriculum = MetaCurriculum(test_meta_curriculum_config) meta_curriculum.set_all_curricula_to_lesson_num(2) assert meta_curriculum.brains_to_curricula["Brain1"].lesson_num == 2 assert meta_curriculum.brains_to_curricula["Brain2"].lesson_num == 2
def test_set_lesson_nums(curriculum_a, curriculum_b): meta_curriculum = MetaCurriculum({"Brain1": curriculum_a, "Brain2": curriculum_b}) meta_curriculum.lesson_nums = {"Brain1": 1, "Brain2": 3} assert curriculum_a.lesson_num == 1 assert curriculum_b.lesson_num == 3
def test_set_all_curriculums_to_lesson_num(curriculum_a, curriculum_b): meta_curriculum = MetaCurriculum({"Brain1": curriculum_a, "Brain2": curriculum_b}) meta_curriculum.set_all_curricula_to_lesson_num(2) assert curriculum_a.lesson_num == 2 assert curriculum_b.lesson_num == 2
def test_increment_lessons(curriculum_a, curriculum_b, measure_vals): meta_curriculum = MetaCurriculum({"Brain1": curriculum_a, "Brain2": curriculum_b}) meta_curriculum.increment_lessons(measure_vals) curriculum_a.increment_lesson.assert_called_with(0.2) curriculum_b.increment_lesson.assert_called_with(0.3)
def test_simple_metacurriculum(curriculum_brain_name): env = Simple1DEnvironment([BRAIN_NAME], use_discrete=False) curriculum_config = json.loads(dummy_curriculum_json_str) mc = MetaCurriculum({curriculum_brain_name: curriculum_config}) _check_environment_trains(env, TRAINER_CONFIG, meta_curriculum=mc, success_threshold=None)
def test_simple_metacurriculum(curriculum_brain_name): env = Simple1DEnvironment(use_discrete=False) with patch( "builtins.open", new_callable=mock_open, read_data=dummy_curriculum_json_str ): curriculum_config = Curriculum.load_curriculum_file("TestBrain.json") curriculum = Curriculum("TestBrain", curriculum_config) mc = MetaCurriculum({curriculum_brain_name: curriculum}) _check_environment_trains(env, META_CURRICULUM_CONFIG, mc, -100.0)
def try_create_meta_curriculum( curriculum_config: Optional[Dict], env: SubprocessEnvManager, restore: bool = False ) -> Optional[MetaCurriculum]: if curriculum_config is None or len(curriculum_config) <= 0: return None else: meta_curriculum = MetaCurriculum(curriculum_config) if restore: meta_curriculum.try_restore_all_curriculum() return meta_curriculum
def test_increment_lessons(measure_vals): meta_curriculum = MetaCurriculum(test_meta_curriculum_config) meta_curriculum.brains_to_curricula["Brain1"] = Mock() meta_curriculum.brains_to_curricula["Brain2"] = Mock() meta_curriculum.increment_lessons(measure_vals) meta_curriculum.brains_to_curricula[ "Brain1"].increment_lesson.assert_called_with(0.2) meta_curriculum.brains_to_curricula[ "Brain2"].increment_lesson.assert_called_with(0.3)
def test_increment_lessons_with_reward_buff_sizes( curriculum_a, curriculum_b, measure_vals, reward_buff_sizes ): curriculum_a.min_lesson_length = 5 curriculum_b.min_lesson_length = 10 meta_curriculum = MetaCurriculum({"Brain1": curriculum_a, "Brain2": curriculum_b}) meta_curriculum.increment_lessons(measure_vals, reward_buff_sizes=reward_buff_sizes) curriculum_a.increment_lesson.assert_called_with(0.2) curriculum_b.increment_lesson.assert_not_called()
def try_create_meta_curriculum( curriculum_config: Optional[Dict], env: SubprocessEnvManager, lesson: int ) -> Optional[MetaCurriculum]: if curriculum_config is None: return None else: meta_curriculum = MetaCurriculum(curriculum_config) # TODO: Should be able to start learning at different lesson numbers # for each curriculum. meta_curriculum.set_all_curricula_to_lesson_num(lesson) return meta_curriculum
def test_init_meta_curriculum_happy_path(listdir, mock_curriculum_init, mock_curriculum_get_config, default_reset_parameters): meta_curriculum = MetaCurriculum("test/") assert len(meta_curriculum.brains_to_curriculums) == 2 assert "Brain1" in meta_curriculum.brains_to_curriculums assert "Brain2.test" in meta_curriculum.brains_to_curriculums calls = [call("test/Brain1.json"), call("test/Brain2.test.json")] mock_curriculum_init.assert_has_calls(calls)
def try_create_meta_curriculum( curriculum_folder: Optional[str], env: SubprocessEnvManager, lesson: int ) -> Optional[MetaCurriculum]: if curriculum_folder is None: return None else: meta_curriculum = MetaCurriculum(curriculum_folder, env.reset_parameters) # TODO: Should be able to start learning at different lesson numbers # for each curriculum. meta_curriculum.set_all_curriculums_to_lesson_num(lesson) return meta_curriculum
def test_increment_lessons_with_reward_buff_sizes( curriculum_a, curriculum_b, measure_vals, reward_buff_sizes ): curriculum_a.min_lesson_length = 5 curriculum_b.min_lesson_length = 10 meta_curriculum = MetaCurriculum(test_meta_curriculum_config) meta_curriculum.brains_to_curricula["Brain1"] = curriculum_a meta_curriculum.brains_to_curricula["Brain2"] = curriculum_b meta_curriculum.increment_lessons(measure_vals, reward_buff_sizes=reward_buff_sizes) curriculum_a.increment_lesson.assert_called_with(0.2) curriculum_b.increment_lesson.assert_not_called()
def test_get_config( curriculum_a, curriculum_b, default_reset_parameters, more_reset_parameters ): curriculum_a.get_config.return_value = default_reset_parameters curriculum_b.get_config.return_value = default_reset_parameters meta_curriculum = MetaCurriculum({"Brain1": curriculum_a, "Brain2": curriculum_b}) assert meta_curriculum.get_config() == default_reset_parameters curriculum_b.get_config.return_value = more_reset_parameters new_reset_parameters = dict(default_reset_parameters) new_reset_parameters.update(more_reset_parameters) assert meta_curriculum.get_config() == new_reset_parameters
def test_init_meta_curriculum_happy_path(listdir, mock_curriculum_init, mock_curriculum_get_config, default_reset_parameters): meta_curriculum = MetaCurriculum('test/', default_reset_parameters) assert len(meta_curriculum.brains_to_curriculums) == 2 assert 'Brain1' in meta_curriculum.brains_to_curriculums assert 'Brain2' in meta_curriculum.brains_to_curriculums calls = [ call('test/Brain1.json', default_reset_parameters), call('test/Brain2.json', default_reset_parameters) ] mock_curriculum_init.assert_has_calls(calls)
def test_restore_curriculums(mock_trainingstatus): meta_curriculum = MetaCurriculum(test_meta_curriculum_config) # Test restore to value mock_trainingstatus.get_parameter_state.return_value = 2 meta_curriculum.try_restore_all_curriculum() mock_trainingstatus.get_parameter_state.assert_has_calls( [ call("Brain1", StatusType.LESSON_NUM), call("Brain2", StatusType.LESSON_NUM) ], any_order=True, ) assert meta_curriculum.brains_to_curricula["Brain1"].lesson_num == 2 assert meta_curriculum.brains_to_curricula["Brain2"].lesson_num == 2 # Test restore to None mock_trainingstatus.get_parameter_state.return_value = None meta_curriculum.try_restore_all_curriculum() assert meta_curriculum.brains_to_curricula["Brain1"].lesson_num == 0 assert meta_curriculum.brains_to_curricula["Brain2"].lesson_num == 0
def try_create_meta_curriculum( curriculum_folder: Optional[str], env: SubprocessEnvManager, lesson: int ) -> Optional[MetaCurriculum]: if curriculum_folder is None: return None else: meta_curriculum = MetaCurriculum(curriculum_folder, env.reset_parameters) # TODO: Should be able to start learning at different lesson numbers # for each curriculum. meta_curriculum.set_all_curriculums_to_lesson_num(lesson) for brain_name in meta_curriculum.brains_to_curriculums.keys(): if brain_name not in env.external_brains.keys(): raise MetaCurriculumError( "One of the curricula " "defined in " + curriculum_folder + " " "does not have a corresponding " "Brain. Check that the " "curriculum file has the same " "name as the Brain " "whose curriculum it defines." ) return meta_curriculum
def test_simple_metacurriculum(curriculum_brain_name): env = Simple1DEnvironment(use_discrete=False) curriculum_config = json.loads(dummy_curriculum_json_str) mc = MetaCurriculum({curriculum_brain_name: curriculum_config}) _check_environment_trains(env, TRAINER_CONFIG, mc, -100.0)
def __init__(self, env_path, run_id, save_freq, curriculum_folder, fast_simulation, load, train, worker_id, keep_checkpoints, lesson, seed, docker_target_name, trainer_config_path, no_graphics, camera_res_overwrite, benchmark, benchmark_episode, success_threshold, benchmark_verbose): """ :param env_path: Location to the environment executable to be loaded. :param run_id: The sub-directory name for model and summary statistics :param save_freq: Frequency at which to save model :param curriculum_folder: Folder containing JSON curriculums for the environment. :param fast_simulation: Whether to run the game at training speed. :param load: Whether to load the model or randomly initialize. :param train: Whether to train model, or only run inference. :param worker_id: Number to add to communication port (5005). Used for multi-environment :param keep_checkpoints: How many model checkpoints to keep. :param lesson: Start learning from this lesson. :param seed: Random seed used for training. :param docker_target_name: Name of docker volume that will contain all data. :param trainer_config_path: Fully qualified path to location of trainer configuration file. :param no_graphics: Whether to run the Unity simulator in no-graphics mode. """ if env_path is not None: # Strip out executable extensions if passed env_path = (env_path.strip().replace('.app', '').replace( '.exe', '').replace('.x86_64', '').replace('.x86', '')) # Recognize and use docker volume if one is passed as an argument if not docker_target_name: self.docker_training = False self.trainer_config_path = trainer_config_path self.model_path = './models/{run_id}'.format(run_id=run_id) self.curriculum_folder = curriculum_folder self.summaries_dir = './summaries' else: self.docker_training = True self.trainer_config_path = \ '/{docker_target_name}/{trainer_config_path}'.format( docker_target_name=docker_target_name, trainer_config_path = trainer_config_path) self.model_path = '/{docker_target_name}/models/{run_id}'.format( docker_target_name=docker_target_name, run_id=run_id) if env_path is not None: """ Comments for future maintenance: Some OS/VM instances (e.g. COS GCP Image) mount filesystems with COS flag which prevents execution of the Unity scene, to get around this, we will copy the executable into the container. """ # Navigate in docker path and find env_path and copy it. env_path = self._prepare_for_docker_run( docker_target_name, env_path) if curriculum_folder is not None: self.curriculum_folder = \ '/{docker_target_name}/{curriculum_folder}'.format( docker_target_name=docker_target_name, curriculum_folder=curriculum_folder) self.summaries_dir = '/{docker_target_name}/summaries'.format( docker_target_name=docker_target_name) self.logger = logging.getLogger('mlagents.envs') self.run_id = run_id self.save_freq = save_freq self.lesson = lesson self.fast_simulation = fast_simulation self.load_model = load self.train_model = train self.worker_id = worker_id self.keep_checkpoints = keep_checkpoints self.trainers = {} self.seed = seed self.benchmark = benchmark self.global_step = 0 self.benchmark_episode = benchmark_episode self.success_threshold = success_threshold self.benchmark_verbose = benchmark_verbose np.random.seed(self.seed) tf.set_random_seed(self.seed) self.env = UnityEnvironment(file_name=env_path, worker_id=self.worker_id, seed=self.seed, docker_training=self.docker_training, no_graphics=no_graphics, camera_res_overwrite=camera_res_overwrite) self.brain_name = self.env.brain_names[ 0] # Get brain_name, assume only have 1 brain if env_path is None: self.env_name = 'editor_' + self.env.academy_name else: # Extract out name of environment self.env_name = os.path.basename(os.path.normpath(env_path)) if curriculum_folder is None: self.meta_curriculum = None else: self.meta_curriculum = MetaCurriculum(self.curriculum_folder, self.env._resetParameters) if self.meta_curriculum: for brain_name in self.meta_curriculum.brains_to_curriculums.keys( ): if brain_name not in self.env.external_brain_names: raise MetaCurriculumError('One of the curriculums ' 'defined in ' + self.curriculum_folder + ' ' 'does not have a corresponding ' 'Brain. Check that the ' 'curriculum file has the same ' 'name as the Brain ' 'whose curriculum it defines.')
def test_simple_metacurriculum(curriculum_brain_name): env = SimpleEnvironment([BRAIN_NAME], use_discrete=False) mc = MetaCurriculum({curriculum_brain_name: dummy_curriculum_config}) _check_environment_trains(env, {BRAIN_NAME: PPO_CONFIG}, meta_curriculum=mc, success_threshold=None)
def test_get_config(): meta_curriculum = MetaCurriculum(test_meta_curriculum_config) assert meta_curriculum.get_config() == {"test_param1": 0.0, "test_param2": 0.0}
def test_init_meta_curriculum_bad_curriculum_folder_raises_error(listdir): with pytest.raises(MetaCurriculumError): MetaCurriculum("test/", default_reset_parameters)
def test_set_lesson_nums(): meta_curriculum = MetaCurriculum(test_meta_curriculum_config) meta_curriculum.lesson_nums = {"Brain1": 1, "Brain2": 3} assert meta_curriculum.brains_to_curricula["Brain1"].lesson_num == 1 assert meta_curriculum.brains_to_curricula["Brain2"].lesson_num == 3
def test_init_meta_curriculum_bad_curriculum_folder_raises_error(listdir): with pytest.raises(MetaCurriculumError): MetaCurriculum("test/")