keras/src/trainers/data_adapters/array_data_adapter.py/ArrayDataAdapter/no_op_collate
class ArrayDataAdapter:    def get_torch_dataloader(self):
        import torch

        from keras.src.backend.torch.core import convert_to_tensor

        class ArrayDataset(torch.utils.data.Dataset):
            def __init__(self, array):
                self.array = array

            def __getitems__(self, indices):
                def slice_and_convert(sliceable):
                    x = sliceable[indices]
                    x = sliceable.convert_to_torch_compatible(x)
                    x = convert_to_tensor(x)
                    return x

                return tree.map_structure(slice_and_convert, self.array)

            def __len__(self):
                return len(self.array[0])

        class RandomBatchSampler(torch.utils.data.Sampler):
            def __init__(self, sampler):
                self.sampler = sampler

            def __iter__(self):
                for batch in self.sampler:
                    yield [batch[i] for i in torch.randperm(len(batch))]

            def __len__(self):
                return len(self.sampler)

        if self._shuffle == "batch":
            batch_sampler = RandomBatchSampler(
                torch.utils.data.BatchSampler(
                    range(self._num_samples),
                    batch_size=self._batch_size,
                    drop_last=False,
                )
            )
        elif self._shuffle:
            batch_sampler = torch.utils.data.BatchSampler(
                torch.utils.data.RandomSampler(range(self._num_samples)),
                batch_size=self._batch_size,
                drop_last=False,
            )
        else:
            batch_sampler = torch.utils.data.BatchSampler(
                torch.utils.data.SequentialSampler(range(self._num_samples)),
                batch_size=self._batch_size,
                drop_last=False,
            )

        # Because ArrayDataset.__getitems__ returns full batches organized in
        # the expected structure, there is nothing to collate.
        def no_op_collate(batch):
            return batch

        inputs = array_slicing.convert_to_sliceable(
            self._inputs, target_backend="torch"
        )
        dataset = ArrayDataset(inputs)
        return torch.utils.data.DataLoader(
            dataset, batch_sampler=batch_sampler, collate_fn=no_op_collate
        )