def train(sess, env, actor, critic, noise, reward, discrete, saver,
          checkpoint_path):
    # Set up summary writer
    summary_writer = tf.summary.FileWriter("ddpg_summary")

    actor.update()
    critic.update()

    replay_buffer = ReplayBuffer(BUFFER_SIZE, RANDOM_SEED)

    # Initialize noise
    ou_level = 0.

    for i in range(MAX_EPISODES):

        if i % 100 == 0:
            saver.save(sess, checkpoint_path)

        # s 는 environment에서 제공하는 첫번째 state 정보.
        s = env.reset()

        ep_reward = 0
        ep_ave_max_q = 0

        # buffer 초기화
        episode_buffer = np.empty((0, 5), float)

        for j in range(MAX_EP_STEPS):

            # print(critic.w1.eval()[0,0])

            env.render()

            # a 는 actor의 current policy를 기반으로 예측한 q_value tensor [None x action_dim]
            a = actor.predict(np.reshape(s, (1, actor.state_dim)))

            # stochastic environment에서의 e-greedy 를 위해서
            # Noise 를 추가한다.
            # 아랫 부분은 ornstein_uhlenbeck_level이라는 내용을 참조해야 합니다.. constant action space에서
            # 학습을 위해서 사용하는 방법이라고 합니다.
            if i < NOISE_MAX_EP:
                ou_level = noise.ornstein_uhlenbeck_level(ou_level)
                a = a + ou_level

                # Set action for discrete and continuous action spaces
            if discrete:
                action = np.argmax(a)
            else:
                action = a[0]

            # 선택된 action을 기반으로 step을 진행시킨 후 결과를
            # 돌려받습니다.
            s2, r, terminal, info = env.step(action)

            # episode 내의 총 reward 값을 더합니다.
            ep_reward += r

            # ==========================================================================[중요한 부분]==============
            # Replay Buffer에 해당 정보를 더합니다.
            # episode_buffer라는 nparray에 [s, a, r, terminal, s2]의 배열을 넣어줍니다.
            episode_buffer = np.append(episode_buffer,
                                       [[s, a, r, terminal, s2]],
                                       axis=0)
            # ===================================================================================================

            # Replay Buffer에 Minibatch size 이상의 데이터가 담겨 있다면
            # 데이터를 가져와서 학습을 진행합니다.
            if replay_buffer.size() > MINIBATCH_SIZE:
                s_batch, a_batch, r_batch, t_batch, s2_batch = \
                    replay_buffer.sample_batch(MINIBATCH_SIZE)

                # critic을 통해서 Q(s, a)인 action-value function을 가져옵니다.
                # 이때 critic은 current policy를 평가하고 action-value function을 학습하므로,
                # actor의 예측 값을 가져옵니다.
                target_q = critic.predict_target(
                    s2_batch, actor.predict_target(s2_batch))

                y_i = []
                for k in range(MINIBATCH_SIZE):
                    if t_batch[k]:
                        y_i.append(r_batch[k])
                    else:
                        y_i.append(r_batch[k] + GAMMA * target_q[k])

                # Critic이 가진 action_value function을 학습합니다.
                # 이때 필요한 데이터는 state batch, action batch, reward batch 입니다.
                # reward는 DQN (deepmind etc...) 논문에서 사용했던 것 과 같이
                # terminal 이라면 마지막 reward 자체.
                # terminal이 아니라면, s2 에서의 q_value 값에 discount factor를 곱한 값과 s 에서의 reward를 더한 값을
                # reward로 계사합니다.
                predicted_q_value, _ = critic.train(
                    s_batch, a_batch, np.reshape(y_i, (MINIBATCH_SIZE, 1)))

                # 모델의 성능 측정을 위해서 average Q 값을 확인합니다.
                # DQN (deepmind etc..) 논문에서 강화학습 모델의 진행도를 측정하기 위한 좋은
                # 지표로서 언급하였습니다.
                ep_ave_max_q += np.amax(predicted_q_value)

                # replay buffer에서 가져온 state_batch를 사용해서 actor의 current policy에 해당하는
                # q_value를 가져옵니다.
                # current_policy에 따른 q_value를 state 정보와 함께 넣어
                # Q(s, a)를 계산합니다 by critic
                a_outs = actor.predict(s_batch)
                grads = critic.action_gradients(s_batch, a_outs)

                # grads 는 (1, BATCH_SIZE, ACTION_DIM) 의 배열이므로
                # (BATCH_SIZE, ACTION_DIM)의 입력을 받는 actor.train 함수를 위해서 grads[0]을 취합니다.
                # actor의 policy를 업데이트 하기 위해서 critic의 gradients를 받아와서 train합니다.
                actor.train(s_batch, grads[0])

                # actor와 critic network 모두 업데이트 합니다.
                actor.update()
                critic.update()

            # s2 를 s 로 바꾸어 진행합니다.
            s = s2

            if terminal:

                episode_buffer = reward.discount(episode_buffer)

                # Add episode to replay buffer
                for step in episode_buffer:
                    replay_buffer.add(
                        np.reshape(step[0], (actor.state_dim, )),
                        np.reshape(step[1], (actor.action_dim, )), step[2],
                        step[3], np.reshape(step[4], (actor.state_dim, )))

                summary = tf.Summary()
                summary.value.add(tag='Perf/Reward',
                                  simple_value=float(ep_reward))
                summary.value.add(tag='Perf/Qmax',
                                  simple_value=float(ep_ave_max_q / float(j)))
                summary_writer.add_summary(summary, i)

                summary_writer.flush()

                print('| Reward: %.2i' % int(ep_reward), " | Episode", i,
                      '| Qmax: %.4f' % (ep_ave_max_q / float(j)))

                break
예제 #2
0
class Agent():
    def __init__(self):
        self.name = "expected_sarsa_agent"

    def agent_init(self, agent_config):
        self.replay_buffer = ReplayBuffer(agent_config['replay_buffer_size'],
                                          agent_config['minibatch_sz'],
                                          agent_config.get("seed"))
        self.network = ActionValueNetwork(agent_config['network_config'])
        self.optimizer = Adam(self.network.layer_sizes,
                              agent_config["optimizer_config"])
        self.num_actions = agent_config['network_config']['num_actions']
        self.num_replay = agent_config['num_replay_updates_per_step']
        self.discount = agent_config['gamma']
        self.tau = agent_config['tau']

        self.rand_generator = np.random.RandomState(agent_config.get("seed"))

        self.last_state = None
        self.last_action = None

        self.sum_rewards = 0
        self.episode_steps = 0

    def policy(self, state):
        action_values = self.network.get_action_values(state)
        probs_batch = softmax(action_values, self.tau)
        action = self.rand_generator.choice(self.num_actions,
                                            p=probs_batch.squeeze())
        return action

    def agent_start(self, state):
        self.sum_rewards = 0
        self.episode_steps = 0
        self.last_state = np.array([state])
        self.last_action = self.policy(self.last_state)
        return self.last_action

    def agent_step(self, reward, state):
        self.sum_rewards += reward
        self.episode_steps += 1

        state = np.array([state])

        action = self.policy(state)

        self.replay_buffer.append(self.last_state, self.last_action, reward, 0,
                                  state)

        # Perform replay steps:
        if self.replay_buffer.size() > self.replay_buffer.minibatch_size:
            current_q = deepcopy(self.network)
            for _ in range(self.num_replay):

                # Get sample experiences from the replay buffer
                experiences = self.replay_buffer.sample()

                # Call optimize_network to update the weights of the network
                optimize_network(experiences, self.discount, self.optimizer,
                                 self.network, current_q, self.tau)

        # Update the last state and last action.
        self.last_state = state
        self.last_action = action

        return action

    # update of the weights using optimize_network
    def agent_end(self, reward):
        self.sum_rewards += reward
        self.episode_steps += 1

        # Set terminal state to an array of zeros
        state = np.zeros_like(self.last_state)

        # Append new experience to replay buffer
        self.replay_buffer.append(self.last_state, self.last_action, reward, 1,
                                  state)

        # Perform replay steps:
        if self.replay_buffer.size() > self.replay_buffer.minibatch_size:
            current_q = deepcopy(self.network)
            for _ in range(self.num_replay):

                # Get sample experiences from the replay buffer
                experiences = self.replay_buffer.sample()

                # Call optimize_network to update the weights of the network
                optimize_network(experiences, self.discount, self.optimizer,
                                 self.network, current_q, self.tau)

    def agent_message(self, message):
        if message == "get_sum_reward":
            return self.sum_rewards
        else:
            raise Exception("Unrecognized Message!")