【问题标题】:When does dataloader shuffle happen for Pytorch?Pytorch 的 dataloader shuffle 何时发生?
【发布时间】:2020-08-26 08:37:18
【问题描述】:

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

namesDataset = NamesDataset()
namesTrainLoader = DataLoader(namesDataset, batch_size=16, shuffle=True)
for batch_data in namesTrainLoader:
    print(batch_data)

当我们定义“namesTrainLoader”时,这是否意味着洗牌已经完成,接下来的迭代将基于固定的数据顺序?定义namesTrainLoader后for循环会不会有随机性?

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

for batch_data in namesTrainLoader:
    batch_data[:8] = special_val
    pre = model(batch_data)

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

【问题讨论】:

    标签: python machine-learning pytorch shuffle dataloader


    【解决方案1】:

    在创建迭代器时发生改组。对于 for 循环,这发生在 for 循环开始之前。

    您可以手动创建迭代器:

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

    如果您设置了shuffle=True,数据加载器默认使用torch.utils.data.RandomSampler(不提供您自己的采样器)。它的实现非常简单,您可以通过查看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())
    

    return 语句是进行洗牌的重要部分。它只是创建索引的随机排列。

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

    【讨论】:

    • 感谢您的回复。所以我的模型会在每个时期看到所有数据,即使在一半的 batch_data 被“special_val”破坏之后?
    • 如果您覆盖它,您将不会在此特定迭代中实际使用该数据。您收到的数据将覆盖整个数据集,但如果您决定覆盖或忽略它,模型将不会看到它。但是,如果您问这是否会影响未来的迭代,那么答案通常是否定的,但在极少数情况下,您将张量存储在数据集中,就地操作会影响这一点。通常情况并非如此,因为您要么按需加载数据,要么至少只在批处理期间创建张量,因此即使就地操作也没有效果。
    【解决方案2】:

    您可以查看 PyTorch 对 torch.utils.data.DataLoader here 的实现。

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

    DataLoader 的实例被创建时,什么都不会被洗牌,它只是实例化对象的必要私有成员和其他类似的设置。

    当您在迭代过程中发出特殊的__iter__ 方法时,在您的情况下,将返回一个名为_SingleProcessDataLoader(self) 的特殊对象,它是数据生成器(可能是批处理、混洗等,假设您不使用多处理)。

    要找到所有私有和辅助相关的方法,有一点需要遵循,但它的基本作用是使用底层的sampler 来获取用于从torch.utils.data.Dataset 获取样本的索引。

    Sampler 一直运行直到用尽并且该过程重复(通常是一个时期)。

    namesTrainLoader 后面的for循环会不会有随机性 被定义了吗?

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-18
      • 2019-07-20
      • 1970-01-01
      • 2020-12-18
      • 2022-11-04
      • 2020-07-14
      • 2022-01-24
      相关资源
      最近更新 更多