Почему средняя награда за эпизод остается постоянной +100 во время тренировки? - PullRequest
0 голосов
/ 01 мая 2020

Я хочу создать класс обратного вызова, который будет проверять каждые 200 шагов обучения, увеличилось ли среднее награда за эпизод в модели и, если это так, сохраняет его. Я знаю, что в библиотеке stable-baselines уже существует класс EvalCallback(), но я пытаюсь закодировать свой собственный обратный вызов.

Я застрял в этой точке, где мой вывод показывает среднее значение награды за серию модели не go за 100. Почему это? Это происходит при каждом запуске.

Это мой код:

class EvalCallback(BaseCallback):
  """
  Callback for evaluating an agent.

  :param eval_env: (gym.Env) The environment used for initialization
  :param n_eval_episodes: (int) The number of episodes to test the agent
  :param eval_freq: (int) Evaluate the agent every eval_freq call of the callback.
  """
  def __init__(self, eval_env, n_eval_episodes=5, eval_freq=200, verbose=1):
    super(EvalCallback, self).__init__(verbose)
    self.eval_env = eval_env
    self.n_eval_episodes = n_eval_episodes
    self.eval_freq = eval_freq
    self.best_mean_reward = -np.inf
    self.save_path = os.path.join(log_dir, 'exercise_best_model')

  def _on_step(self) -> bool:
    """
    This method will be called by the model.

    :return: (bool)
    """
    # self.n_calls is automatically updated because
    # we derive from BaseCallback
    if self.n_calls % self.eval_freq == 0:
      # Evaluate the agent:
      done = False
      all_episode_rewards = []
      obs = self.eval_env.reset()
      for _ in range(self.n_eval_episodes):
        episode_rewards = []
        while not done:
          action, _states = self.model.predict(obs, deterministic=True)
          obs, reward, done, info = self.eval_env.step(action)
          episode_rewards.append(reward)
        all_episode_rewards.append(sum(episode_rewards))
      # Save the agent if needed
      # and update self.best_mean_reward
      mean_reward = np.mean(all_episode_rewards)
      if mean_reward > self.best_mean_reward:
        self.best_mean_reward = mean_reward
        self.model.save(self.save_path)
        if self.verbose > 0:
          print("Best mean reward: {:.2f}".format(self.best_mean_reward))
          print("Saving new best model to {}.zip".format(self.save_path))
          print('-' * 30)        
      # ====================== #    
    return True

И вот как я инициализирую env и модель:

# Env used for training
env = gym.make("CartPole-v1")
# Env for evaluating the agent
eval_env = gym.make("CartPole-v1")

# Create the callback object
callback = EvalCallback(eval_env, verbose=1)

# Create the RL model
model = PPO2('MlpPolicy', env, verbose=0)

# Train the RL model
model.learn(100000, callback=callback)

Вывод такой:

Best mean reward: 13.80
Saving new best model to /tmp/gym/exercise_best_model.zip
------------------------------
Best mean reward: 18.20
Saving new best model to /tmp/gym/exercise_best_model.zip
------------------------------
Best mean reward: 20.80
Saving new best model to /tmp/gym/exercise_best_model.zip
------------------------------
Best mean reward: 100.00
Saving new best model to /tmp/gym/exercise_best_model.zip
------------------------------
<stable_baselines.ppo2.ppo2.PPO2 at 0x7f1c15095438>

РЕДАКТИРОВАТЬ:

Я попробовал другую реализацию. В этом случае лучшая средняя награда модели составляет 500,00. Насколько мне известно, функция evaluate_policy() работает так же, как моя реализация выше, но, очевидно, это не может быть правдой.

## 2nd IMPLEMENTATION
## -------------------
class EvalCallback(BaseCallback):
  """
  Callback for evaluating an agent.

  :param eval_env: (gym.Env) The environment used for initialization
  :param n_eval_episodes: (int) The number of episodes to test the agent
  :param eval_freq: (int) Evaluate the agent every eval_freq call of the callback.
  """
  def __init__(self, eval_env, n_eval_episodes=5, eval_freq=200, verbose=1):
    super(EvalCallback, self).__init__(verbose)
    self.eval_env = eval_env
    self.n_eval_episodes = n_eval_episodes
    self.eval_freq = eval_freq
    self.best_mean_reward = -np.inf
    self.save_path = os.path.join(log_dir, 'exercise_best_model')

  def _on_step(self) -> bool:
    """
    This method will be called by the model.

    :return: (bool)
    """
    # self.n_calls is automatically updated because
    # we derive from BaseCallback
    if self.n_calls % self.eval_freq == 0:
      episode_rewards, episode_lengths = evaluate_policy(self.model, self.eval_env,
                                                         n_eval_episodes=self.n_eval_episodes,
                                                         deterministic=True,
                                                         return_episode_rewards=True)
      mean_reward = np.mean(episode_rewards)
      # Save the agent if needed
      # and update self.best_mean_reward
      if mean_reward > self.best_mean_reward:
        self.best_mean_reward = mean_reward
        self.model.save(self.save_path)
        if self.verbose > 0:
          print("Best mean reward: {:.2f}".format(self.best_mean_reward))
          print("Saving new best model to {}.zip".format(self.save_path))
          print('-' * 30)        
    return True
...