예제 #1
0
def _upload(training_dir,
            algorithm_id=None,
            writeup=None,
            benchmark_run_id=None,
            api_key=None,
            ignore_open_monitors=False,
            skip_videos=False):
    if not ignore_open_monitors:
        open_monitors = monitoring._open_monitors()
        if len(open_monitors) > 0:
            envs = [
                m.env.spec.id if m.env.spec else '(unknown)'
                for m in open_monitors
            ]
            raise error.Error(
                "Still have an open monitor on {}. You must run 'env.close()' before uploading."
                .format(', '.join(envs)))

    env_info, training_episode_batch, training_video = upload_training_data(
        training_dir, api_key=api_key, skip_videos=skip_videos)
    env_id = env_info['env_id']
    training_episode_batch_id = training_video_id = None
    if training_episode_batch:
        training_episode_batch_id = training_episode_batch.id
    if training_video:
        training_video_id = training_video.id

    if logger.level <= logging.INFO:
        if training_episode_batch_id is not None and training_video_id is not None:
            logger.info(
                '[%s] Creating evaluation object from %s with learning curve and training video',
                env_id, training_dir)
        elif training_episode_batch_id is not None:
            logger.info(
                '[%s] Creating evaluation object from %s with learning curve',
                env_id, training_dir)
        elif training_video_id is not None:
            logger.info(
                '[%s] Creating evaluation object from %s with training video',
                env_id, training_dir)
        else:
            raise error.Error(
                "[%s] You didn't have any recorded training data in %s. Once you've used 'env = gym.wrappers.Monitor(env, directory)' to start recording, you need to actually run some rollouts. Please join the community chat on https://gym.openai.com if you have any issues."
                % (env_id, training_dir))

    evaluation = resource.Evaluation.create(
        training_episode_batch=training_episode_batch_id,
        training_video=training_video_id,
        env=env_info['env_id'],
        algorithm={
            'id': algorithm_id,
        },
        benchmark_run_id=benchmark_run_id,
        writeup=writeup,
        gym_version=env_info['gym_version'],
        api_key=api_key,
    )

    return evaluation
예제 #2
0
    def make(self, options={}):
        """Instantiates an instance of the environment with appropriate kwargs"""
        if self._entry_point is None:
            raise error.Error(
                'Attempting to make deprecated env {}. (HINT: is there a newer registered version of this env?)'
                .format(self.id))

        elif callable(self._entry_point):
            env = self._entry_point()
        else:
            try:
                cls = load(self._entry_point)
                #env = cls(**self._kwargs)
                #TODO merge use of kwargs and options
                env = cls(options)
            except ModuleNotFoundError:
                #load envs directory if it exists
                import os, sys, importlib
                lib_path = os.getcwd() + os.sep + 'envs'
                sys.path.insert(0, lib_path)

                def snake(name):
                    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
                    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()

                mod = importlib.import_module(snake(self._entry_point))
                my_class = getattr(mod, self._entry_point)
                env = my_class(options)

        # Make the enviroment aware of which spec it came from.
        env.unwrapped._spec = self

        return env
예제 #3
0
    def spec(self, id):
        match = env_id_re.search(id)
        if not match:
            raise error.Error(
                'Attempted to look up malformed environment ID: {}. (Currently all IDs must be of the form {}.)'
                .format(id.encode('utf-8'), env_id_re.pattern))

        try:
            return self.env_specs[id]
        except KeyError:
            # Parse the env name and check to see if it matches the non-version
            # part of a valid env (could also check the exact number here)
            env_name = match.group(1)
            matching_envs = [
                valid_env_name
                for valid_env_name, valid_env_spec in self.env_specs.items()
                if env_name == valid_env_spec._env_name
            ]
            if matching_envs:
                raise error.DeprecatedEnv(
                    'Env {} not found (valid versions include {})'.format(
                        id, matching_envs))
            else:
                raise error.UnregisteredEnv(
                    'No registered env with id: {}'.format(id))
예제 #4
0
    def __init__(self,
                 id,
                 entry_point=None,
                 trials=100,
                 reward_threshold=None,
                 local_only=False,
                 kwargs=None,
                 nondeterministic=False,
                 tags=None,
                 max_episode_steps=None,
                 max_episode_seconds=None,
                 timestep_limit=None):
        self.id = id
        # Evaluation parameters
        self.trials = trials
        self.reward_threshold = reward_threshold
        # Environment properties
        self.nondeterministic = nondeterministic

        if tags is None:
            tags = {}
        self.tags = tags

        # BACKWARDS COMPAT 2017/1/18
        if tags.get('wrapper_config.TimeLimit.max_episode_steps'):
            max_episode_steps = tags.get(
                'wrapper_config.TimeLimit.max_episode_steps')
            # TODO: Add the following deprecation warning after 2017/02/18
            # warnings.warn("DEPRECATION WARNING wrapper_config.TimeLimit has been deprecated. Replace any calls to `register(tags={'wrapper_config.TimeLimit.max_episode_steps': 200)}` with `register(max_episode_steps=200)`. This change was made 2017/1/31 and is included in gym version 0.8.0. If you are getting many of these warnings, you may need to update universe past version 0.21.3")

        tags['wrapper_config.TimeLimit.max_episode_steps'] = max_episode_steps
        ######

        # BACKWARDS COMPAT 2017/1/31
        if timestep_limit is not None:
            max_episode_steps = timestep_limit
            # TODO: Add the following deprecation warning after 2017/03/01
            # warnings.warn("register(timestep_limit={}) is deprecated. Use register(max_episode_steps={}) instead.".format(timestep_limit, timestep_limit))
        ######

        self.max_episode_steps = max_episode_steps
        self.max_episode_seconds = max_episode_seconds

        # We may make some of these other parameters public if they're
        # useful.
        match = env_id_re.search(id)
        if not match:
            raise error.Error(
                'Attempted to register malformed environment ID: {}. (Currently all IDs must be of the form {}.)'
                .format(id, env_id_re.pattern))
        self._env_name = match.group(1)
        self._entry_point = entry_point
        self._local_only = local_only
        self._kwargs = {} if kwargs is None else kwargs
예제 #5
0
def upload_training_data(training_dir, api_key=None, skip_videos=False):
    # Could have multiple manifests
    results = monitoring.load_results(training_dir)
    if not results:
        raise error.Error('''Could not find any manifest files in {}.

(HINT: this usually means you did not yet close() your env.monitor and have not yet exited the process. You should call 'env.monitor.start(training_dir)' at the start of training and 'env.close()' at the end, or exit the process.)'''
                          .format(training_dir))

    manifests = results['manifests']
    env_info = results['env_info']
    data_sources = results['data_sources']
    timestamps = results['timestamps']
    episode_lengths = results['episode_lengths']
    episode_rewards = results['episode_rewards']
    episode_types = results['episode_types']
    initial_reset_timestamps = results['initial_reset_timestamps']
    videos = results['videos'] if not skip_videos else []

    env_id = env_info['env_id']
    logger.debug('[%s] Uploading data from manifest %s', env_id,
                 ', '.join(manifests))

    # Do the relevant uploads
    if len(episode_lengths) > 0:
        training_episode_batch = upload_training_episode_batch(
            data_sources,
            episode_lengths,
            episode_rewards,
            episode_types,
            initial_reset_timestamps,
            timestamps,
            api_key,
            env_id=env_id)
    else:
        training_episode_batch = None

    if len(videos) > MAX_VIDEOS:
        logger.warning(
            '[%s] You recorded videos for %s episodes, but the scoreboard only supports up to %s. We will automatically subsample for you, but you also might wish to adjust your video recording rate.',
            env_id, len(videos), MAX_VIDEOS)
        subsample_inds = np.linspace(0,
                                     len(videos) - 1,
                                     MAX_VIDEOS).astype('int')  #pylint: disable=E1101
        videos = [videos[i] for i in subsample_inds]

    if len(videos) > 0:
        training_video = upload_training_video(videos, api_key, env_id=env_id)
    else:
        training_video = None

    return env_info, training_episode_batch, training_video
예제 #6
0
 def register(self, id, **kwargs):
     if id in self.env_specs:
         raise error.Error('Cannot re-register id: {}'.format(id))
     self.env_specs[id] = EnvSpec(id, **kwargs)
예제 #7
0
def _upload_benchmark(training_dir, algorithm_id, benchmark_id,
                      benchmark_run_tags, api_key, ignore_open_monitors,
                      skip_videos):
    # We're uploading a benchmark run.
    directories = []
    env_ids = []
    for name, _, files in os.walk(training_dir):
        manifests = monitoring.detect_training_manifests(name, files=files)
        if manifests:
            env_info = monitoring.load_env_info_from_manifests(
                manifests, training_dir)
            env_ids.append(env_info['env_id'])
            directories.append(name)

    # Validate against benchmark spec
    try:
        spec = benchmark_spec(benchmark_id)
    except error.UnregisteredBenchmark:
        raise error.Error(
            "Invalid benchmark id: {}. Are you using a benchmark registered in gym/benchmarks/__init__.py?"
            .format(benchmark_id))

    spec_env_ids = [
        task.env_id for task in spec.tasks for _ in range(task.trials)
    ]

    if not env_ids:
        raise error.Error(
            "Could not find any evaluations in {}".format(training_dir))

    # This could be more stringent about mixing evaluations
    if sorted(env_ids) != sorted(spec_env_ids):
        logger.info(
            "WARNING: Evaluations do not match spec for benchmark %s. In %s, we found evaluations for %s, expected %s",
            benchmark_id, training_dir, sorted(env_ids), sorted(spec_env_ids))

    tags = json.dumps(benchmark_run_tags)
    _create_with_retries = util.retry_exponential_backoff(
        resource.BenchmarkRun.create,
        (error.APIConnectionError, ),
        max_retries=5,
        interval=3,
    )
    benchmark_run = _create_with_retries(benchmark_id=benchmark_id,
                                         algorithm_id=algorithm_id,
                                         tags=tags)
    benchmark_run_id = benchmark_run.id

    # Actually do the uploads.
    for training_dir in directories:
        # N.B. we don't propagate algorithm_id to Evaluation if we're running as part of a benchmark
        _upload_with_retries = util.retry_exponential_backoff(
            _upload,
            (error.APIConnectionError, ),
            max_retries=5,
            interval=3,
        )
        _upload_with_retries(training_dir, None, None, benchmark_run_id,
                             api_key, ignore_open_monitors, skip_videos)

    logger.info(
        """
****************************************************
You successfully uploaded your benchmark on %s to
SenseNet! You can find it at:

    %s

****************************************************
    """.rstrip(), benchmark_id, benchmark_run.web_url())

    return benchmark_run_id
예제 #8
0
def write_archive(videos, archive_file, env_id=None):
    if len(videos) > MAX_VIDEOS:
        raise error.Error(
            '[{}] Trying to upload {} videos, but there is a limit of {} currently. If you actually want to upload this many videos, please email [email protected] with your use-case.'
            .format(env_id, MAX_VIDEOS, len(videos)))

    logger.debug('[%s] Preparing an archive of %d videos: %s', env_id,
                 len(videos), videos)

    # Double check that there are no collisions
    basenames = set()
    manifest = {'version': 0, 'videos': []}

    with tarfile.open(fileobj=archive_file, mode='w:gz') as tar:
        for video_path, metadata_path in videos:
            video_name = os.path.basename(video_path)
            metadata_name = os.path.basename(metadata_path)

            if not os.path.exists(video_path):
                raise error.Error(
                    '[{}] No such video file {}. (HINT: Your video recorder may have broken midway through the run. You can check this with `video_recorder.functional`.)'
                    .format(env_id, video_path))
            elif not os.path.exists(metadata_path):
                raise error.Error(
                    '[{}] No such metadata file {}. (HINT: this should be automatically created when using a VideoRecorder instance.)'
                    .format(env_id, video_path))

            # Do some sanity checking
            if video_name in basenames:
                raise error.Error(
                    '[{}] Duplicated video name {} in video list: {}'.format(
                        env_id, video_name, videos))
            elif metadata_name in basenames:
                raise error.Error(
                    '[{}] Duplicated metadata file name {} in video list: {}'.
                    format(env_id, metadata_name, videos))
            elif not video_name_re.search(video_name):
                raise error.Error(
                    '[{}] Invalid video name {} (must match {})'.format(
                        env_id, video_name, video_name_re.pattern))
            elif not metadata_name_re.search(metadata_name):
                raise error.Error(
                    '[{}] Invalid metadata file name {} (must match {})'.
                    format(env_id, metadata_name, metadata_name_re.pattern))

            # Record that we've seen these names; add to manifest
            basenames.add(video_name)
            basenames.add(metadata_name)
            manifest['videos'].append((video_name, metadata_name))

            # Import the files into the archive
            tar.add(video_path, arcname=video_name, recursive=False)
            tar.add(metadata_path, arcname=metadata_name, recursive=False)

        f = tempfile.NamedTemporaryFile(mode='w+', delete=False)
        try:
            json.dump(manifest, f)
            f.close()
            tar.add(f.name, arcname='manifest.json')
        finally:
            f.close()
            os.remove(f.name)