Buckets:
| import torch | |
| from torch.utils.data import Dataset, DataLoader | |
| from datasets import load_dataset | |
| import tiktoken | |
| from typing import List, Dict, Any, Optional | |
| class PG19Dataset(Dataset): | |
| """ Dataset class for test-split of PG-19. | |
| Downloads the dataset from huggingface `emozilla/pg19-test` and preprocesses it | |
| into chunks of a specified sequence length and tokenizes it using gpt2 tokenizer. | |
| """ | |
| def __init__( | |
| self, | |
| seq_len: int = 1024, | |
| streaming: bool = False, | |
| max_books: Optional[int] = None | |
| ): | |
| self.seq_len = seq_len | |
| self.tokenizer = tiktoken.get_encoding("gpt2") | |
| # Load the dataset | |
| self.dataset = load_dataset("emozilla/pg19-test", split="test", streaming=streaming) | |
| # If not streaming and max_books is specified, limit the dataset | |
| if not streaming and max_books is not None: | |
| self.dataset = self.dataset.select(range(min(max_books, len(self.dataset)))) | |
| # Preprocess and chunk the texts | |
| self.chunks = [] | |
| self._prepare_chunks(max_books if streaming else None) | |
| print(f"Dataset prepared with {len(self.chunks)} chunks of max length {seq_len}") | |
| def _prepare_chunks(self, max_books: Optional[int] = None): | |
| book_count = 0 | |
| for example in self.dataset: | |
| if max_books and book_count >= max_books: | |
| break | |
| text = example['text'] | |
| # Tokenize the entire book | |
| tokens = self.tokenizer.encode(text) | |
| # Split into chunks of seq_len | |
| for i in range(0, len(tokens), self.seq_len): | |
| chunk = tokens[i:i + self.seq_len] | |
| # Only keep chunks that are at least seq_len tokens | |
| # (you might want to adjust this based on your needs) | |
| if len(chunk) == self.seq_len: | |
| self.chunks.append({ | |
| 'input_ids': torch.tensor(chunk, dtype=torch.long), | |
| 'book_id': example.get('book_id', book_count), | |
| 'chunk_id': i // self.seq_len | |
| }) | |
| book_count += 1 | |
| if book_count % 10 == 0: | |
| print(f"Processed {book_count} books, {len(self.chunks)} chunks so far...") | |
| def __len__(self) -> int: | |
| return len(self.chunks) | |
| def __getitem__(self, idx: int) -> Dict[str, torch.Tensor]: | |
| return self.chunks[idx] | |
| class PG19DataLoader: | |
| def __init__( | |
| self, | |
| seq_len: int = 1024, | |
| batch_size: int = 1, | |
| streaming: bool = False, | |
| max_books: Optional[int] = None, | |
| num_workers: int = 4, | |
| shuffle: bool = True, | |
| pin_memory: bool = True | |
| ): | |
| self.dataset = PG19Dataset( | |
| seq_len=seq_len, | |
| streaming=streaming, | |
| max_books=max_books | |
| ) | |
| self.dataloader = DataLoader( | |
| self.dataset, | |
| batch_size=batch_size, | |
| shuffle=shuffle and not streaming, # Can't shuffle streaming datasets | |
| num_workers=num_workers, | |
| pin_memory=pin_memory, | |
| collate_fn=self._collate_fn | |
| ) | |
| def _collate_fn(self, batch: List[Dict[str, Any]]) -> Dict[str, torch.Tensor]: | |
| # Stack input_ids | |
| input_ids = torch.stack([item['input_ids'] for item in batch]) | |
| # Collect metadata | |
| book_ids = torch.tensor([item['book_id'] for item in batch], dtype=torch.long) | |
| chunk_ids = torch.tensor([item['chunk_id'] for item in batch], dtype=torch.long) | |
| return { | |
| 'input_ids': input_ids, | |
| 'book_ids': book_ids, | |
| 'chunk_ids': chunk_ids | |
| } | |
| def __iter__(self): | |
| return iter(self.dataloader) | |
| def __len__(self): | |
| return len(self.dataloader) | |
| # Example usage and testing | |
| if __name__ == "__main__": | |
| # Example 1: Basic usage | |
| print("Creating PG-19 DataLoader...") | |
| # For testing, use a small number of books | |
| pg19_loader = PG19DataLoader( | |
| seq_len=10240, | |
| batch_size=1, | |
| max_books=100, | |
| num_workers=4, | |
| shuffle=True | |
| ) | |
| print(f"DataLoader created with {len(pg19_loader)} batches") | |
| # Test loading a few batches | |
| print("\nTesting batch loading...") | |
| for i, batch in enumerate(pg19_loader): | |
| print(f" Batch {i+1}:") | |
| print(f" Input IDs shape: {batch['input_ids'].shape}") | |
| print(f" Book IDs: {batch['book_ids'].tolist()}") | |
| print(f" Chunk IDs: {batch['chunk_ids'].tolist()}") | |
| # Decode first few tokens to verify | |
| tokenizer = tiktoken.get_encoding("gpt2") | |
| first_sequence = batch['input_ids'][0][:100] | |
| decoded_text = tokenizer.decode(first_sequence.tolist()) | |
| print(f" Sample text: {decoded_text}...") | |
| if i >= 2: # Only show first 3 batches | |
| break | |
| # print("\n" + "="*50) | |
| # print("Example 2: Streaming mode for large datasets") | |
| # # Example with streaming (useful for very large datasets) | |
| # streaming_loader = PG19DataLoader( | |
| # seq_len=1024, | |
| # batch_size=2, | |
| # streaming=True, | |
| # max_books=3, # Still limit for demo | |
| # shuffle=False # Can't shuffle streaming datasets | |
| # ) | |
| # print(f"Streaming DataLoader created") | |
| # # Test a few batches from streaming | |
| # for i, batch in enumerate(streaming_loader): | |
| # print(f"Streaming Batch {i+1}: {batch['input_ids'].shape}") | |
| # if i >= 1: # Only show first 2 batches | |
| # break |
Xet Storage Details
- Size:
- 5.74 kB
- Xet hash:
- eeec1568eac93ba085ca6151d0b7f2e12f1d68c4ae3ca766e716317ebb437a85
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.