Pytorch 的数据加载器 shuffle 何时发生?

Jim*_*ang 4 python shuffle machine-learning pytorch dataloader

我已经多次使用 pytorch 数据加载器的 shuffle 选项。但我想知道这种 shuffle 何时发生以及它是否在迭代期间动态执行。以下面的代码为例:

namesDataset = NamesDataset()
namesTrainLoader = DataLoader(namesDataset, batch_size=16, shuffle=True)
for batch_data in namesTrainLoader:
    print(batch_data)
Run Code Online (Sandbox Code Playgroud)

当我们定义“namesTrainLoader”时,是否意味着shuffle结束,接下来的迭代将基于固定的数据顺序?定义了 namesTrainLoader 后,for 循环中会不会有任何随机性?

我试图用一些特殊值替换“batch_data”的一半:

for batch_data in namesTrainLoader:
    batch_data[?8] = special_val
    pre = model(batch_data)
Run Code Online (Sandbox Code Playgroud)

假设将有无数个 epoch,“模型”最终会看到“namesTrainLoader”中的所有数据吗?还是说“namesTrainLoader”的一半数据实际上丢给了“model”?

Mic*_*ngo 6

混洗在创建迭代器时发生。在 for 循环的情况下,这发生在 for 循环开始之前。

您可以使用以下命令手动创建迭代器:

# Iterator gets created, the data has been shuffled at this point.
data_iterator = iter(namesTrainLoader)
Run Code Online (Sandbox Code Playgroud)

默认情况下,数据加载器使用torch.utils.data.RandomSamplerif 您设置shuffle=True(不提供您自己的采样器)。它的实现非常简单,您可以通过查看该RandomSampler.__iter__方法来查看创建迭代器时数据被打乱的位置:

def __iter__(self):
    n = len(self.data_source)
    if self.replacement:
        return iter(torch.randint(high=n, size=(self.num_samples,), dtype=torch.int64).tolist())
    return iter(torch.randperm(n).tolist())
Run Code Online (Sandbox Code Playgroud)

return 语句是重排发生的重要部分。它只是创建索引的随机排列。

这意味着每次完全使用迭代器时,您都会看到整个数据集,只是每次的顺序不同。因此没有数据丢失(不包括带有 的情况drop_last=True)并且您的模型将看到每个时期的所有数据。


Szy*_*zke 5

torch.utils.data.DataLoader 您可以在此处查看 PyTorch 的实现。

如果您指定shuffle=True torch.utils.data.RandomSampler将被使用(SequentialSampler否则)。

当创建实例时DataLoader,不会对任何内容进行洗牌,它只是实例化对象的必要私有成员和其他设置之类的东西。

当您在迭代期间发出特殊__iter__方法时,就像您的情况一样,会返回一个特殊对象,_SingleProcessDataLoader(self)该对象名为数据生成器(可能是批处理、洗牌等,假设您不使用多处理)。

要找到所有私有和帮助程序相关的方法,需要遵循一些兔子洞,但它基本上所做的是使用底层sampler来获取索引,这些索引用于从torch.utils.data.Dataset.

采样器运行直到耗尽并且重复该过程(通常是一个时期)。

定义namesTrainLoader后for循环中会有随机性吗?

在每个周期/纪元开始时RandomSampler都会对索引进行洗牌__iter__,所以是的,它将在每个纪元之前(当调用并返回新值时)进行随机化_SingleProcessDataLoader(self),这可以无限期地完成。

[...]“模型”最终会看到“namesTrainLoader”中的所有数据吗?

是的,它最终很可能会看到所有数据点