from datasets import load_dataset import numpy as np MNIST_CLASSES = list(range(10)) def _to_numpy(batch): """ Convert an HF batch (PIL images + int labels) to numpy arrays. Images are flattened to 784-dim vectors and normalized to [0, 1]. Labels are one-hot encoded for use with SoftmaxCrossEntropy. """ imgs = np.stack([np.array(img, dtype=np.float32).reshape(-1) / 255.0 for img in batch["image"]]) labels = np.array(batch["label"], dtype=np.int32) one_hot = np.zeros((len(labels), 10), dtype=np.float32) one_hot[np.arange(len(labels)), labels] = 1.0 return imgs, labels, one_hot def load_mnist(batch_size=64): """ Load MNIST via HuggingFace datasets. Returns train_loader and test_loader, each yielding (images, labels, one_hot_labels) as numpy arrays. The dataset is cached as Arrow files in ~/.cache/huggingface/datasets/. """ ds = load_dataset("ylecun/mnist", split="train") ds_test = load_dataset("ylecun/mnist", split="test") def batch_generator(dataset, bs, shuffle): """Manual mini-batch generator from HF dataset.""" indices = np.arange(len(dataset)) if shuffle: np.random.shuffle(indices) for start in range(0, len(dataset), bs): batch_indices = indices[start:start + bs] batch = dataset[batch_indices.tolist()] yield _to_numpy(batch) def train_loader(): return batch_generator(ds, batch_size, shuffle=True) def test_loader(): return batch_generator(ds_test, batch_size, shuffle=False) return train_loader, test_loader