Как сделать входные данные и модель одинаковой формы (обучение с подкреплением RLlib Ray Sagemaker)

У меня несоответствие форм входных данных и модели моего проекта обучения с подкреплением.

Я внимательно слежу за примерами AWS, особенно за примером тележки. Однако я создал свою собственную среду. Я изо всех сил пытаюсь понять, как изменить мою среду, чтобы она могла работать с предварительно созданным Ray RLEstimator.

Вот код среды:

from enum import Enum
import math

import gym
from gym import error, spaces, utils, wrappers
from gym.utils import seeding
from gym.envs.registration import register
from gym.spaces import Discrete, Box


import numpy as np

# from float_space import FloatSpace


def sigmoid_price_fun(x, maxcust, gamma):
    return maxcust / (1 + math.exp(gamma * max(0, x)))


class Actions(Enum):
    DECREASE_PRICE = 0
    INCREASE_PRICE = 1
    HOLD = 2


PRICE_ADJUSTMENT = {
    Actions.DECREASE_PRICE: -0.25,
    Actions.INCREASE_PRICE: 0.25,
    Actions.HOLD: 0
}


class ArrivalSim(gym.Env):
    """ Simple environment for price optimising RL learner. """


    def __init__(self, price):
        """
        Parameters
        ----------
        price : float
            The initial price to use.
        """
        super().__init__()
        self.price = price
        self.revenue = 0
        self.action_space = Discrete(3)  # [0, 1, 2]  #increase or decrease
        self.observation_space = Box(np.array(0.0),np.array(1000))
#         self.observation_space = FloatSpace(price)

    def step(self, action):
        """ Enacts the specified action in the environment.

        Returns the new price, reward, whether we're finished and an empty dict for compatibility with Gym's
        interface. """

        self._take_action(Actions(action))
        next_state = self.price
#         next_state = self.observation_space.sample()
        reward = self._get_reward()
        done = False

        if next_state < 0 or reward == 0:
            done = True

        print(next_state, reward, done, {})

        return np.array(next_state), reward, done, {}

    def reset(self):
        """ Resets the environment, selecting a random initial price. Returns the price. """

#         self.observation_space.value = np.random.rand()
#         return self.observation_space.sample()
        self.price = np.random.rand()
        return self.price

    def _take_action(self, action):
#         self.observation_space.value += PRICE_ADJUSTMENT[action]
        self.price += PRICE_ADJUSTMENT[action]

    def _get_reward(self,price):
#         price = self.observation_space.value
#         return max(np.random.poisson(sigmoid_price_fun(price, 50, 0.5)) * price, 0)
        self.revenue = max(np.random.poisson(sigmoid_price_fun(self.price, 50, 0.5)) * self.price, 0)
        return max(np.random.poisson(sigmoid_price_fun(self.price, 50, 0.5)) * self.price, 0)


#     def render(self, mode='human'):
#         super().render(mode)

def testEnv():
    register(
        id='ArrivalSim-v0',
        entry_point='env:ArrivalSim',
        kwargs= {'price' : 40}
    )
    env = gym.make('ArrivalSim-v0')

    env.reset()
    for _ in range(20):
        test = env.action_space.sample()
        print(test)
        print(env.observation_space)
        env.step(test)  # take a random action
    env.close()



if __name__ =='__main__':

    testEnv()

Вот сценарий обучения

import json
import os

import gym
import ray
from ray.tune import run_experiments
from ray.tune.registry import register_env
from gym.envs.registration import register

from sagemaker_rl.ray_launcher import SageMakerRayLauncher


def create_environment(env_config):
    import gym
#     from gym.spaces import Space
    from gym.envs.registration import register

    # This import must happen inside the method so that worker processes import this code
    register(
        id='ArrivalSim-v0',
        entry_point='env:ArrivalSim',
        kwargs= {'price' : 40}
    )
    return gym.make('ArrivalSim-v0')



class MyLauncher(SageMakerRayLauncher):

    def register_env_creator(self):
        register_env("ArrivalSim-v0", create_environment)

    def get_experiment_config(self):
        return {
          "training": {
            "env": "ArrivalSim-v0",
            "run": "PPO",
            "stop": {
              "episode_reward_mean": 5000,
            },
            "config": {
              "gamma": 0.995,
              "kl_coeff": 1.0,
              "num_sgd_iter": 10,
              "lr": 0.0001,
              "sgd_minibatch_size": 32768,
              "train_batch_size": 320000,
              "monitor": False,  # Record videos.
              "model": {
                "free_log_std": False
              },
              "use_gae": False,
              "num_workers": (self.num_cpus-1),
              "num_gpus": self.num_gpus,
              "batch_mode": "complete_episodes"

            }
          }
        }

if __name__ == "__main__":
    MyLauncher().train_main()

Вот код, который я запускаю в Jupyter:

metric_definitions = RLEstimator.default_metric_definitions(RLToolkit.RAY)
environment = env = {
    'SAGEMAKER_REQUIREMENTS': 'requirements.txt', # path relative to `source_dir` below.
}

estimator = RLEstimator(entry_point="train.py",
                        source_dir='.',
                        toolkit=RLToolkit.RAY,
                        toolkit_version='0.6.5',
                        framework=RLFramework.TENSORFLOW,
                        dependencies=["sagemaker_rl"],
#                         image_name='price-response-ray-cpu',
                        role=role,
#                         train_instance_type="ml.c5.2xlarge",
                        train_instance_type='local',
                        train_instance_count=1,
#                         output_path=s3_output_path,
#                         base_job_name=job_name_prefix,
                        metric_definitions=metric_definitions
#                         hyperparameters={
                          # Attention scientists!  You can override any Ray algorithm parameter here:
                          #"rl.training.config.horizon": 5000,
                          #"rl.training.config.num_sgd_iter": 10,
                        #}
                    )

estimator.fit(wait=True)
job_name = estimator.latest_training_job.job_name
print("Training job: %s" % job_name)

Я получаю следующее сообщение об ошибке:

algo-1-dxwxx_1  | == Status ==
algo-1-dxwxx_1  | Using FIFO scheduling algorithm.
algo-1-dxwxx_1  | Resources requested: 0/3 CPUs, 0/0 GPUs
algo-1-dxwxx_1  | Memory usage on this node: 1.1/4.1 GB
algo-1-dxwxx_1  | 
algo-1-dxwxx_1  | == Status ==
algo-1-dxwxx_1  | Using FIFO scheduling algorithm.
algo-1-dxwxx_1  | Resources requested: 2/3 CPUs, 0/0 GPUs
algo-1-dxwxx_1  | Memory usage on this node: 1.4/4.1 GB
algo-1-dxwxx_1  | Result logdir: /opt/ml/output/intermediate/training
algo-1-dxwxx_1  | Number of trials: 1 ({'RUNNING': 1})
algo-1-dxwxx_1  | RUNNING trials:
algo-1-dxwxx_1  |  - PPO_ArrivalSim-v0_0:   RUNNING
algo-1-dxwxx_1  | 
algo-1-dxwxx_1  | (pid=72) 2019-08-30 09:35:13,030  WARNING ppo.py:172 -- FYI: By default, the value function will not share layers with the policy model ('vf_share_layers': False).
algo-1-dxwxx_1  | 2019-08-30 09:35:13,063   ERROR trial_runner.py:460 -- Error processing event.
algo-1-dxwxx_1  | Traceback (most recent call last):
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/tune/trial_runner.py", line 409, in _process_trial
algo-1-dxwxx_1  |     result = self.trial_executor.fetch_result(trial)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/tune/ray_trial_executor.py", line 314, in fetch_result
algo-1-dxwxx_1  |     result = ray.get(trial_future[0])
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/worker.py", line 2316, in get
algo-1-dxwxx_1  |     raise value
algo-1-dxwxx_1  | ray.exceptions.RayTaskError: ray_worker (pid=72, host=b9b15d495b68)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/models/model.py", line 83, in __init__
algo-1-dxwxx_1  |     restored, num_outputs, options)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/models/model.py", line 135, in _build_layers_v2
algo-1-dxwxx_1  |     raise NotImplementedError
algo-1-dxwxx_1  | NotImplementedError
algo-1-dxwxx_1  | 
algo-1-dxwxx_1  | During handling of the above exception, another exception occurred:
algo-1-dxwxx_1  | 
algo-1-dxwxx_1  | ray_worker (pid=72, host=b9b15d495b68)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/agents/agent.py", line 276, in __init__
algo-1-dxwxx_1  |     Trainable.__init__(self, config, logger_creator)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/tune/trainable.py", line 88, in __init__
algo-1-dxwxx_1  |     self._setup(copy.deepcopy(self.config))
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/agents/agent.py", line 373, in _setup
algo-1-dxwxx_1  |     self._init()
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/agents/ppo/ppo.py", line 77, in _init
algo-1-dxwxx_1  |     self.env_creator, self._policy_graph)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/agents/agent.py", line 506, in make_local_evaluator
algo-1-dxwxx_1  |     extra_config or {}))
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/agents/agent.py", line 714, in _make_evaluator
algo-1-dxwxx_1  |     async_remote_worker_envs=config["async_remote_worker_envs"])
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/evaluation/policy_evaluator.py", line 288, in __init__
algo-1-dxwxx_1  |     self._build_policy_map(policy_dict, policy_config)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/evaluation/policy_evaluator.py", line 661, in _build_policy_map
algo-1-dxwxx_1  |     policy_map[name] = cls(obs_space, act_space, merged_conf)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/agents/ppo/ppo_policy_graph.py", line 176, in __init__
algo-1-dxwxx_1  |     seq_lens=existing_seq_lens)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/models/catalog.py", line 215, in get_model
algo-1-dxwxx_1  |     seq_lens)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/models/catalog.py", line 255, in _get_model
algo-1-dxwxx_1  |     num_outputs, options)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/models/model.py", line 86, in __init__
algo-1-dxwxx_1  |     input_dict["obs"], num_outputs, options)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/ray/rllib/models/fcnet.py", line 37, in _build_layers
algo-1-dxwxx_1  |     scope=label)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/tensorflow/contrib/framework/python/ops/arg_scope.py", line 182, in func_with_args
algo-1-dxwxx_1  |     return func(*args, **current_args)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/tensorflow/contrib/layers/python/layers/layers.py", line 1854, in fully_connected
algo-1-dxwxx_1  |     outputs = layer.apply(inputs)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py", line 817, in apply
algo-1-dxwxx_1  |     return self.__call__(inputs, *args, **kwargs)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/layers/base.py", line 374, in __call__
algo-1-dxwxx_1  |     outputs = super(Layer, self).__call__(inputs, *args, **kwargs)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py", line 730, in __call__
algo-1-dxwxx_1  |     self._assert_input_compatibility(inputs)
algo-1-dxwxx_1  |   File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py", line 1493, in _assert_input_compatibility
algo-1-dxwxx_1  |     str(x.shape.as_list()))
algo-1-dxwxx_1  | ValueError: Input 0 of layer default/fc1 is incompatible with the layer: : expected min_ndim=2, found ndim=1. Full shape received: [None]
algo-1-dxwxx_1  | 
algo-1-dxwxx_1  | 2019-08-30 09:35:13,064   INFO ray_trial_executor.py:178 -- Destroying actor for trial PPO_ArrivalSim-v0_0. If your trainable is slow to initialize, consider setting reuse_actors=True to reduce actor creation overheads.
algo-1-dxwxx_1  | 2019-08-30 09:35:13,076   INFO trial_runner.py:497 -- Attempting to recover trial state from last checkpoint.
algo-1-dxwxx_1  | (pid=72) 2019-08-30 09:35:13,041  INFO policy_evaluator.py:278 -- Creating policy evaluation worker 0 on CPU (please ignore any CUDA init errors)

Я не уверен, как изменить ввод, который среда дает модели, или саму настройку моделей. Похоже, что документация не совсем ясна. У меня есть подозрение, что проблема связана с областями наблюдения и действия.

Вот ссылка на исходный пример проекта aws: https://github.com/awslabs/amazon-sagemaker-examples/tree/master/reinforcement_learning/rl_roboschool_ray


person Rishan    schedule 30.08.2019    source источник


Ответы (1)


Возможная причина:

Сообщение об ошибке:

ValueError: Input 0 of layer default/fc1 is incompatible with the layer: : expected min_ndim=2, found ndim=1. Full shape received: [None]

Ваше исходное пространство для наблюдения за окружающей средой - self.observation_space = Box(np.array(0.0),np.array(1000)).

Отображение формы вашего окружения в пространстве дает:

print(Box(np.array(0.0), np.array(1000), dtype=np.float32).shape) = ()

На это может указывать Full shape received: [None] в сообщении об ошибке.

Если вы передадите фигуру (1,1) в np.zeros, вы получите ожидаемый min_ndim=2:

x = np.zeros((1, 1)) print(x) [[0.]] print(x.ndim) 2

Предлагаемое решение:

Я предполагаю, что вы хотите, чтобы пространство obs вашего окружения находилось в диапазоне от 0,0 до 1000,0, как указано self.price = np.random.rand() в вашей reset функции.

Попробуйте использовать следующее для вашего окружения obs space:

self.observation_space = Box(0.0, 1000.0, shape=(1,1), dtype=np.float32)

Я надеюсь, что установка Box с явным shape поможет.

ИЗМЕНИТЬ (20190903):

Я изменил ваш тренировочный сценарий. Эта модификация включает в себя новый импорт, пользовательский класс модели, регистрацию модели и добавление зарегистрированной пользовательской модели в config. Для удобства чтения ниже показаны только добавленные разделы. Полный измененный сценарий обучения доступен в этой сути. Пожалуйста, используйте предложенное пространство для обследования, как описано выше.

Новый дополнительный импорт:

# new imports
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import numpy as np
from ray.rllib.models import ModelCatalog
from ray.rllib.models.tf.tf_modelv2 import TFModelV2
from ray.rllib.models.tf.fcnet_v2 import FullyConnectedNetwork

from ray.rllib.utils import try_import_tf
from ray.tune import grid_search

tf = try_import_tf()
# end new imports

Класс нестандартной модели:

# Custom model class (fcnet)
class CustomModel(TFModelV2):
    """Example of a custom model that just delegates to a fc-net."""

    def __init__(self, obs_space, action_space, num_outputs, model_config,
                 name):
        super(CustomModel, self).__init__(obs_space, action_space, num_outputs,
                                          model_config, name)
        self.model = FullyConnectedNetwork(obs_space, action_space,
                                           num_outputs, model_config, name)
        self.register_variables(self.model.variables())

    def forward(self, input_dict, state, seq_lens):
        return self.model.forward(input_dict, state, seq_lens)

    def value_function(self):
        return self.model.value_function()

Зарегистрировали и добавили нестандартную модель:

    def get_experiment_config(self):


        # Register custom model
        ModelCatalog.register_custom_model("my_model", CustomModel)


        return {
          "training": {
            "env": "ArrivalSim-v0",
            "run": "PPO",
            "stop": {
              "episode_reward_mean": 5000,
            },
            "config": {


              "model": {"custom_model": "my_model"}, # Add registered custom model


              "gamma": 0.995,
              "kl_coeff": 1.0,
              "num_sgd_iter": 10,
              "lr": 0.0001,
              "sgd_minibatch_size": 32768,
              "train_batch_size": 320000,
              "monitor": False,  # Record videos.
              "model": {
                "free_log_std": False
              },
              "use_gae": False,
              "num_workers": (self.num_cpus-1),
              "num_gpus": self.num_gpus,
              "batch_mode": "complete_episodes"
            }
          }
        }

РЕДАКТИРОВАТЬ 2 (20190910):

Чтобы показать, что это работает, усеченный вывод Sagemaker (экземпляр записной книжки Jupyter):

.
.
.
algo-1-y2ayw_1  | price b = 0.439261780930142
algo-1-y2ayw_1  | price a = 0.439261780930142
algo-1-y2ayw_1  | (self.price).shape = (1,)
algo-1-y2ayw_1  | [0.43926178] 10.103020961393266 False {}
algo-1-y2ayw_1  | price b = 0.439261780930142
algo-1-y2ayw_1  | price a = 0.439261780930142
algo-1-y2ayw_1  | (self.price).shape = (1,)
algo-1-y2ayw_1  | [0.43926178] 9.663759180463124 False {}
algo-1-y2ayw_1  | price b = 0.439261780930142
algo-1-y2ayw_1  | price a = 0.189261780930142
algo-1-y2ayw_1  | (self.price).shape = (1,)
algo-1-y2ayw_1  | [0.18926178] 5.67785342790426 False {}
algo-1-y2ayw_1  | price b = 0.189261780930142
algo-1-y2ayw_1  | price a = -0.06073821906985799
algo-1-y2ayw_1  | (self.price).shape = (1,)
algo-1-y2ayw_1  | [-0.06073822] 0 True {}
algo-1-y2ayw_1  | Result for PPO_ArrivalSim-v0_0:
algo-1-y2ayw_1  |   date: 2019-09-10_11-51-13
algo-1-y2ayw_1  |   done: true
algo-1-y2ayw_1  |   episode_len_mean: 126.72727272727273
algo-1-y2ayw_1  |   episode_reward_max: 15772.677709596366
algo-1-y2ayw_1  |   episode_reward_mean: 2964.4609668691965
algo-1-y2ayw_1  |   episode_reward_min: 0.0
algo-1-y2ayw_1  |   episodes: 5
algo-1-y2ayw_1  |   experiment_id: 5d3b9f2988854a0db164a2e5e9a7550f
algo-1-y2ayw_1  |   hostname: 2dae585dcc65
algo-1-y2ayw_1  |   info:
algo-1-y2ayw_1  |     cur_lr: 4.999999873689376e-05
algo-1-y2ayw_1  |     entropy: 1.0670874118804932
algo-1-y2ayw_1  |     grad_time_ms: 1195.066
algo-1-y2ayw_1  |     kl: 3.391784191131592
algo-1-y2ayw_1  |     load_time_ms: 44.725
algo-1-y2ayw_1  |     num_steps_sampled: 463
algo-1-y2ayw_1  |     num_steps_trained: 463
algo-1-y2ayw_1  |     policy_loss: -0.05383850634098053
algo-1-y2ayw_1  |     sample_time_ms: 621.282
algo-1-y2ayw_1  |     total_loss: 2194493.5
algo-1-y2ayw_1  |     update_time_ms: 145.352
algo-1-y2ayw_1  |     vf_explained_var: -5.519390106201172e-05
algo-1-y2ayw_1  |     vf_loss: 2194492.5
algo-1-y2ayw_1  |   iterations_since_restore: 2
algo-1-y2ayw_1  |   node_ip: 172.18.0.2
algo-1-y2ayw_1  |   pid: 77
algo-1-y2ayw_1  |   policy_reward_mean: {}
algo-1-y2ayw_1  |   time_since_restore: 4.55129861831665
algo-1-y2ayw_1  |   time_this_iter_s: 1.3484764099121094
algo-1-y2ayw_1  |   time_total_s: 4.55129861831665
algo-1-y2ayw_1  |   timestamp: 1568116273
algo-1-y2ayw_1  |   timesteps_since_restore: 463
algo-1-y2ayw_1  |   timesteps_this_iter: 234
algo-1-y2ayw_1  |   timesteps_total: 463
algo-1-y2ayw_1  |   training_iteration: 2
algo-1-y2ayw_1  |
algo-1-y2ayw_1  | A worker died or was killed while executing task 00000000781a7b5b94a203683f8f789e593abbb1.
algo-1-y2ayw_1  | A worker died or was killed while executing task 00000000d3507bc6b41ee1c9fc36292eeae69557.
algo-1-y2ayw_1  | == Status ==
algo-1-y2ayw_1  | Using FIFO scheduling algorithm.
algo-1-y2ayw_1  | Resources requested: 0/3 CPUs, 0/0 GPUs
algo-1-y2ayw_1  | Result logdir: /opt/ml/output/intermediate/training
algo-1-y2ayw_1  | TERMINATED trials:
algo-1-y2ayw_1  |  - PPO_ArrivalSim-v0_0:   TERMINATED [pid=77], 4 s, 2 iter, 463 ts, 2.96e+03 rew
algo-1-y2ayw_1  |
algo-1-y2ayw_1  | Saved model configuration.
algo-1-y2ayw_1  | Saved the checkpoint file /opt/ml/output/intermediate/training/PPO_ArrivalSim-v0_0_2019-09-10_11-50-53vd32vlux/checkpoint-2.extra_data as /opt/ml/model/checkpoint.extra_data
algo-1-y2ayw_1  | Saved the checkpoint file /opt/ml/output/intermediate/training/PPO_ArrivalSim-v0_0_2019-09-10_11-50-53vd32vlux/checkpoint-2.tune_metadata as /opt/ml/model/checkpoint.tune_metadata
algo-1-y2ayw_1  | Created LogSyncer for /root/ray_results/PPO_ArrivalSim-v0_2019-09-10_11-51-13xdn_5i34 -> None
algo-1-y2ayw_1  | 2019-09-10 11:51:13.941718: I tensorflow/core/common_runtime/process_util.cc:71] Creating new thread pool with default inter op setting: 2. Tune using inter_op_parallelism_threads for best performance.
algo-1-y2ayw_1  | reset -> (self.price).shape =  (1,)
algo-1-y2ayw_1  | LocalMultiGPUOptimizer devices ['/cpu:0']
algo-1-y2ayw_1  | reset -> (self.price).shape =  (1,)
algo-1-y2ayw_1  | INFO:tensorflow:No assets to save.
algo-1-y2ayw_1  | No assets to save.
algo-1-y2ayw_1  | INFO:tensorflow:No assets to write.
algo-1-y2ayw_1  | No assets to write.
algo-1-y2ayw_1  | INFO:tensorflow:SavedModel written to: /opt/ml/model/1/saved_model.pb
algo-1-y2ayw_1  | SavedModel written to: /opt/ml/model/1/saved_model.pb
algo-1-y2ayw_1  | Saved TensorFlow serving model!
algo-1-y2ayw_1  | A worker died or was killed while executing task 00000000f352d985b807ca399460941fe2264899.

algo-1-y2ayw_1  | 2019-09-10 11:51:20,075 sagemaker-containers INFO

 Reporting training SUCCESS

tmpwwb4b358_algo-1-y2ayw_1 exited with code 0

Aborting on container exit...
Failed to delete: /tmp/tmpwwb4b358/algo-1-y2ayw Please remove it manually.

===== Job Complete =====

На этот раз я редактирую все 3 файла. Ваша среда, сценарий обучения и записная книжка Jupyter, но оказывается, что нет необходимости определять пользовательские модели для вашей пользовательской среды. Однако это остается жизнеспособным. И вы правы, основная причина проблемы все еще находится в космосе.

Я установил self.price как одномерный массив numpy, чтобы он лучше взаимодействовал с Ray RLlib. Создание настраиваемой среды в обучающем сценарии было выполнено более простым способом, как показано ниже. Что касается ноутбука, я использовал версию 0.5.3 вместо 0.6.5 для toolkit_version, и обучение выполняется в локальном режиме (в контейнере докеров на экземпляре ноутбука Sagemaker Jupyter, все еще на AWS) только с ЦП. Однако он также будет работать с любым экземпляром ML (например, ml.m4.xlarge) с графическим процессором.

Весь пакет вместе со всеми зависимостями находится здесь.

Отредактированный env:

# new
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
# end new


from enum import Enum
import math

import gym
from gym import error, spaces, utils, wrappers
from gym.utils import seeding
from gym.envs.registration import register
from gym.spaces import Discrete, Box

import numpy as np


def sigmoid_price_fun(x, maxcust, gamma):
    return maxcust / (1 + math.exp(gamma * max(0, x)))


class Actions(Enum):
    DECREASE_PRICE = 0
    INCREASE_PRICE = 1
    HOLD = 2


PRICE_ADJUSTMENT = {
    Actions.DECREASE_PRICE: -0.25,
    Actions.INCREASE_PRICE: 0.25,
    Actions.HOLD: 0
}


class ArrivalSim(gym.Env):
    """ Simple environment for price optimising RL learner. """

    def __init__(self, price):
        """
        Parameters
        ----------
        price : float
            The initial price to use.
        """
        super().__init__()

        self.price = price
        self.revenue = 0
        self.action_space = Discrete(3)  # [0, 1, 2]  #increase or decrease
        # original obs space:
        #self.observation_space = Box(0.0, 1000.0, shape=(1,1), dtype=np.float32)
        # obs space initially suggested:
        #self.observation_space = Box(0.0, 1000.0, shape=(1,1), dtype=np.float32)
        # obs space suggested in this edit:
        self.observation_space = spaces.Box(np.array([0.0]), np.array([1000.0]), dtype=np.float32)

    def step(self, action):
        """ Enacts the specified action in the environment.

        Returns the new price, reward, whether we're finished and an empty dict for compatibility with Gym's
        interface. """

        self._take_action(Actions(action))

        next_state = self.price
        print('(self.price).shape =', (self.price).shape)
        #next_state = self.observation_space.sample()

        reward = self._get_reward()
        done = False

        if next_state < 0 or reward == 0:
            done = True

        print(next_state, reward, done, {})

        return np.array(next_state), reward, done, {}

    def reset(self):
        """ Resets the environment, selecting a random initial price. Returns the price. """
        #self.observation_space.value = np.random.rand()
        #return self.observation_space.sample()

        self.price = np.random.rand(1)

        print('reset -> (self.price).shape = ', (self.price).shape)

        return self.price

    def _take_action(self, action):
#         self.observation_space.value += PRICE_ADJUSTMENT[action]
        #print('price b =', self.price)
        print('price b =', self.price[0])
        #print('price b =', self.price[[0]])
        #self.price += PRICE_ADJUSTMENT[action]
        self.price[0] += PRICE_ADJUSTMENT[action]
        #self.price[[0]] += PRICE_ADJUSTMENT[action]
        #print('price a =', self.price)
        print('price a =', self.price[0])
        #print('price a =', self.price[[0]])

    #def _get_reward(self, price):
    def _get_reward(self):
#         price = self.observation_space.value
#         return max(np.random.poisson(sigmoid_price_fun(price, 50, 0.5)) * price, 0)
        #self.revenue = max(np.random.poisson(sigmoid_price_fun(self.price, 50, 0.5)) * self.price, 0)
        #return max(np.random.poisson(sigmoid_price_fun(self.price, 50, 0.5)) * self.price, 0)
        self.revenue = max(np.random.poisson(sigmoid_price_fun(self.price[0], 50, 0.5)) * self.price[0], 0)
        return max(np.random.poisson(sigmoid_price_fun(self.price[0], 50, 0.5)) * self.price[0], 0)

#     def render(self, mode='human'):
#         super().render(mode)

def testEnv():
    """
    register(
        id='ArrivalSim-v0',
        entry_point='env:ArrivalSim',
        kwargs= {'price' : 40.0}
    )
    env = gym.make('ArrivalSim-v0')
    """
    env = ArrivalSim(30.0)

    val = env.reset()
    print('val.shape = ', val.shape)

    for _ in range(5):
        print('env.observation_space =', env.observation_space)
        act = env.action_space.sample()
        print('\nact =', act)
        next_state, reward, done, _ = env.step(act)  # take a random action
        print('next_state = ', next_state)
    env.close()



if __name__ =='__main__':

    testEnv()

Отредактированный сценарий обучения:

import json
import os

import gym
import ray
from ray.tune import run_experiments
import ray.rllib.agents.a3c as a3c
import ray.rllib.agents.ppo as ppo
from ray.tune.registry import register_env
from mod_op_env import ArrivalSim

from sagemaker_rl.ray_launcher import SageMakerRayLauncher

"""
def create_environment(env_config):
    import gym
#     from gym.spaces import Space
    from gym.envs.registration import register

    # This import must happen inside the method so that worker processes import this code
    register(
        id='ArrivalSim-v0',
        entry_point='env:ArrivalSim',
        kwargs= {'price' : 40}
    )
    return gym.make('ArrivalSim-v0')
"""
def create_environment(env_config):
    price = 30.0
    # This import must happen inside the method so that worker processes import this code
    from mod_op_env import ArrivalSim
    return ArrivalSim(price)


class MyLauncher(SageMakerRayLauncher):
    def __init__(self):        
        super(MyLauncher, self).__init__()
        self.num_gpus = int(os.environ.get("SM_NUM_GPUS", 0))
        self.hosts_info = json.loads(os.environ.get("SM_RESOURCE_CONFIG"))["hosts"]
        self.num_total_gpus = self.num_gpus * len(self.hosts_info)

    def register_env_creator(self):
        register_env("ArrivalSim-v0", create_environment)

    def get_experiment_config(self):
        return {
          "training": {
            "env": "ArrivalSim-v0",
            "run": "PPO",
            "stop": {
              "training_iteration": 3,
            },

            "local_dir": "/opt/ml/model/",
            "checkpoint_freq" : 3,

            "config": {                                
              #"num_workers": max(self.num_total_gpus-1, 1),
              "num_workers": max(self.num_cpus-1, 1),
              #"use_gpu_for_workers": False,
              "train_batch_size": 128, #5,
              "sample_batch_size": 32, #1,
              "gpu_fraction": 0.3,
              "optimizer": {
                "grads_per_step": 10
              },
            },
            #"trial_resources": {"cpu": 1, "gpu": 0, "extra_gpu": max(self.num_total_gpus-1, 1), "extra_cpu": 0},
            #"trial_resources": {"cpu": 1, "gpu": 0, "extra_gpu": max(self.num_total_gpus-1, 0),
            #                    "extra_cpu": max(self.num_cpus-1, 1)},
            "trial_resources": {"cpu": 1,
                                "extra_cpu": max(self.num_cpus-1, 1)},              
          }
        }

if __name__ == "__main__":
    os.environ["LC_ALL"] = "C.UTF-8"
    os.environ["LANG"] = "C.UTF-8"
    os.environ["RAY_USE_XRAY"] = "1"
    print(ppo.DEFAULT_CONFIG)
    MyLauncher().train_main()

Код записной книжки:

!/bin/bash ./setup.sh

from time import gmtime, strftime
import sagemaker 
role = sagemaker.get_execution_role()

sage_session = sagemaker.session.Session()
s3_bucket = sage_session.default_bucket()  
s3_output_path = 's3://{}/'.format(s3_bucket)
print("S3 bucket path: {}".format(s3_output_path))

job_name_prefix = 'ArrivalSim'

from sagemaker.rl import RLEstimator, RLToolkit, RLFramework

estimator = RLEstimator(entry_point="mod_op_train.py", # Our launcher code
                        source_dir='src', # Directory where the supporting files are at. All of this will be
                                          # copied into the container.
                        dependencies=["common/sagemaker_rl"], # some other utils files.
                        toolkit=RLToolkit.RAY, # We want to run using the Ray toolkit against the ray container image.
                        framework=RLFramework.TENSORFLOW, # The code is in tensorflow backend.
                        toolkit_version='0.5.3', # Toolkit version. This will also choose an apporpriate tf version.                                               
                        #toolkit_version='0.6.5', # Toolkit version. This will also choose an apporpriate tf version.                        
                        role=role, # The IAM role that we created at the begining.
                        #train_instance_type="ml.m4.xlarge", # Since we want to run fast, lets run on GPUs.
                        train_instance_type="local", # Since we want to run fast, lets run on GPUs.
                        train_instance_count=1, # Single instance will also work, but running distributed makes things 
                                                # fast, particularly in the case of multiple rollout training.
                        output_path=s3_output_path, # The path where we can expect our trained model.
                        base_job_name=job_name_prefix, # This is the name we setup above to be to track our job.
                        hyperparameters = {      # Some hyperparameters for Ray toolkit to operate.
                          "s3_bucket": s3_bucket,
                          "rl.training.stop.training_iteration": 2, # Number of iterations.
                          "rl.training.checkpoint_freq": 2,
                        },
                        #metric_definitions=metric_definitions, # This will bring all the logs out into the notebook.
                    )

estimator.fit()
person Huan    schedule 02.09.2019
comment
Спасибо за вашу помощь, я попробовал это и только что получил еще одну проблему со стеком. python ValueError: No default configuration for obs shape [1, 1], you must specify `conv_filters` manually as a model option. Default configurations are only available for inputs of shape [42, 42, K] and [84, 84, K]. You may alternatively want to use a custom model or preprocessor. Мне не нужны фильтры свертки, поскольку в моей среде нет вывода изображений - person Rishan; 03.09.2019
comment
Я думаю, что проблема определенно связана с формами среды и нейронной сети. Я также пробовал использовать Coach с MXNET, но даже до сих пор не было ясно, как изменить формы. С Coach это было даже немного проще, так как мы могли вручную определить график, но до сих пор нет достаточной документации о том, как выровнять среду и агент. - person Rishan; 03.09.2019
comment
Привет ты прав Похоже, что RLlib по умолчанию использует свою конвективную модель. Обратите внимание, что RLlib, который вы используете, использует устаревшую версию visionnet_v1.py (строка 84), которая вызывает новую ошибку. Я не вижу сообщения об ошибке в более новой версии visionnet_v2.py - person Huan; 03.09.2019
comment
Предположим, вы не обновляете свою RLlib (я сомневаюсь, что это решит вашу проблему). Предложение разработчика RLlib, задокументированное здесь, заключается в использовании пользовательской модели, заставляя RLlib для использования fcnet. Это то, что я сделал для своей пользовательской среды MARL работает с сырым RLlib (не с Sagemaker). - person Huan; 03.09.2019
comment
Я отредактировал ваш обучающий сценарий, чтобы включить пользовательскую модель, как описано здесь. Может, тебе стоит попробовать запустить его. См. Раздел редактирования выше. - person Huan; 03.09.2019
comment
Хуан, спасибо, я внес твои правки. Однако, похоже, есть некоторые действительно раздражающие проблемы с модулями и импортом версий. python ModuleNotFoundError: No module named 'ray.rllib.models.tf' Я сталкивался с этой проблемой раньше и не могу найти решение. - person Rishan; 04.09.2019
comment
Я изучу ваш пример среды MARL. В очередной раз благодарим за помощь - person Rishan; 04.09.2019
comment
Привет, после нескольких дней изучения Sagemaker мне удалось запустить ваш пользовательский env на AWS Sagemaker с экземпляром ноутбука Jupyter. См. ИЗМЕНИТЬ 2 выше. Если вы нашли мой ответ полезным, примите его и проголосуйте за него. Спасибо. - person Huan; 10.09.2019
comment
Хуан, спасибо вам большое. Я только что вернулся из отпуска и проверю, как он работает. Сходится ли алгоритм PPO? Я пытался использовать DQN. Я решил перейти на тренерскую работу, но у меня та же проблема. Я тоже собираюсь задать вопрос по этому поводу, и, может быть, вы тоже можете мне с этим помочь? - person Rishan; 18.09.2019
comment
Привет, я не могу точно сказать, будет ли агент PPO обучаться в вашей пользовательской среде, поскольку я выполнил только 2 взаимодействия (~ 400 + t шагов) в SageMaker. Я расширил приведенный выше усеченный вывод, включив в него сводку результатов RLlib. См. Под Result for PPO_ArrivalSim-v0_0: в выводе в EDIT 2 выше. Одно можно сказать наверняка: теперь ваш пользовательский env работает в sagemaker. - person Huan; 18.09.2019
comment
Я не могу комментировать выбор инструментария RL, коуча или RLlib, действительно зависит от личных предпочтений. Что касается алгоритма, я думаю, что DQN будет достаточно, поскольку вы используете пространство дискретных действий в своем env. RLlib также имеет DQN, в значительной степени стандартный алгоритм в большинстве инструментов RL. Что касается тех же проблем в Coach, вы имеете в виду, что вы не можете запустить свой env в sagemaker с Coin или алгоритм DQN из Coach не сходится для вашего env? Если вы зададите еще один вопрос по этому поводу, я могу изучить его. - person Huan; 18.09.2019
comment
Да, я вполне уверен в использовании DQN или даже QRDQN. Просто мои знания о фреймворке ограничены, а документация не так уж и хороша! Я надеюсь, что скоро опубликую вопрос о Ray и свяжу вас с ним - person Rishan; 19.09.2019
comment
Я пытаюсь сообщить вам напрямую о вашем решении, вы знаете, как это сделать? - person Rishan; 19.09.2019
comment
Также в отношении проблемы, с которой я столкнулся с тренером - это то же самое в том смысле, что формы не совпадают, и я не знаю, что с этим делать. - person Rishan; 19.09.2019
comment
Привет, полностью согласен, что документацию можно написать лучше. Отредактированные коды (1D array ops space) работают у вас на sagemaker? Если это так, пожалуйста, примите и проголосуйте. Вопросы, касающиеся выбора алгоритма (или сходимости), действительно выходят за рамки этого вопроса, и я, возможно, не лучший человек, чтобы на них ответить. Я не думаю, что в stackoverflow есть встроенная система обмена сообщениями (это хорошая функция, которую они действительно должны иметь). - person Huan; 19.09.2019
comment
Я заметил в своем репозитории MARL, что я сглаживал свое многомерное пространство (тренажерный зал) obs до 1D перед обработкой в ​​пользовательской модели нейронной сети в моих кодах. Может быть, поэтому он работает в RLlib, но точно сказать не могу. - person Huan; 19.09.2019
comment
К вашему сведению, я открыл проблему с awslabs относительно их поддержки в ray 0.6.5 (это одна из официальных поддерживаемых версий, кроме 0.5.3). Если вам интересно, вот ссылка. - person Huan; 19.09.2019
comment
Хуан, пока мне не удалось заставить его работать с моей настройкой Ray, я загрузил ваш файл git и заставил его работать ... не только то, что вы сделали с моей средой, заставило его работать с коучем. Я не уверен, что именно вы сделали, чтобы преобразовать его в одномерный массив. Это как-то связано с `` self.price [0] `` ` - person Rishan; 20.09.2019
comment
Привет, да, изначально пространство операций self.price - это Box с типом float, я просто меняю его на Box с 1D-массивом типа float32. Для всех изменений кода, будь то env, обучающий скрипт или записная книжка, я оставил ваш исходный код прокомментированным на случай, если они вам понадобятся. Я рад, что они у вас работают, и спасибо, что приняли ответ. - person Huan; 20.09.2019