Commit 381cd367 authored by Benjamin's avatar Benjamin
Browse files

Modif curriculum + metacurriculum to use yaml

parent 6ebfa72e
......@@ -3,6 +3,7 @@ import json
import math
from .exception import CurriculumError
from animalai.envs.arena_config import ArenaConfig
import logging
......@@ -10,10 +11,11 @@ logger = logging.getLogger('mlagents.trainers')
class Curriculum(object):
def __init__(self, location):
def __init__(self, location, yaml_files):
"""
Initializes a Curriculum object.
:param location: Path to JSON defining curriculum.
:param yaml_files: A list of configuration files for each lesson
"""
self.max_lesson_num = 0
self.measure = None
......@@ -32,7 +34,7 @@ class Curriculum(object):
raise CurriculumError('There was an error decoding {}'
.format(location))
self.smoothing_value = 0
for key in ['parameters', 'measure', 'thresholds',
for key in ['configuration_files', 'measure', 'thresholds',
'min_lesson_length', 'signal_smoothing']:
if key not in self.data:
raise CurriculumError("{0} does not contain a "
......@@ -43,18 +45,24 @@ class Curriculum(object):
self.min_lesson_length = self.data['min_lesson_length']
self.max_lesson_num = len(self.data['thresholds'])
parameters = self.data['parameters']
for key in parameters:
# if key not in default_reset_parameters:
# raise CurriculumError(
# 'The parameter {0} in Curriculum {1} is not present in '
# 'the Environment'.format(key, location))
if len(parameters[key]) != self.max_lesson_num + 1:
raise CurriculumError(
'The parameter {0} in Curriculum {1} must have {2} values '
'but {3} were found'.format(key, location,
self.max_lesson_num + 1,
len(parameters[key])))
configuration_files = self.data['configuration_files']
# for key in configuration_files:
# if key not in default_reset_parameters:
# raise CurriculumError(
# 'The parameter {0} in Curriculum {1} is not present in '
# 'the Environment'.format(key, location))
if len(configuration_files) != self.max_lesson_num + 1:
raise CurriculumError(
'The parameter {0} in Curriculum {1} must have {2} values '
'but {3} were found'.format(key, location,
self.max_lesson_num + 1,
len(configuration_files)))
folder_yaml_files = os.listdir(location)
if not all([file in folder_yaml_files for file in configuration_files]):
raise Curriculum(
'One or more configuration file(s) in curriculum {0} could not be found'.format(location)
)
self.configurations = [ArenaConfig(os.path.join(location, file) for file in yaml_files)]
@property
def lesson_num(self):
......@@ -79,15 +87,13 @@ class Curriculum(object):
if self.lesson_num < self.max_lesson_num:
if measure_val > self.data['thresholds'][self.lesson_num]:
self.lesson_num += 1
config = {}
parameters = self.data['parameters']
for key in parameters:
config[key] = parameters[key][self.lesson_num]
logger.info('{0} lesson changed. Now in lesson {1}: {2}'
# config = {}
# parameters = self.data['parameters']
# for key in parameters:
# config[key] = parameters[key][self.lesson_num]
logger.info('{0} lesson changed. Now in lesson {1}'
.format(self._brain_name,
self.lesson_num,
', '.join([str(x) + ' -> ' + str(config[x])
for x in config])))
self.lesson_num))
return True
return False
......@@ -103,8 +109,8 @@ class Curriculum(object):
if lesson is None:
lesson = self.lesson_num
lesson = max(0, min(lesson, self.max_lesson_num))
config = {}
parameters = self.data['parameters']
for key in parameters:
config[key] = parameters[key][lesson]
config = self.configurations[lesson]
# parameters = self.data['parameters']
# for key in parameters:
# config[key] = parameters[key][lesson]
return config
......@@ -20,34 +20,41 @@ class MetaCurriculum(object):
Args:
curriculum_folder (str): The relative or absolute path of the
folder which holds the curriculums for this environment.
The folder should contain JSON files whose names are the
brains that the curriculums belong to.
The folder should contain one JSON file which name is the
same as the brains in the academy (e.g Learner) and contains
the parameters for the curriculum as well as all the YAML
files for each curriculum lesson
"""
used_reset_parameters = set()
# used_reset_parameters = set()
self._brains_to_curriculums = {}
self._configuration_files = []
try:
for curriculum_filename in os.listdir(curriculum_folder):
brain_name = curriculum_filename.split('.')[0]
json_files = [file for file in os.listdir(curriculum_folder) if '.json' in file.lower()]
yaml_files = [file for file in os.listdir(curriculum_folder) if
('.yaml' in file.lower() or '.yml' in file.lower())]
for curriculum_filename in json_files:
brain_name= curriculum_filename.split('.')[0]
curriculum_filepath = \
os.path.join(curriculum_folder, curriculum_filename)
curriculum = Curriculum(curriculum_filepath)
curriculum = Curriculum(curriculum_filepath, yaml_files)
# ===== TO REMOVE ??? ===========
# Check if any two curriculums use the same reset params.
if any([(parameter in curriculum.get_config().keys())
for parameter in used_reset_parameters]):
logger.warning('Two or more curriculums will '
'attempt to change the same reset '
'parameter. The result will be '
'non-deterministic.')
used_reset_parameters.update(curriculum.get_config().keys())
# if any([(parameter in curriculum.get_config().keys())
# for parameter in used_reset_parameters]):
# logger.warning('Two or more curriculums will '
# 'attempt to change the same reset '
# 'parameter. The result will be '
# 'non-deterministic.')
#
# used_reset_parameters.update(curriculum.get_config().keys())
# ===== end of to remove =========
self._brains_to_curriculums[brain_name] = curriculum
except NotADirectoryError:
raise MetaCurriculumError(curriculum_folder + ' is not a '
'directory. Refer to the ML-Agents '
'curriculum learning docs.')
'directory. Refer to the ML-Agents '
'curriculum learning docs.')
@property
def brains_to_curriculums(self):
......@@ -83,7 +90,7 @@ class MetaCurriculum(object):
increment its lesson.
"""
return reward_buff_size >= (self.brains_to_curriculums[brain_name]
.min_lesson_length)
.min_lesson_length)
def increment_lessons(self, measure_vals, reward_buff_sizes=None):
"""Attempts to increments all the lessons of all the curriculums in this
......@@ -108,14 +115,13 @@ class MetaCurriculum(object):
if self._lesson_ready_to_increment(brain_name, buff_size):
measure_val = measure_vals[brain_name]
ret[brain_name] = (self.brains_to_curriculums[brain_name]
.increment_lesson(measure_val))
.increment_lesson(measure_val))
else:
for brain_name, measure_val in measure_vals.items():
ret[brain_name] = (self.brains_to_curriculums[brain_name]
.increment_lesson(measure_val))
.increment_lesson(measure_val))
return ret
def set_all_curriculums_to_lesson_num(self, lesson_num):
"""Sets all the curriculums in this meta curriculum to a specified
lesson number.
......@@ -127,7 +133,6 @@ class MetaCurriculum(object):
for _, curriculum in self.brains_to_curriculums.items():
curriculum.lesson_num = lesson_num
def get_config(self):
"""Get the combined configuration of all curriculums in this
MetaCurriculum.
......
!ArenaConfig
arenas:
0: !Arena
t: 250
items:
- !Item
name: Wall
positions:
- !Vector3 {x: -1, y: 0, z: 10}
colors:
rotations: [90]
sizes:
- !Vector3 {x: 1, y: 5, z: 9}
- !Item
name: GoodGoal
positions:
- !Vector3 {x: -1, y: 0, z: 35}
sizes:
- !Vector3 {x: 2, y: 2, z: 2}
- !Item
name: Agent
positions:
- !Vector3 {x: -1, y: 1, z: 5}
\ No newline at end of file
!ArenaConfig
arenas:
0: !Arena
t: 300
items:
- !Item
name: Wall
positions:
- !Vector3 {x: -1, y: 0, z: 10}
- !Vector3 {x: -1, y: 0, z: 20}
colors:
rotations: [90,90]
sizes:
- !Vector3 {x: 1, y: 5, z: 9}
- !Vector3 {x: 1, y: 5, z: 9}
- !Item
name: GoodGoal
positions:
- !Vector3 {x: -1, y: 0, z: 35}
sizes:
- !Vector3 {x: 2, y: 2, z: 2}
- !Item
name: Agent
positions:
- !Vector3 {x: -1, y: 1, z: 5}
\ No newline at end of file
!ArenaConfig
arenas:
0: !Arena
t: 350
items:
- !Item
name: Wall
positions:
- !Vector3 {x: -1, y: 0, z: 10}
- !Vector3 {x: -1, y: 0, z: 20}
- !Vector3 {x: -1, y: 0, z: 30}
colors:
rotations: [90,90,90]
sizes:
- !Vector3 {x: 1, y: 5, z: 9}
- !Vector3 {x: 1, y: 5, z: 9}
- !Vector3 {x: 1, y: 5, z: 9}
- !Item
name: GoodGoal
positions:
- !Vector3 {x: -1, y: 0, z: 35}
sizes:
- !Vector3 {x: 2, y: 2, z: 2}
- !Item
name: Agent
positions:
- !Vector3 {x: -1, y: 1, z: 5}
\ No newline at end of file
!ArenaConfig
arenas:
0: !Arena
t: 400
items:
- !Item
name: Wall
positions:
- !Vector3 {x: -1, y: 0, z: 10}
- !Vector3 {x: -1, y: 0, z: 20}
- !Vector3 {x: -1, y: 0, z: 30}
- !Vector3 {x: 10, y: 0, z: -1}
colors:
rotations: [90,90,90,0]
sizes:
- !Vector3 {x: 1, y: 5, z: 9}
- !Vector3 {x: 1, y: 5, z: 9}
- !Vector3 {x: 1, y: 5, z: 9}
- !Vector3 {x: 1, y: 5, z: 9}
- !Item
name: GoodGoal
positions:
- !Vector3 {x: -1, y: 0, z: 35}
sizes:
- !Vector3 {x: 2, y: 2, z: 2}
- !Item
name: Agent
positions:
- !Vector3 {x: -1, y: 1, z: 5}
\ No newline at end of file
!ArenaConfig
arenas:
0: !Arena
t: 500
items:
- !Item
name: Wall
positions:
- !Vector3 {x: -1, y: 0, z: 10}
- !Vector3 {x: -1, y: 0, z: 20}
- !Vector3 {x: -1, y: 0, z: 30}
- !Vector3 {x: 10, y: 0, z: -1}
- !Vector3 {x: 20, y: 0, z: -1}
colors:
rotations: [90,90,90,0,0]
sizes:
- !Vector3 {x: 1, y: 5, z: 9}
- !Vector3 {x: 1, y: 5, z: 9}
- !Vector3 {x: 1, y: 5, z: 9}
- !Vector3 {x: 1, y: 5, z: 9}
- !Vector3 {x: 1, y: 5, z: 9}
- !Item
name: GoodGoal
positions:
- !Vector3 {x: -1, y: 0, z: 35}
sizes:
- !Vector3 {x: 2, y: 2, z: 2}
- !Item
name: Agent
positions:
- !Vector3 {x: -1, y: 1, z: 5}
\ No newline at end of file
{
"measure": "progress",
"thresholds": [
0.1,
0.3,
0.5
],
"min_lesson_length": 100,
"signal_smoothing": true,
"configuration_files": [
"1.yaml",
"2.yaml",
"3.yaml",
"4.yaml",
"5.yaml"
]
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment