-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathdataloader.h
More file actions
131 lines (114 loc) · 4.58 KB
/
Copy pathdataloader.h
File metadata and controls
131 lines (114 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#pragma once
// ============================================================
// include/dataloader.h – Character-level tokeniser & batching
// Mirrors the data-loading section of the Python script
// ============================================================
#include "tensor.h"
#include "config/config.h"
#include <string>
#include <vector>
#include <map>
#include <set>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <iostream>
#include <random>
#include <stdexcept>
struct DataLoader
{
std::string text;
std::vector<char> chars; // sorted vocabulary
std::map<char, int> stoi; // char → index
std::map<int, char> itos; // index → char
int vocab_size{0};
std::vector<int> train_data;
std::vector<int> val_data;
// ---- load and prepare ----------------------------------------
void load(const std::string &path, double train_split = TRAIN_SPLIT)
{
std::ifstream f(path);
if (!f.is_open())
throw std::runtime_error("[DataLoader] Cannot open file: " + path);
std::ostringstream ss;
ss << f.rdbuf();
text = ss.str();
if (text.empty())
throw std::runtime_error("[DataLoader] File is empty: " + path);
// build vocabulary
std::set<char> charset(text.begin(), text.end());
chars = std::vector<char>(charset.begin(), charset.end());
std::sort(chars.begin(), chars.end());
vocab_size = (int)chars.size();
stoi.clear();
itos.clear();
for (int i = 0; i < vocab_size; ++i)
{
stoi[chars[i]] = i;
itos[i] = chars[i];
}
// encode
std::vector<int> data;
data.reserve(text.size());
for (char c : text)
data.push_back(stoi.at(c));
int n = (int)(train_split * data.size());
train_data = std::vector<int>(data.begin(), data.begin() + n);
val_data = std::vector<int>(data.begin() + n, data.end());
if (train_data.size() <= (size_t)BLOCK_SIZE ||
val_data.size() <= (size_t)BLOCK_SIZE)
throw std::runtime_error("[DataLoader] Dataset is too small for the configured BLOCK_SIZE=" +
std::to_string(BLOCK_SIZE) + ". Need more than " +
std::to_string(BLOCK_SIZE + 1) + " tokens in both train and validation splits.");
std::cout << "[DATA] Total characters : " << text.size() << "\n";
std::cout << "[DATA] Vocabulary size : " << vocab_size << "\n";
std::cout << "[DATA] Train tokens : " << train_data.size() << "\n";
std::cout << "[DATA] Val tokens : " << val_data.size() << "\n";
}
// ---- encode / decode -----------------------------------------
std::vector<int> encode(const std::string &s) const
{
std::vector<int> out;
out.reserve(s.size());
for (char c : s)
{
auto it = stoi.find(c);
if (it != stoi.end())
out.push_back(it->second);
}
return out;
}
std::string decode(const std::vector<int> &ids) const
{
std::string out;
out.reserve(ids.size());
for (int id : ids)
{
auto it = itos.find(id);
if (it != itos.end())
out += it->second;
}
return out;
}
// ---- batch sampler -------------------------------------------
// Returns (x, y) as flat integer vectors of size B*T
std::pair<std::vector<int>, std::vector<int>>
get_batch(const std::string &split, int batch_size, int block_size,
std::mt19937 &rng) const
{
const std::vector<int> &d = (split == "train") ? train_data : val_data;
std::uniform_int_distribution<int> dist(0, (int)d.size() - block_size - 1);
std::vector<int> x(batch_size * block_size);
std::vector<int> y(batch_size * block_size);
for (int b = 0; b < batch_size; ++b)
{
int start = dist(rng);
for (int t = 0; t < block_size; ++t)
{
x[b * block_size + t] = d[start + t];
y[b * block_size + t] = d[start + t + 1];
}
}
return {x, y};
}
};