【问题标题】:Is Pytorch DataLoader Iteration order stable?Pytorch DataLoader 迭代顺序稳定吗?
【发布时间】:2019-12-12 23:35:00
【问题描述】:

Pytorch Dataloader 的迭代顺序是否保证相同(在温和条件下)?

例如:

dataloader = DataLoader(my_dataset, batch_size=4,
                        shuffle=True, num_workers=4)
print("run 1")
for batch in dataloader:
  print(batch["index"])

print("run 2")
for batch in dataloader:
  print(batch["index"])

到目前为止,我已尝试对其进行测试,但似乎没有修复,两次运行的顺序相同。有没有办法使订单相同?谢谢

编辑:我也试过做

unlabeled_sampler = data.sampler.SubsetRandomSampler(unlabeled_indices)
unlabeled_dataloader = data.DataLoader(train_dataset, 
                sampler=unlabeled_sampler, batch_size=args.batch_size, drop_last=False)

然后遍历数据加载器两次,但结果相同的非确定性。

【问题讨论】:

  • 稳定提供shuffle=False,在您的情况下,您通过设置shuffle=True明确要求以随机顺序返回数据
  • 好的,好点。但它是“相同的”数据加载器,不是吗?
  • 同一个数据集不是同一个加载器。加载器“只是”数据集的一个接口,其中定义了一个采样器。采样器以定义的方式和顺序对您的数据集进行采样。如果您更改 shuffle,那么您正在更改数据加载器正在使用的采样器,这可以使其从稳定变为不稳定。您还可以在定义数据加载器时显式指定采样器。
  • 感谢您的澄清!所以实际上我有:unlabeled_sampler = data.sampler.SubsetRandomSampler(unlabeled_indices),然后是unlabeled_dataloader = data.DataLoader(train_dataset, sampler=unlabeled_sampler, batch_size=args.batch_size, drop_last=False),迭代顺序仍然不稳定。有什么想法吗?
  • 我想我现在更了解您的问题了。我发布了一个我相信可以回答您的问题的答案。

标签: pytorch iterable deterministic dataloader


【解决方案1】:

简短的回答是否定的,当 shuffle=True 的迭代顺序 DataLoader 在迭代之间不稳定时。每次您在加载器上迭代时,内部 RandomSampler 都会创建一个新的随机顺序。

获得稳定的混洗DataLoader 的一种方法是使用一组混洗索引创建Subset 数据集。

shuffled_dataset = torch.utils.data.Subset(my_dataset, torch.randperm(len(my_dataset)).tolist())
dataloader = DataLoader(shuffled_dataset, batch_size=4, num_workers=4, shuffled=False)

【讨论】:

  • 谢谢,让我再测试一个想法,然后我会尝试你的答案并接受。对我来说奇怪的是,如果我适当地设置种子,那么内部 RandomSampler 应该每次都给出相同的随机索引,不是吗?
  • @information_interchange 我相信RandomSampler 中的随机化发生在创建数据加载器迭代器时(例如,当您执行for label, data in dataloader: 时)。您需要在每次迭代您的数据加载器之前立即使用相同的种子值播种torch 的随机数生成器(例如torch.manual_seed(1234)),以确保可重复性。这并不理想,因为您系统中的任何其他随机行为最终也会被重复,这可能是不希望的。
  • 嘿嘿,我刚试过这个方法,可惜没用:ValueError: sampler should be an instance of torch.utils.data.Sampler, but got sampler=[739, 841, 1892,..]
  • 哦,这真的很有趣,你是对的。这非常令人惊讶,因为这是 pytorch 开发人员之一的建议。无论如何,我恢复了我的第一个解决方案,该解决方案也同样有效,并且我已经进行了测试以确保。
【解决方案2】:

我实际上选择了 jodag 的 in-the-cmets 答案:

torch.manual_seed("0")

for i,elt in enumerate(unlabeled_dataloader):
    order.append(elt[2].item())
    print(elt)

    if i > 10:
        break

torch.manual_seed("0")

print("new dataloader")
for i,elt in enumerate( unlabeled_dataloader):
    print(elt)
    if i > 10:
        break
exit(1)                       

和输出:

[tensor([[-0.3583, -0.6944]]), tensor([3]), tensor([1610])]
[tensor([[-0.6623, -0.3790]]), tensor([3]), tensor([1958])]
[tensor([[-0.5046, -0.6399]]), tensor([3]), tensor([1814])]
[tensor([[-0.5349,  0.2365]]), tensor([2]), tensor([1086])]
[tensor([[-0.1310,  0.1158]]), tensor([0]), tensor([321])]
[tensor([[-0.2085,  0.0727]]), tensor([0]), tensor([422])]
[tensor([[ 0.1263, -0.1597]]), tensor([0]), tensor([142])]
[tensor([[-0.1387,  0.3769]]), tensor([1]), tensor([894])]
[tensor([[-0.0500,  0.8009]]), tensor([3]), tensor([1924])]
[tensor([[-0.6907,  0.6448]]), tensor([4]), tensor([2016])]
[tensor([[-0.2817,  0.5136]]), tensor([2]), tensor([1267])]
[tensor([[-0.4257,  0.8338]]), tensor([4]), tensor([2411])]
new dataloader
[tensor([[-0.3583, -0.6944]]), tensor([3]), tensor([1610])]
[tensor([[-0.6623, -0.3790]]), tensor([3]), tensor([1958])]
[tensor([[-0.5046, -0.6399]]), tensor([3]), tensor([1814])]
[tensor([[-0.5349,  0.2365]]), tensor([2]), tensor([1086])]
[tensor([[-0.1310,  0.1158]]), tensor([0]), tensor([321])]
[tensor([[-0.2085,  0.0727]]), tensor([0]), tensor([422])]
[tensor([[ 0.1263, -0.1597]]), tensor([0]), tensor([142])]
[tensor([[-0.1387,  0.3769]]), tensor([1]), tensor([894])]
[tensor([[-0.0500,  0.8009]]), tensor([3]), tensor([1924])]
[tensor([[-0.6907,  0.6448]]), tensor([4]), tensor([2016])]
[tensor([[-0.2817,  0.5136]]), tensor([2]), tensor([1267])]
[tensor([[-0.4257,  0.8338]]), tensor([4]), tensor([2411])]

这是所需的。但是,我认为 jodag 的主要答案仍然更好;这只是一个快速破解,现在可以使用;)

【讨论】:

    猜你喜欢
    • 2022-11-27
    • 1970-01-01
    • 2023-02-20
    • 2012-09-17
    • 1970-01-01
    • 2019-05-17
    • 2021-04-18
    • 2019-07-20
    • 1970-01-01
    相关资源
    最近更新 更多