Download ar/data/dataset.py from AjayRangoji/AR: direct link, hf CLI and curl.
- Browser
- Download file 2.46 kB
-
https://huggingface.co/AjayRangoji/AR/resolve/main/ar/data/dataset.py
- Command line
-
hf download hf://AjayRangoji/AR/ar/data/dataset.py
-
curl -L -o dataset.py https://huggingface.co/AjayRangoji/AR/resolve/main/ar/data/dataset.py
2.46 kB
| import numpy as np | |
| import torch | |
| class BinDataset: | |
| """Serves training batches from one or more memory-mapped .bin token files. | |
| Memory-mapping lets us read slices of a huge file without loading it into RAM. | |
| Each sample is a random window; input and target are the window shifted by one. | |
| Also returns segment IDs so attention can stay inside document boundaries. | |
| """ | |
| def __init__( | |
| self, | |
| bin_paths: list[str], | |
| seq_len: int, | |
| weights: list[float] | None = None, | |
| eot_token_id: int = 151643, | |
| ): | |
| self.seq_len = seq_len | |
| self.eot_token_id = eot_token_id | |
| # open each source as a read-only memory map of uint32 token ids | |
| self.data = [np.memmap(p, dtype=np.uint32, mode="r") for p in bin_paths] | |
| self.lengths = [len(d) for d in self.data] | |
| # sampling weights = the data mix (e.g. 0.65 english, 0.20 code, 0.15 math) | |
| if weights is None: | |
| weights = [n / sum(self.lengths) for n in self.lengths] | |
| self.weights = np.array(weights) / np.sum(weights) | |
| def get_batch(self, batch_size: int, device: str = "cuda"): | |
| x = np.empty((batch_size, self.seq_len), dtype=np.int64) | |
| y = np.empty((batch_size, self.seq_len), dtype=np.int64) | |
| seg = np.empty((batch_size, self.seq_len), dtype=np.int32) | |
| for i in range(batch_size): | |
| # pick a source according to the mix, then a random window inside it | |
| src = np.random.choice(len(self.data), p=self.weights) | |
| arr, n = self.data[src], self.lengths[src] | |
| start = np.random.randint(0, n - self.seq_len - 1) | |
| chunk = arr[start : start + self.seq_len + 1].astype(np.int64) | |
| x[i] = chunk[:-1] # input: tokens 0..seq_len-1 | |
| y[i] = chunk[1:] # target: same window shifted by one | |
| # segment IDs bump AFTER each EOT, so EOT stays with the doc it ends. | |
| # Example x[i]=[a,b,EOT,c,d,EOT,e] -> seg[i]=[0,0,0,1,1,1,2] | |
| is_eot = (x[i] == self.eot_token_id).astype(np.int32) | |
| seg[i] = np.cumsum(is_eot) - is_eot | |
| # pin_memory + non_blocking speeds up the CPU->GPU copy during training | |
| xt = torch.from_numpy(x).pin_memory().to(device, non_blocking=True) | |
| yt = torch.from_numpy(y).pin_memory().to(device, non_blocking=True) | |
| st = torch.from_numpy(seg).pin_memory().to(device, non_blocking=True) | |
| return xt, yt, st |