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
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!")