shared_buffer.py
MAPPO 对照 buffer
原文件 · 588 行 · 31775 字节
utils/shared_buffer.py
SHA-256: c9cf6f5ed3efae47653e39a506f87531a2aaabacd7df6299be71793c9d77e430
1import torch2import numpy as np3from utils.util import get_shape_from_obs_space, get_shape_from_act_space4from utils.obs_utils import POLICY_OBS_KEYS567def _flatten(T, N, x):8 return x.reshape(T * N, *x.shape[2:])91011def _cast(x):12 return x.transpose(1, 2, 0, *range(3, x.ndim)).reshape(-1, *x.shape[3:])131415def _normalize_shape(shape):16 if type(shape[-1]) == list:17 return shape[:1]18 return shape192021def _main_obs_shape(obs_shape):22 if isinstance(obs_shape, dict):23 return (int(sum(np.prod(obs_shape[k]) for k in POLICY_OBS_KEYS)),)24 return _normalize_shape(obs_shape)252627class SharedReplayBuffer(object):28 """29 Buffer to store training data.30 :param args: (argparse.Namespace) arguments containing relevant model, policy, and env information.31 :param num_agents: (int) number of agents in the env.32 :param obs_space: (gym.Space) observation space of agents.33 :param cent_obs_space: (gym.Space) centralized observation space of agents.34 :param act_space: (gym.Space) action space for agents.35 """3637 def __init__(self, args, num_agents, obs_space, cent_obs_space, act_space):38 self.episode_length = args.episode_length39 self.n_rollout_threads = args.n_rollout_threads40 self.hidden_size = args.hidden_size41 self.recurrent_N = args.recurrent_N42 self.gamma = args.gamma43 self.gae_lambda = args.gae_lambda44 self._use_gae = args.use_gae45 self._use_popart = args.use_popart46 self._use_valuenorm = args.use_valuenorm47 self._use_proper_time_limits = args.use_proper_time_limits4849 obs_shape_dict = get_shape_from_obs_space(obs_space) # dict for Dict space50 share_obs_shape = get_shape_from_obs_space(cent_obs_space)5152 if isinstance(share_obs_shape, dict):53 self.share_obs = {54 k: np.zeros(55 (self.episode_length + 1, self.n_rollout_threads, num_agents, *_normalize_shape(v)),56 dtype=np.float32,57 )58 for k, v in share_obs_shape.items()59 }60 else:61 share_obs_shape = _main_obs_shape(share_obs_shape)62 self.share_obs = np.zeros(63 (self.episode_length + 1, self.n_rollout_threads, num_agents, *share_obs_shape),64 dtype=np.float32,65 )66 if isinstance(obs_shape_dict, dict):67 self.obs = {68 k: np.zeros((self.episode_length + 1, self.n_rollout_threads, num_agents, *_normalize_shape(v)),69 dtype=np.float32)70 for k, v in obs_shape_dict.items()71 }72 else:73 obs_shape = _normalize_shape(obs_shape_dict)74 self.obs = {75 "obs": np.zeros((self.episode_length + 1, self.n_rollout_threads, num_agents, *obs_shape),76 dtype=np.float32)77 }7879 self.rnn_states = np.zeros(80 (self.episode_length + 1, self.n_rollout_threads, num_agents, self.recurrent_N, self.hidden_size),81 dtype=np.float32)82 self.rnn_states_critic = np.zeros_like(self.rnn_states)8384 self.value_preds = np.zeros(85 (self.episode_length + 1, self.n_rollout_threads, num_agents, 1), dtype=np.float32)86 self.returns = np.zeros_like(self.value_preds)8788 # 为啥只有 Discrete 才有 available_actions ?给你注释了89 # if act_space.__class__.__name__ == 'Discrete':90 self.available_actions = np.ones((self.episode_length + 1, self.n_rollout_threads, num_agents, act_space.n),91 dtype=np.float32)92 # else:93 # self.available_actions = None9495 act_shape = get_shape_from_act_space(act_space)9697 self.actions = np.zeros(98 (self.episode_length, self.n_rollout_threads, num_agents, act_shape), dtype=np.float32)99 self.action_log_probs = np.zeros(100 (self.episode_length, self.n_rollout_threads, num_agents, act_shape), dtype=np.float32)101 self.rewards = np.zeros(102 (self.episode_length, self.n_rollout_threads, num_agents, 1), dtype=np.float32)103104 self.masks = np.ones((self.episode_length + 1, self.n_rollout_threads, num_agents, 1), dtype=np.float32)105 self.bad_masks = np.ones_like(self.masks)106 self.active_masks = np.ones_like(self.masks)107108 self.step = 0109110 def insert(self, share_obs, obs, rnn_states_actor, rnn_states_critic, actions, action_log_probs,111 value_preds, rewards, masks, agent_caps=None, task_reqs=None, bad_masks=None, active_masks=None, available_actions=None):112 """113 Insert data into the buffer.114 :param share_obs: (argparse.Namespace) arguments containing relevant model, policy, and env information.115 :param obs: (np.ndarray) local agent observations.116 :param rnn_states_actor: (np.ndarray) RNN states for actor network.117 :param rnn_states_critic: (np.ndarray) RNN states for critic network.118 :param actions:(np.ndarray) actions taken by agents.119 :param action_log_probs:(np.ndarray) log probs of actions taken by agents120 :param value_preds: (np.ndarray) value function prediction at each step.121 :param rewards: (np.ndarray) reward collected at each step.122 :param masks: (np.ndarray) denotes whether the environment has terminated or not.123 :param agent_caps: (np.ndarray) agent capabilities (unused in base buffer, used by GAT buffer).124 :param task_reqs: (np.ndarray) task requirements (unused in base buffer, used by GAT buffer).125 :param bad_masks: (np.ndarray) action space for agents.126 :param active_masks: (np.ndarray) denotes whether an agent is active or dead in the env.127 :param available_actions: (np.ndarray) actions available to each agent. If None, all actions are available.128 """129 if isinstance(self.share_obs, dict):130 for k in self.share_obs:131 self.share_obs[k][self.step + 1] = share_obs[k].copy()132 else:133 self.share_obs[self.step + 1] = share_obs.copy()134 for k in self.obs:135 self.obs[k][self.step + 1] = obs[k].copy()136 self.rnn_states[self.step + 1] = rnn_states_actor.copy()137 self.rnn_states_critic[self.step + 1] = rnn_states_critic.copy()138 self.actions[self.step] = actions.copy()139 self.action_log_probs[self.step] = action_log_probs.copy()140 self.value_preds[self.step] = value_preds.copy()141 self.rewards[self.step] = rewards.copy()142 self.masks[self.step + 1] = masks.copy()143 if bad_masks is not None:144 self.bad_masks[self.step + 1] = bad_masks.copy()145 if active_masks is not None:146 self.active_masks[self.step + 1] = active_masks.copy()147 if available_actions is not None:148 self.available_actions[self.step + 1] = available_actions.copy()149150 self.step = (self.step + 1) % self.episode_length151152 def chooseinsert(self, share_obs, obs, rnn_states, rnn_states_critic, actions, action_log_probs,153 value_preds, rewards, masks, bad_masks=None, active_masks=None, available_actions=None):154 """155 Insert data into the buffer. This insert function is used specifically for Hanabi, which is turn based.156 :param share_obs: (argparse.Namespace) arguments containing relevant model, policy, and env information.157 :param obs: (np.ndarray) local agent observations.158 :param rnn_states_actor: (np.ndarray) RNN states for actor network.159 :param rnn_states_critic: (np.ndarray) RNN states for critic network.160 :param actions:(np.ndarray) actions taken by agents.161 :param action_log_probs:(np.ndarray) log probs of actions taken by agents162 :param value_preds: (np.ndarray) value function prediction at each step.163 :param rewards: (np.ndarray) reward collected at each step.164 :param masks: (np.ndarray) denotes whether the environment has terminated or not.165 :param bad_masks: (np.ndarray) denotes indicate whether whether true terminal state or due to episode limit166 :param active_masks: (np.ndarray) denotes whether an agent is active or dead in the env.167 :param available_actions: (np.ndarray) actions available to each agent. If None, all actions are available.168 """169 if isinstance(self.share_obs, dict):170 for k in self.share_obs:171 self.share_obs[k][self.step] = share_obs[k].copy()172 else:173 self.share_obs[self.step] = share_obs.copy()174 for k in self.obs:175 self.obs[k][self.step] = obs[k].copy()176 self.rnn_states[self.step + 1] = rnn_states.copy()177 self.rnn_states_critic[self.step + 1] = rnn_states_critic.copy()178 self.actions[self.step] = actions.copy()179 self.action_log_probs[self.step] = action_log_probs.copy()180 self.value_preds[self.step] = value_preds.copy()181 self.rewards[self.step] = rewards.copy()182 self.masks[self.step + 1] = masks.copy()183 if bad_masks is not None:184 self.bad_masks[self.step + 1] = bad_masks.copy()185 if active_masks is not None:186 self.active_masks[self.step] = active_masks.copy()187 if available_actions is not None:188 self.available_actions[self.step] = available_actions.copy()189190 self.step = (self.step + 1) % self.episode_length191192 def after_update(self):193 """Copy last timestep data to first index. Called after update to model."""194 if isinstance(self.share_obs, dict):195 for k in self.share_obs:196 self.share_obs[k][0] = self.share_obs[k][-1].copy()197 else:198 self.share_obs[0] = self.share_obs[-1].copy()199 for k in self.obs:200 self.obs[k][0] = self.obs[k][-1].copy()201 self.rnn_states[0] = self.rnn_states[-1].copy()202 self.rnn_states_critic[0] = self.rnn_states_critic[-1].copy()203 self.masks[0] = self.masks[-1].copy()204 self.bad_masks[0] = self.bad_masks[-1].copy()205 self.active_masks[0] = self.active_masks[-1].copy()206 if self.available_actions is not None:207 self.available_actions[0] = self.available_actions[-1].copy()208209 def chooseafter_update(self):210 """Copy last timestep data to first index. This method is used for Hanabi."""211 self.rnn_states[0] = self.rnn_states[-1].copy()212 self.rnn_states_critic[0] = self.rnn_states_critic[-1].copy()213 self.masks[0] = self.masks[-1].copy()214 self.bad_masks[0] = self.bad_masks[-1].copy()215216 def compute_returns(self, next_value, value_normalizer=None):217 """218 Compute returns either as discounted sum of rewards, or using GAE.219 :param next_value: (np.ndarray) value predictions for the step after the last episode step.220 :param value_normalizer: (PopArt) If not None, PopArt value normalizer instance.221 """222 if self._use_proper_time_limits:223 if self._use_gae:224 self.value_preds[-1] = next_value225 gae = 0226 for step in reversed(range(self.rewards.shape[0])):227 if self._use_popart or self._use_valuenorm:228 # step + 1229 delta = self.rewards[step] + self.gamma * value_normalizer.denormalize(230 self.value_preds[step + 1]) * self.masks[step + 1] \231 - value_normalizer.denormalize(self.value_preds[step])232 gae = delta + self.gamma * self.gae_lambda * gae * self.masks[step + 1]233 gae = gae * self.bad_masks[step + 1]234 self.returns[step] = gae + value_normalizer.denormalize(self.value_preds[step])235 else:236 delta = self.rewards[step] + self.gamma * self.value_preds[step + 1] * self.masks[step + 1] - \237 self.value_preds[step]238 gae = delta + self.gamma * self.gae_lambda * self.masks[step + 1] * gae239 gae = gae * self.bad_masks[step + 1]240 self.returns[step] = gae + self.value_preds[step]241 else:242 self.returns[-1] = next_value243 for step in reversed(range(self.rewards.shape[0])):244 if self._use_popart or self._use_valuenorm:245 self.returns[step] = (self.returns[step + 1] * self.gamma * self.masks[step + 1] + self.rewards[246 step]) * self.bad_masks[step + 1] \247 + (1 - self.bad_masks[step + 1]) * value_normalizer.denormalize(248 self.value_preds[step])249 else:250 self.returns[step] = (self.returns[step + 1] * self.gamma * self.masks[step + 1] + self.rewards[251 step]) * self.bad_masks[step + 1] \252 + (1 - self.bad_masks[step + 1]) * self.value_preds[step]253 else:254 if self._use_gae:255 self.value_preds[-1] = next_value256 gae = 0257 for step in reversed(range(self.rewards.shape[0])):258 if self._use_popart or self._use_valuenorm:259 delta = self.rewards[step] + self.gamma * value_normalizer.denormalize(260 self.value_preds[step + 1]) * self.masks[step + 1] \261 - value_normalizer.denormalize(self.value_preds[step])262 gae = delta + self.gamma * self.gae_lambda * self.masks[step + 1] * gae263 self.returns[step] = gae + value_normalizer.denormalize(self.value_preds[step])264 else:265 delta = self.rewards[step] + self.gamma * self.value_preds[step + 1] * self.masks[step + 1] - \266 self.value_preds[step]267 gae = delta + self.gamma * self.gae_lambda * self.masks[step + 1] * gae268 self.returns[step] = gae + self.value_preds[step]269 else:270 self.returns[-1] = next_value271 for step in reversed(range(self.rewards.shape[0])):272 self.returns[step] = self.returns[step + 1] * self.gamma * self.masks[step + 1] + self.rewards[step]273274 def feed_forward_generator(self, advantages, num_mini_batch=None, mini_batch_size=None):275 """276 Yield training data for MLP policies.277 :param advantages: (np.ndarray) advantage estimates.278 :param num_mini_batch: (int) number of minibatches to split the batch into.279 :param mini_batch_size: (int) number of samples in each minibatch.280 """281 episode_length, n_rollout_threads, num_agents = self.rewards.shape[0:3]282 batch_size = n_rollout_threads * episode_length * num_agents283284 if mini_batch_size is None:285 assert batch_size >= num_mini_batch, (286 "PPO requires the number of processes ({}) "287 "* number of steps ({}) * number of agents ({}) = {} "288 "to be greater than or equal to the number of PPO mini batches ({})."289 "".format(n_rollout_threads, episode_length, num_agents,290 n_rollout_threads * episode_length * num_agents,291 num_mini_batch))292 mini_batch_size = batch_size // num_mini_batch293294 rand = torch.randperm(batch_size).numpy()295 sampler = [rand[i * mini_batch_size:(i + 1) * mini_batch_size] for i in range(num_mini_batch)]296297 if isinstance(self.share_obs, dict):298 share_obs = {299 k: v[:-1].reshape(-1, *v.shape[3:])300 for k, v in self.share_obs.items()301 }302 else:303 share_obs = self.share_obs[:-1].reshape(-1, *self.share_obs.shape[3:])304 obs = {305 k: v[:-1].reshape(-1, *v.shape[3:])306 for k, v in self.obs.items()307 }308 rnn_states = self.rnn_states[:-1].reshape(-1, *self.rnn_states.shape[3:])309 rnn_states_critic = self.rnn_states_critic[:-1].reshape(-1, *self.rnn_states_critic.shape[3:])310 actions = self.actions.reshape(-1, self.actions.shape[-1])311 if self.available_actions is not None:312 available_actions = self.available_actions[:-1].reshape(-1, self.available_actions.shape[-1])313 value_preds = self.value_preds[:-1].reshape(-1, 1)314 returns = self.returns[:-1].reshape(-1, 1)315 masks = self.masks[:-1].reshape(-1, 1)316 active_masks = self.active_masks[:-1].reshape(-1, 1)317 action_log_probs = self.action_log_probs.reshape(-1, self.action_log_probs.shape[-1])318 advantages = advantages.reshape(-1, 1)319320 for indices in sampler:321 # obs size [T+1 N M Dim]-->[T N M Dim]-->[T*N*M,Dim]-->[index,Dim]322 share_obs_batch = (323 {k: v[indices] for k, v in share_obs.items()}324 if isinstance(share_obs, dict)325 else share_obs[indices]326 )327 obs_batch = {k: v[indices] for k, v in obs.items()}328 rnn_states_batch = rnn_states[indices]329 rnn_states_critic_batch = rnn_states_critic[indices]330 actions_batch = actions[indices]331 if self.available_actions is not None:332 available_actions_batch = available_actions[indices]333 else:334 available_actions_batch = None335 value_preds_batch = value_preds[indices]336 return_batch = returns[indices]337 masks_batch = masks[indices]338 active_masks_batch = active_masks[indices]339 old_action_log_probs_batch = action_log_probs[indices]340 if advantages is None:341 adv_targ = None342 else:343 adv_targ = advantages[indices]344345 yield share_obs_batch, obs_batch, rnn_states_batch, rnn_states_critic_batch, actions_batch,\346 value_preds_batch, return_batch, masks_batch, active_masks_batch, old_action_log_probs_batch,\347 adv_targ, available_actions_batch348349 def naive_recurrent_generator(self, advantages, num_mini_batch):350 """351 Yield training data for non-chunked RNN training.352 :param advantages: (np.ndarray) advantage estimates.353 :param num_mini_batch: (int) number of minibatches to split the batch into.354 """355 episode_length, n_rollout_threads, num_agents = self.rewards.shape[0:3]356 batch_size = n_rollout_threads * num_agents357 assert n_rollout_threads * num_agents >= num_mini_batch, (358 "PPO requires the number of processes ({})* number of agents ({}) "359 "to be greater than or equal to the number of "360 "PPO mini batches ({}).".format(n_rollout_threads, num_agents, num_mini_batch))361 num_envs_per_batch = batch_size // num_mini_batch362 perm = torch.randperm(batch_size).numpy()363364 if isinstance(self.share_obs, dict):365 share_obs = {366 k: v.reshape(-1, batch_size, *v.shape[3:])367 for k, v in self.share_obs.items()368 }369 else:370 share_obs = self.share_obs.reshape(-1, batch_size, *self.share_obs.shape[3:])371 obs = {372 k: v.reshape(-1, batch_size, *v.shape[3:])373 for k, v in self.obs.items()374 }375 rnn_states = self.rnn_states.reshape(-1, batch_size, *self.rnn_states.shape[3:])376 rnn_states_critic = self.rnn_states_critic.reshape(-1, batch_size, *self.rnn_states_critic.shape[3:])377 actions = self.actions.reshape(-1, batch_size, self.actions.shape[-1])378 if self.available_actions is not None:379 available_actions = self.available_actions.reshape(-1, batch_size, self.available_actions.shape[-1])380 value_preds = self.value_preds.reshape(-1, batch_size, 1)381 returns = self.returns.reshape(-1, batch_size, 1)382 masks = self.masks.reshape(-1, batch_size, 1)383 active_masks = self.active_masks.reshape(-1, batch_size, 1)384 action_log_probs = self.action_log_probs.reshape(-1, batch_size, self.action_log_probs.shape[-1])385 advantages = advantages.reshape(-1, batch_size, 1)386387 for start_ind in range(0, batch_size, num_envs_per_batch):388 share_obs_batch = {k: [] for k in self.share_obs} if isinstance(self.share_obs, dict) else []389 obs_batch = {k: [] for k in self.obs}390 rnn_states_batch = []391 rnn_states_critic_batch = []392 actions_batch = []393 available_actions_batch = []394 value_preds_batch = []395 return_batch = []396 masks_batch = []397 active_masks_batch = []398 old_action_log_probs_batch = []399 adv_targ = []400401 for offset in range(num_envs_per_batch):402 ind = perm[start_ind + offset]403 if isinstance(share_obs, dict):404 for k in share_obs_batch:405 share_obs_batch[k].append(share_obs[k][:-1, ind])406 else:407 share_obs_batch.append(share_obs[:-1, ind])408 for k in obs_batch:409 obs_batch[k].append(obs[k][:-1, ind])410 rnn_states_batch.append(rnn_states[0:1, ind])411 rnn_states_critic_batch.append(rnn_states_critic[0:1, ind])412 actions_batch.append(actions[:, ind])413 if self.available_actions is not None:414 available_actions_batch.append(available_actions[:-1, ind])415 value_preds_batch.append(value_preds[:-1, ind])416 return_batch.append(returns[:-1, ind])417 masks_batch.append(masks[:-1, ind])418 active_masks_batch.append(active_masks[:-1, ind])419 old_action_log_probs_batch.append(action_log_probs[:, ind])420 adv_targ.append(advantages[:, ind])421422 # [N[T, dim]]423 T, N = self.episode_length, num_envs_per_batch424 # These are all from_numpys of size (T, N, -1)425 if isinstance(share_obs_batch, dict):426 share_obs_batch = {k: np.stack(v, 1) for k, v in share_obs_batch.items()}427 else:428 share_obs_batch = np.stack(share_obs_batch, 1)429 obs_batch = {k: np.stack(v, 1) for k, v in obs_batch.items()}430 actions_batch = np.stack(actions_batch, 1)431 if self.available_actions is not None:432 available_actions_batch = np.stack(available_actions_batch, 1)433 value_preds_batch = np.stack(value_preds_batch, 1)434 return_batch = np.stack(return_batch, 1)435 masks_batch = np.stack(masks_batch, 1)436 active_masks_batch = np.stack(active_masks_batch, 1)437 old_action_log_probs_batch = np.stack(old_action_log_probs_batch, 1)438 adv_targ = np.stack(adv_targ, 1)439440 # States is just a (N, dim) from_numpy [N[1,dim]]441 rnn_states_batch = np.stack(rnn_states_batch).reshape(N, *self.rnn_states.shape[3:])442 rnn_states_critic_batch = np.stack(rnn_states_critic_batch).reshape(N, *self.rnn_states_critic.shape[3:])443444 # Flatten the (T, N, ...) from_numpys to (T * N, ...)445 if isinstance(share_obs_batch, dict):446 share_obs_batch = {k: _flatten(T, N, v) for k, v in share_obs_batch.items()}447 else:448 share_obs_batch = _flatten(T, N, share_obs_batch)449 obs_batch = {k: _flatten(T, N, v) for k, v in obs_batch.items()}450 actions_batch = _flatten(T, N, actions_batch)451 if self.available_actions is not None:452 available_actions_batch = _flatten(T, N, available_actions_batch)453 else:454 available_actions_batch = None455 value_preds_batch = _flatten(T, N, value_preds_batch)456 return_batch = _flatten(T, N, return_batch)457 masks_batch = _flatten(T, N, masks_batch)458 active_masks_batch = _flatten(T, N, active_masks_batch)459 old_action_log_probs_batch = _flatten(T, N, old_action_log_probs_batch)460 adv_targ = _flatten(T, N, adv_targ)461462 yield share_obs_batch, obs_batch, rnn_states_batch, rnn_states_critic_batch, actions_batch,\463 value_preds_batch, return_batch, masks_batch, active_masks_batch, old_action_log_probs_batch,\464 adv_targ, available_actions_batch465466 def recurrent_generator(self, advantages, num_mini_batch, data_chunk_length):467 """468 Yield training data for chunked RNN training.469 :param advantages: (np.ndarray) advantage estimates.470 :param num_mini_batch: (int) number of minibatches to split the batch into.471 :param data_chunk_length: (int) length of sequence chunks with which to train RNN.472 """473 episode_length, n_rollout_threads, num_agents = self.rewards.shape[0:3]474 batch_size = n_rollout_threads * episode_length * num_agents475 data_chunks = batch_size // data_chunk_length # [C=r*T*M/L]476 mini_batch_size = data_chunks // num_mini_batch477478 rand = torch.randperm(data_chunks).numpy()479 sampler = [rand[i * mini_batch_size:(i + 1) * mini_batch_size] for i in range(num_mini_batch)]480481 if isinstance(self.share_obs, dict):482 share_obs = {483 k: v[:-1].transpose(1, 2, 0, *range(3, v.ndim)).reshape(-1, *v.shape[3:])484 for k, v in self.share_obs.items()485 }486 else:487 share_obs = _cast(self.share_obs[:-1])488 obs = {k: _cast(v[:-1]) for k, v in self.obs.items()}489490 actions = _cast(self.actions)491 action_log_probs = _cast(self.action_log_probs)492 advantages = _cast(advantages)493 value_preds = _cast(self.value_preds[:-1])494 returns = _cast(self.returns[:-1])495 masks = _cast(self.masks[:-1])496 active_masks = _cast(self.active_masks[:-1])497 # rnn_states = _cast(self.rnn_states[:-1])498 # rnn_states_critic = _cast(self.rnn_states_critic[:-1])499 rnn_states = self.rnn_states[:-1].transpose(1, 2, 0, 3, 4).reshape(-1, *self.rnn_states.shape[3:])500 rnn_states_critic = self.rnn_states_critic[:-1].transpose(1, 2, 0, 3, 4).reshape(-1,501 *self.rnn_states_critic.shape[502 3:])503504 if self.available_actions is not None:505 available_actions = _cast(self.available_actions[:-1])506507 for indices in sampler:508 share_obs_batch = {k: [] for k in self.share_obs} if isinstance(self.share_obs, dict) else []509 obs_batch = {k: [] for k in self.obs}510 rnn_states_batch = []511 rnn_states_critic_batch = []512 actions_batch = []513 available_actions_batch = []514 value_preds_batch = []515 return_batch = []516 masks_batch = []517 active_masks_batch = []518 old_action_log_probs_batch = []519 adv_targ = []520521 for index in indices:522523 ind = index * data_chunk_length524 # size [T+1 N M Dim]-->[T N M Dim]-->[N,M,T,Dim]-->[N*M*T,Dim]-->[L,Dim]525 if isinstance(share_obs, dict):526 for k in share_obs_batch:527 share_obs_batch[k].append(share_obs[k][ind:ind + data_chunk_length])528 else:529 share_obs_batch.append(share_obs[ind:ind + data_chunk_length])530 for k in obs_batch:531 obs_batch[k].append(obs[k][ind:ind + data_chunk_length])532 actions_batch.append(actions[ind:ind + data_chunk_length])533 if self.available_actions is not None:534 available_actions_batch.append(available_actions[ind:ind + data_chunk_length])535 value_preds_batch.append(value_preds[ind:ind + data_chunk_length])536 return_batch.append(returns[ind:ind + data_chunk_length])537 masks_batch.append(masks[ind:ind + data_chunk_length])538 active_masks_batch.append(active_masks[ind:ind + data_chunk_length])539 old_action_log_probs_batch.append(action_log_probs[ind:ind + data_chunk_length])540 adv_targ.append(advantages[ind:ind + data_chunk_length])541 # size [T+1 N M Dim]-->[T N M Dim]-->[N M T Dim]-->[N*M*T,Dim]-->[1,Dim]542 rnn_states_batch.append(rnn_states[ind])543 rnn_states_critic_batch.append(rnn_states_critic[ind])544545 L, N = data_chunk_length, mini_batch_size546547 # These are all from_numpys of size (L, N, Dim) 548 if isinstance(share_obs_batch, dict):549 share_obs_batch = {k: np.stack(v, axis=1) for k, v in share_obs_batch.items()}550 else:551 share_obs_batch = np.stack(share_obs_batch, axis=1)552 obs_batch = {k: np.stack(v, axis=1) for k, v in obs_batch.items()}553554 actions_batch = np.stack(actions_batch, axis=1)555 if self.available_actions is not None:556 available_actions_batch = np.stack(available_actions_batch, axis=1)557 value_preds_batch = np.stack(value_preds_batch, axis=1)558 return_batch = np.stack(return_batch, axis=1)559 masks_batch = np.stack(masks_batch, axis=1)560 active_masks_batch = np.stack(active_masks_batch, axis=1)561 old_action_log_probs_batch = np.stack(old_action_log_probs_batch, axis=1)562 adv_targ = np.stack(adv_targ, axis=1)563564 # States is just a (N, -1) from_numpy565 rnn_states_batch = np.stack(rnn_states_batch).reshape(N, *self.rnn_states.shape[3:])566 rnn_states_critic_batch = np.stack(rnn_states_critic_batch).reshape(N, *self.rnn_states_critic.shape[3:])567568 # Flatten the (L, N, ...) from_numpys to (L * N, ...)569 if isinstance(share_obs_batch, dict):570 share_obs_batch = {k: _flatten(L, N, v) for k, v in share_obs_batch.items()}571 else:572 share_obs_batch = _flatten(L, N, share_obs_batch)573 obs_batch = {k: _flatten(L, N, v) for k, v in obs_batch.items()}574 actions_batch = _flatten(L, N, actions_batch)575 if self.available_actions is not None:576 available_actions_batch = _flatten(L, N, available_actions_batch)577 else:578 available_actions_batch = None579 value_preds_batch = _flatten(L, N, value_preds_batch)580 return_batch = _flatten(L, N, return_batch)581 masks_batch = _flatten(L, N, masks_batch)582 active_masks_batch = _flatten(L, N, active_masks_batch)583 old_action_log_probs_batch = _flatten(L, N, old_action_log_probs_batch)584 adv_targ = _flatten(L, N, adv_targ)585586 yield share_obs_batch, obs_batch, rnn_states_batch, rnn_states_critic_batch, actions_batch,\587 value_preds_batch, return_batch, masks_batch, active_masks_batch, old_action_log_probs_batch,\588 adv_targ, available_actions_batch