Spaces:
Sleeping
Sleeping
| import numpy as np | |
| import torch | |
| import random | |
| from typing import Dict, List, Tuple | |
| class ReplayBuffer: | |
| """ | |
| A simple sequence replay buffer for Dreamer training. | |
| Expects episodes of shape (seq_len, dim) to be added. | |
| """ | |
| def __init__(self, capacity: int = 10000, seq_len: int = 50): | |
| self.capacity = capacity | |
| self.seq_len = seq_len | |
| self.episodes = [] | |
| def add_episode(self, obs: np.ndarray, actions: np.ndarray, rewards: np.ndarray): | |
| """ | |
| obs: (time, obs_dim) | |
| actions: (time, action_dim) | |
| rewards: (time,) | |
| """ | |
| if len(self.episodes) >= self.capacity: | |
| self.episodes.pop(0) | |
| self.episodes.append({ | |
| 'obs': obs, | |
| 'actions': actions, | |
| 'rewards': rewards | |
| }) | |
| def sample_batch(self, batch_size: int) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: | |
| """ | |
| Samples a batch of sequence chunks. | |
| Returns tensors of shape (batch, seq_len, dim) | |
| """ | |
| if len(self.episodes) == 0: | |
| raise ValueError("Replay buffer is empty.") | |
| obs_batch, action_batch, reward_batch = [], [], [] | |
| for _ in range(batch_size): | |
| ep_idx = random.randint(0, len(self.episodes) - 1) | |
| ep = self.episodes[ep_idx] | |
| ep_len = len(ep['obs']) | |
| if ep_len <= self.seq_len: | |
| start = 0 | |
| pad_len = self.seq_len - ep_len | |
| obs = np.pad(ep['obs'], ((0, pad_len), (0, 0)), mode='edge') | |
| acts = np.pad(ep['actions'], ((0, pad_len), (0, 0)), mode='edge') | |
| rews = np.pad(ep['rewards'], (0, pad_len), mode='constant', constant_values=0) | |
| else: | |
| start = random.randint(0, ep_len - self.seq_len) | |
| obs = ep['obs'][start:start + self.seq_len] | |
| acts = ep['actions'][start:start + self.seq_len] | |
| rews = ep['rewards'][start:start + self.seq_len] | |
| obs_batch.append(obs) | |
| action_batch.append(acts) | |
| reward_batch.append(rews) | |
| return ( | |
| torch.FloatTensor(np.stack(obs_batch)), | |
| torch.FloatTensor(np.stack(action_batch)), | |
| torch.FloatTensor(np.stack(reward_batch)) | |
| ) | |