From bc42e71a0298649844c9659062f3c8ea6bea2c7b Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Wed, 31 Mar 2021 18:42:53 -0400 Subject: [PATCH 01/16] Add strict check to settings.py --- ml-agents/mlagents/trainers/cli_utils.py | 8 ++++++++ ml-agents/mlagents/trainers/settings.py | 23 +++++++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/ml-agents/mlagents/trainers/cli_utils.py b/ml-agents/mlagents/trainers/cli_utils.py index fcb8b14b89..2646407dce 100644 --- a/ml-agents/mlagents/trainers/cli_utils.py +++ b/ml-agents/mlagents/trainers/cli_utils.py @@ -167,6 +167,14 @@ def _create_parser() -> argparse.ArgumentParser: action=DetectDefaultStoreTrue, help="Whether to enable debug-level logging for some parts of the code", ) + argparser.add_argument( + "--strict", + default=False, + action=DetectDefaultStoreTrue, + help="Use strict matching for behavior names. If a behavior name is found in the Unity environment." + "and not specified in the trainer configuration, an exception will be thrown unless default_config " + "is used.", + ) argparser.add_argument( "--env-args", default=None, diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index d0d175f2f0..902eb49e34 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -718,12 +718,26 @@ def __init__(self, *args): super().__init__(*args) else: super().__init__(TrainerSettings, *args) + self._strict = False + + def set_strict(self, is_strict: bool) -> None: + self._strict = is_strict def __missing__(self, key: Any) -> "TrainerSettings": if TrainerSettings.default_override is not None: - return copy.deepcopy(TrainerSettings.default_override) + self[key] = copy.deepcopy(TrainerSettings.default_override) + elif self._strict: + raise TrainerConfigError( + f"The behavior name {key} has not been specified in the trainer configuration. " + f"Please add an entry in the configuration file for {key}." + ) else: - return TrainerSettings() + warnings.warn( + f"Behavior name {key} does not match any behaviors specified " + f"in the trainer configuration file. A default configuration will be used." + ) + self[key] = TrainerSettings() + return self[key] # COMMAND LINE ######################################################################### @@ -800,6 +814,7 @@ class RunOptions(ExportableSettings): # These are options that are relevant to the run itself, and not the engine or environment. # They will be left here. debug: bool = parser.get_default("debug") + strict: bool = parser.get_default("strict") # Strict conversion cattr.register_structure_hook(EnvironmentSettings, strict_to_cls) cattr.register_structure_hook(EngineSettings, strict_to_cls) @@ -820,6 +835,10 @@ class RunOptions(ExportableSettings): ) cattr.register_unstructure_hook(collections.defaultdict, defaultdict_to_dict) + # Set strict check on DefaultTrainerDict + def __attrs_post_init__(self): + self.behaviors.set_strict(self.strict) + @staticmethod def from_argparse(args: argparse.Namespace) -> "RunOptions": """ From 48764a14a05ff1141f911a129edd689f41ffdda1 Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Wed, 31 Mar 2021 18:43:16 -0400 Subject: [PATCH 02/16] Remove warning from trainer factory, add test --- .../mlagents/trainers/tests/test_settings.py | 24 ++++++++++++++++++- .../trainers/trainer/trainer_factory.py | 5 ---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/ml-agents/mlagents/trainers/tests/test_settings.py b/ml-agents/mlagents/trainers/tests/test_settings.py index 52a0460718..f127c8ed62 100644 --- a/ml-agents/mlagents/trainers/tests/test_settings.py +++ b/ml-agents/mlagents/trainers/tests/test_settings.py @@ -508,7 +508,7 @@ def test_default_settings(): default_settings_cls = cattr.structure(default_settings, TrainerSettings) check_if_different(default_settings_cls, run_options.behaviors["test2"]) - # Check that an existing beehavior overrides the defaults in specified fields + # Check that an existing behavior overrides the defaults in specified fields test1_settings = run_options.behaviors["test1"] assert test1_settings.max_steps == 2 assert test1_settings.network_settings.hidden_units == 2000 @@ -519,6 +519,28 @@ def test_default_settings(): check_if_different(test1_settings, default_settings_cls) +def test_strict(): + # Create normal non-strict RunOptions + behaviors = {"test1": {"max_steps": 2, "network_settings": {"hidden_units": 2000}}} + run_options_dict = {"behaviors": behaviors} + ro = RunOptions.from_dict(run_options_dict) + # Test that we can grab an entry that is not in the dict. + assert isinstance(ro.behaviors["test2"], TrainerSettings) + + # Create strict RunOptions with no defualt_settings + run_options_dict = {"behaviors": behaviors, "strict": True} + ro = RunOptions.from_dict(run_options_dict) + with pytest.raises(TrainerConfigError): + ro.behaviors["test2"] + + # Create strict RunOptions with default settings + default_settings = {"max_steps": 1, "network_settings": {"num_layers": 1000}} + run_options_dict = {"default_settings": default_settings, "behaviors": behaviors} + ro = RunOptions.from_dict(run_options_dict) + # Test that we can grab an entry that is not in the dict. + assert isinstance(ro.behaviors["test2"], TrainerSettings) + + def test_pickle(): # Make sure RunOptions is pickle-able. run_options = RunOptions() diff --git a/ml-agents/mlagents/trainers/trainer/trainer_factory.py b/ml-agents/mlagents/trainers/trainer/trainer_factory.py index c5ed2a9f64..9d351e3b5c 100644 --- a/ml-agents/mlagents/trainers/trainer/trainer_factory.py +++ b/ml-agents/mlagents/trainers/trainer/trainer_factory.py @@ -56,11 +56,6 @@ def __init__( self.ghost_controller = GhostController() def generate(self, behavior_name: str) -> Trainer: - if behavior_name not in self.trainer_config.keys(): - logger.warning( - f"Behavior name {behavior_name} does not match any behaviors specified" - f"in the trainer configuration file: {sorted(self.trainer_config.keys())}" - ) trainer_settings = self.trainer_config[behavior_name] return TrainerFactory._initialize_trainer( trainer_settings, From ceb6cdeae6023b5bea548f78ae92583011cd11ae Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Wed, 31 Mar 2021 18:51:14 -0400 Subject: [PATCH 03/16] Add changelog --- com.unity.ml-agents/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/com.unity.ml-agents/CHANGELOG.md b/com.unity.ml-agents/CHANGELOG.md index 5703bd5c3c..706ee52df4 100755 --- a/com.unity.ml-agents/CHANGELOG.md +++ b/com.unity.ml-agents/CHANGELOG.md @@ -41,6 +41,8 @@ sizes and will need to be retrained. (#5181) depend on the previous behavior, you can explicitly set the Agent's `InferenceDevice` to `InferenceDevice.CPU`. (#5175) #### ml-agents / ml-agents-envs / gym-unity (Python) +- A `--strict` command line option has been added. `--strict` will require all behaviors found in a Unity +executable to be defined in the trainer configuration YAML, or that `default_settings` is specified. (#5210) ### Bug Fixes #### com.unity.ml-agents / com.unity.ml-agents.extensions (C#) From 9c5b41202c250513015b64c34a3a5a54f232c37b Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Thu, 1 Apr 2021 10:52:45 -0400 Subject: [PATCH 04/16] Fix test --- ml-agents/mlagents/trainers/tests/test_settings.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ml-agents/mlagents/trainers/tests/test_settings.py b/ml-agents/mlagents/trainers/tests/test_settings.py index f127c8ed62..42f51951e5 100644 --- a/ml-agents/mlagents/trainers/tests/test_settings.py +++ b/ml-agents/mlagents/trainers/tests/test_settings.py @@ -531,7 +531,8 @@ def test_strict(): run_options_dict = {"behaviors": behaviors, "strict": True} ro = RunOptions.from_dict(run_options_dict) with pytest.raises(TrainerConfigError): - ro.behaviors["test2"] + # Variable must be accessed otherwise Python won't query the dict + print(ro.behaviors["test2"]) # Create strict RunOptions with default settings default_settings = {"max_steps": 1, "network_settings": {"num_layers": 1000}} From 50bad0b7d7e5fb14fb4eb6e9213e9f163e665082 Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Thu, 1 Apr 2021 17:41:03 -0400 Subject: [PATCH 05/16] Update changelog --- com.unity.ml-agents/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.ml-agents/CHANGELOG.md b/com.unity.ml-agents/CHANGELOG.md index 706ee52df4..b4197d380c 100755 --- a/com.unity.ml-agents/CHANGELOG.md +++ b/com.unity.ml-agents/CHANGELOG.md @@ -41,8 +41,8 @@ sizes and will need to be retrained. (#5181) depend on the previous behavior, you can explicitly set the Agent's `InferenceDevice` to `InferenceDevice.CPU`. (#5175) #### ml-agents / ml-agents-envs / gym-unity (Python) -- A `--strict` command line option has been added. `--strict` will require all behaviors found in a Unity -executable to be defined in the trainer configuration YAML, or that `default_settings` is specified. (#5210) +- When using a configuration YAML, it is required to define all behaviors found in a Unity +executable in the trainer configuration YAML, or specify `default_settings`. (#5210) ### Bug Fixes #### com.unity.ml-agents / com.unity.ml-agents.extensions (C#) From 26d694852363a55529fd09530dbb8ca7ab3a4da5 Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Thu, 1 Apr 2021 17:42:25 -0400 Subject: [PATCH 06/16] Remove strict CLI options --- ml-agents/mlagents/trainers/cli_utils.py | 8 -------- ml-agents/mlagents/trainers/settings.py | 4 +++- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/ml-agents/mlagents/trainers/cli_utils.py b/ml-agents/mlagents/trainers/cli_utils.py index 2646407dce..fcb8b14b89 100644 --- a/ml-agents/mlagents/trainers/cli_utils.py +++ b/ml-agents/mlagents/trainers/cli_utils.py @@ -167,14 +167,6 @@ def _create_parser() -> argparse.ArgumentParser: action=DetectDefaultStoreTrue, help="Whether to enable debug-level logging for some parts of the code", ) - argparser.add_argument( - "--strict", - default=False, - action=DetectDefaultStoreTrue, - help="Use strict matching for behavior names. If a behavior name is found in the Unity environment." - "and not specified in the trainer configuration, an exception will be thrown unless default_config " - "is used.", - ) argparser.add_argument( "--env-args", default=None, diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index 902eb49e34..89c9442137 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -814,7 +814,7 @@ class RunOptions(ExportableSettings): # These are options that are relevant to the run itself, and not the engine or environment. # They will be left here. debug: bool = parser.get_default("debug") - strict: bool = parser.get_default("strict") + strict: bool = False # Strict conversion cattr.register_structure_hook(EnvironmentSettings, strict_to_cls) cattr.register_structure_hook(EngineSettings, strict_to_cls) @@ -859,6 +859,8 @@ def from_argparse(args: argparse.Namespace) -> "RunOptions": "torch_settings": {}, } if config_path is not None: + # If we're loading for a file, make sure we have strict on + configured_dict["strict"] = True configured_dict.update(load_config(config_path)) # Use the YAML file values for all values not specified in the CLI. From e84f21fab7510f820a2d2d77c7f18efc3b19d357 Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Tue, 6 Apr 2021 12:26:40 -0400 Subject: [PATCH 07/16] Remove strict option, rename, make strict default --- ml-agents/mlagents/trainers/settings.py | 27 ++++++++++++++----------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index 89c9442137..2cea173933 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -14,6 +14,7 @@ Union, ClassVar, ) + from enum import Enum import collections import argparse @@ -718,15 +719,15 @@ def __init__(self, *args): super().__init__(*args) else: super().__init__(TrainerSettings, *args) - self._strict = False + self._config_specified = True - def set_strict(self, is_strict: bool) -> None: - self._strict = is_strict + def set_config_specified(self, require_config_specified: bool) -> None: + self._config_specified = require_config_specified def __missing__(self, key: Any) -> "TrainerSettings": if TrainerSettings.default_override is not None: self[key] = copy.deepcopy(TrainerSettings.default_override) - elif self._strict: + elif self._config_specified: raise TrainerConfigError( f"The behavior name {key} has not been specified in the trainer configuration. " f"Please add an entry in the configuration file for {key}." @@ -814,8 +815,8 @@ class RunOptions(ExportableSettings): # These are options that are relevant to the run itself, and not the engine or environment. # They will be left here. debug: bool = parser.get_default("debug") - strict: bool = False - # Strict conversion + + # Convert to settings while making sure all fields are valid cattr.register_structure_hook(EnvironmentSettings, strict_to_cls) cattr.register_structure_hook(EngineSettings, strict_to_cls) cattr.register_structure_hook(CheckpointSettings, strict_to_cls) @@ -835,10 +836,6 @@ class RunOptions(ExportableSettings): ) cattr.register_unstructure_hook(collections.defaultdict, defaultdict_to_dict) - # Set strict check on DefaultTrainerDict - def __attrs_post_init__(self): - self.behaviors.set_strict(self.strict) - @staticmethod def from_argparse(args: argparse.Namespace) -> "RunOptions": """ @@ -858,10 +855,12 @@ def from_argparse(args: argparse.Namespace) -> "RunOptions": "engine_settings": {}, "torch_settings": {}, } + _require_all_behaviors = True if config_path is not None: - # If we're loading for a file, make sure we have strict on - configured_dict["strict"] = True + # If we're loading for a file, make sure we strictly match the behavior names configured_dict.update(load_config(config_path)) + else: + _require_all_behaviors = False # Use the YAML file values for all values not specified in the CLI. for key in configured_dict.keys(): @@ -889,6 +888,10 @@ def from_argparse(args: argparse.Namespace) -> "RunOptions": configured_dict[key] = val final_runoptions = RunOptions.from_dict(configured_dict) + # Need check to bypass type checking but keep structure on dict working + if isinstance(final_runoptions.behaviors, TrainerSettings.DefaultTrainerDict): + # configure whether or not we should require all behavior names to be found in the config YAML + final_runoptions.behaviors.set_config_specified(_require_all_behaviors) return final_runoptions @staticmethod From fb57b92e26a017a4ffec144853daea44c3e1d930 Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Tue, 6 Apr 2021 12:27:15 -0400 Subject: [PATCH 08/16] Remove newline --- ml-agents/mlagents/trainers/settings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index 2cea173933..821cfac013 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -14,7 +14,6 @@ Union, ClassVar, ) - from enum import Enum import collections import argparse From f476caf579fe0556e5bc7c3d97831c10cc7d8dad Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Tue, 6 Apr 2021 14:38:04 -0400 Subject: [PATCH 09/16] Update comments --- ml-agents/mlagents/trainers/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index 821cfac013..105f1c3d61 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -856,9 +856,9 @@ def from_argparse(args: argparse.Namespace) -> "RunOptions": } _require_all_behaviors = True if config_path is not None: - # If we're loading for a file, make sure we strictly match the behavior names configured_dict.update(load_config(config_path)) else: + # If we're not loading from a file, we don't require all behavior names to be specified. _require_all_behaviors = False # Use the YAML file values for all values not specified in the CLI. From f5e587b6734457e5dbfb33c13ebf04eceeb302a3 Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Thu, 15 Apr 2021 17:46:55 -0400 Subject: [PATCH 10/16] Set default dict to actually default to a default dict --- ml-agents/mlagents/trainers/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index 0d5c410517..5bd078be7d 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -718,7 +718,7 @@ def __init__(self, *args): super().__init__(*args) else: super().__init__(TrainerSettings, *args) - self._config_specified = True + self._config_specified = False def set_config_specified(self, require_config_specified: bool) -> None: self._config_specified = require_config_specified From 5f05c158045203f32e43074ff3f8f0afeec5efa1 Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Mon, 19 Apr 2021 15:01:46 -0400 Subject: [PATCH 11/16] Fix tests --- ml-agents/mlagents/trainers/tests/test_settings.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ml-agents/mlagents/trainers/tests/test_settings.py b/ml-agents/mlagents/trainers/tests/test_settings.py index 42f51951e5..70a181ab16 100644 --- a/ml-agents/mlagents/trainers/tests/test_settings.py +++ b/ml-agents/mlagents/trainers/tests/test_settings.py @@ -519,16 +519,20 @@ def test_default_settings(): check_if_different(test1_settings, default_settings_cls) -def test_strict(): - # Create normal non-strict RunOptions +def test_config_specified(): + # Test require all behavior names to be specified (or not) + # Remove any pre-set defaults + TrainerSettings.default_override = None behaviors = {"test1": {"max_steps": 2, "network_settings": {"hidden_units": 2000}}} run_options_dict = {"behaviors": behaviors} ro = RunOptions.from_dict(run_options_dict) + # Don't require all behavior names + ro.behaviors.set_config_specified(False) # Test that we can grab an entry that is not in the dict. assert isinstance(ro.behaviors["test2"], TrainerSettings) # Create strict RunOptions with no defualt_settings - run_options_dict = {"behaviors": behaviors, "strict": True} + run_options_dict = {"behaviors": behaviors} ro = RunOptions.from_dict(run_options_dict) with pytest.raises(TrainerConfigError): # Variable must be accessed otherwise Python won't query the dict From a7505c917210310abba460cbea23d69498ee427a Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Mon, 19 Apr 2021 15:04:18 -0400 Subject: [PATCH 12/16] Fix tests again --- ml-agents/mlagents/trainers/tests/test_settings.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ml-agents/mlagents/trainers/tests/test_settings.py b/ml-agents/mlagents/trainers/tests/test_settings.py index 70a181ab16..266b70d7a5 100644 --- a/ml-agents/mlagents/trainers/tests/test_settings.py +++ b/ml-agents/mlagents/trainers/tests/test_settings.py @@ -526,14 +526,14 @@ def test_config_specified(): behaviors = {"test1": {"max_steps": 2, "network_settings": {"hidden_units": 2000}}} run_options_dict = {"behaviors": behaviors} ro = RunOptions.from_dict(run_options_dict) - # Don't require all behavior names - ro.behaviors.set_config_specified(False) # Test that we can grab an entry that is not in the dict. assert isinstance(ro.behaviors["test2"], TrainerSettings) # Create strict RunOptions with no defualt_settings run_options_dict = {"behaviors": behaviors} ro = RunOptions.from_dict(run_options_dict) + # Require all behavior names + ro.behaviors.set_config_specified(True) with pytest.raises(TrainerConfigError): # Variable must be accessed otherwise Python won't query the dict print(ro.behaviors["test2"]) @@ -542,6 +542,8 @@ def test_config_specified(): default_settings = {"max_steps": 1, "network_settings": {"num_layers": 1000}} run_options_dict = {"default_settings": default_settings, "behaviors": behaviors} ro = RunOptions.from_dict(run_options_dict) + # Require all behavior names + ro.behaviors.set_config_specified(True) # Test that we can grab an entry that is not in the dict. assert isinstance(ro.behaviors["test2"], TrainerSettings) From 125eb3f61605c0256fede99deb283e02dd740209 Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Mon, 19 Apr 2021 15:10:05 -0400 Subject: [PATCH 13/16] Default trainer dict to requiring all fields --- ml-agents/mlagents/trainers/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index 5bd078be7d..0d5c410517 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -718,7 +718,7 @@ def __init__(self, *args): super().__init__(*args) else: super().__init__(TrainerSettings, *args) - self._config_specified = False + self._config_specified = True def set_config_specified(self, require_config_specified: bool) -> None: self._config_specified = require_config_specified From 88a6bc88797a09c14607640cf6a219e107ac7355 Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Mon, 19 Apr 2021 15:15:40 -0400 Subject: [PATCH 14/16] Fix settings typing --- ml-agents/mlagents/trainers/settings.py | 6 +++--- ml-agents/mlagents/trainers/tests/test_settings.py | 4 +++- ml-agents/mlagents/trainers/tests/test_trainer_util.py | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index 0d5c410517..98aec23bc2 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -661,7 +661,7 @@ def _check_batch_size_seq_length(self, attribute, value): ) @staticmethod - def dict_to_defaultdict(d: Dict, t: type) -> DefaultDict: + def dict_to_trainerdict(d: Dict, t: type) -> "TrainerSettings.DefaultTrainerDict": return TrainerSettings.DefaultTrainerDict( cattr.structure(d, Dict[str, TrainerSettings]) ) @@ -802,7 +802,7 @@ class TorchSettings: @attr.s(auto_attribs=True) class RunOptions(ExportableSettings): default_settings: Optional[TrainerSettings] = None - behaviors: DefaultDict[str, TrainerSettings] = attr.ib( + behaviors: TrainerSettings.DefaultTrainerDict = attr.ib( factory=TrainerSettings.DefaultTrainerDict ) env_settings: EnvironmentSettings = attr.ib(factory=EnvironmentSettings) @@ -831,7 +831,7 @@ class RunOptions(ExportableSettings): ) cattr.register_structure_hook(TrainerSettings, TrainerSettings.structure) cattr.register_structure_hook( - DefaultDict[str, TrainerSettings], TrainerSettings.dict_to_defaultdict + TrainerSettings.DefaultTrainerDict, TrainerSettings.dict_to_trainerdict ) cattr.register_unstructure_hook(collections.defaultdict, defaultdict_to_dict) diff --git a/ml-agents/mlagents/trainers/tests/test_settings.py b/ml-agents/mlagents/trainers/tests/test_settings.py index 266b70d7a5..5e4a78d6d5 100644 --- a/ml-agents/mlagents/trainers/tests/test_settings.py +++ b/ml-agents/mlagents/trainers/tests/test_settings.py @@ -77,9 +77,9 @@ def test_no_configuration(): Verify that a new config will have a PPO trainer with extrinsic rewards. """ blank_runoptions = RunOptions() + blank_runoptions.behaviors.set_config_specified(False) assert isinstance(blank_runoptions.behaviors["test"], TrainerSettings) assert isinstance(blank_runoptions.behaviors["test"].hyperparameters, PPOSettings) - assert ( RewardSignalType.EXTRINSIC in blank_runoptions.behaviors["test"].reward_signals ) @@ -526,6 +526,8 @@ def test_config_specified(): behaviors = {"test1": {"max_steps": 2, "network_settings": {"hidden_units": 2000}}} run_options_dict = {"behaviors": behaviors} ro = RunOptions.from_dict(run_options_dict) + # Don't require all behavior names + ro.behaviors.set_config_specified(False) # Test that we can grab an entry that is not in the dict. assert isinstance(ro.behaviors["test2"], TrainerSettings) diff --git a/ml-agents/mlagents/trainers/tests/test_trainer_util.py b/ml-agents/mlagents/trainers/tests/test_trainer_util.py index 62c7be9107..e8459d0752 100644 --- a/ml-agents/mlagents/trainers/tests/test_trainer_util.py +++ b/ml-agents/mlagents/trainers/tests/test_trainer_util.py @@ -71,6 +71,8 @@ def test_handles_no_config_provided(): """ brain_name = "testbrain" no_default_config = RunOptions().behaviors + # Pretend this was created without a YAML file + no_default_config.set_config_specified(False) trainer_factory = TrainerFactory( trainer_config=no_default_config, From 402b53804f3e4fd7717fa774b53c6984db8a55bf Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Mon, 19 Apr 2021 15:19:19 -0400 Subject: [PATCH 15/16] Use logger --- ml-agents/mlagents/trainers/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index 98aec23bc2..6ce3d8d2ea 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -732,7 +732,7 @@ def __missing__(self, key: Any) -> "TrainerSettings": f"Please add an entry in the configuration file for {key}." ) else: - warnings.warn( + logger.warn( f"Behavior name {key} does not match any behaviors specified " f"in the trainer configuration file. A default configuration will be used." ) From 800f7c40e6db9ad22d98c095f867c215ebeb3081 Mon Sep 17 00:00:00 2001 From: Ervin Teng Date: Mon, 19 Apr 2021 15:20:22 -0400 Subject: [PATCH 16/16] Add default_settings to error --- ml-agents/mlagents/trainers/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml-agents/mlagents/trainers/settings.py b/ml-agents/mlagents/trainers/settings.py index 6ce3d8d2ea..6226cf9bf4 100644 --- a/ml-agents/mlagents/trainers/settings.py +++ b/ml-agents/mlagents/trainers/settings.py @@ -729,7 +729,7 @@ def __missing__(self, key: Any) -> "TrainerSettings": elif self._config_specified: raise TrainerConfigError( f"The behavior name {key} has not been specified in the trainer configuration. " - f"Please add an entry in the configuration file for {key}." + f"Please add an entry in the configuration file for {key}, or set default_settings." ) else: logger.warn(