如何使用pytorch同时迭代两个数据加载器?

时间:2018-07-20 13:50:42

标签: python machine-learning zip conv-neural-network pytorch

我正在尝试实现一个包含两个图像的暹罗网络。我加载这些图像并创建两个单独的数据加载器。

在循环中,我想同时浏览两个数据加载器,以便可以在两个图像上训练网络。

for i, data in enumerate(zip(dataloaders1, dataloaders2)):

    # get the inputs
    inputs1 = data[0][0].cuda(async=True);
    labels1 = data[0][1].cuda(async=True);

    inputs2 = data[1][0].cuda(async=True);
    labels2 = data[1][1].cuda(async=True);

    labels1 = labels1.view(batchSize,1)
    labels2 = labels2.view(batchSize,1)

    # zero the parameter gradients
    optimizer.zero_grad()

    # forward + backward + optimize
    outputs1 = alexnet(inputs1)
    outputs2 = alexnet(inputs2)

数据加载器的返回值是一个元组。 但是,当我尝试使用zip遍历它们时,出现以下错误:

OSError: [Errno 24] Too many open files
Exception NameError: "global name 'FileNotFoundError' is not defined" in <bound method _DataLoaderIter.__del__ of <torch.utils.data.dataloader._DataLoaderIter object at 0x7f2d3c00c190>> ignored                           

不是所有可迭代项目都可用zip压缩吗?但是似乎在这里我不能在数据加载器上使用它。

还有其他方法可以做到这一点吗?还是我错误地实现了暹罗网络的实施?

5 个答案:

答案 0 :(得分:4)

要完成@ManojAcharya的答案:

您遇到的错误既不是来自zip(),也不是来自DataLoader()。 Python试图告诉您它找不到您要的数据文件之一(参见异常跟踪中的FileNotFoundError),可能找不到您的Dataset中。

在下面的示例中结合使用DataLoaderzip。请注意,如果您想重新整理数据,则很难保留两个数据集之间的对应关系。这证明了@ManojAcharya的解决方案。

import torch
from torch.utils.data import DataLoader, Dataset

class DummyDataset(Dataset):
    """
    Dataset of numbers in [a,b] inclusive
    """

    def __init__(self, a=0, b=100):
        super(DummyDataset, self).__init__()
        self.a = a
        self.b = b

    def __len__(self):
        return self.b - self.a + 1

    def __getitem__(self, index):
        return index, "label_{}".format(index)

dataloaders1 = DataLoader(DummyDataset(0, 9), batch_size=2, shuffle=True)
dataloaders2 = DataLoader(DummyDataset(0, 9), batch_size=2, shuffle=True)

for i, data in enumerate(zip(dataloaders1, dataloaders2)):
    print(data)
# ([tensor([ 4,  7]), ('label_4', 'label_7')], [tensor([ 8,  5]), ('label_8', 'label_5')])
# ([tensor([ 1,  9]), ('label_1', 'label_9')], [tensor([ 6,  9]), ('label_6', 'label_9')])
# ([tensor([ 6,  5]), ('label_6', 'label_5')], [tensor([ 0,  4]), ('label_0', 'label_4')])
# ([tensor([ 8,  2]), ('label_8', 'label_2')], [tensor([ 2,  7]), ('label_2', 'label_7')])
# ([tensor([ 0,  3]), ('label_0', 'label_3')], [tensor([ 3,  1]), ('label_3', 'label_1')])

答案 1 :(得分:2)

我看到您正在努力实现正确的dataloder功能。我会的:

class Siamese(Dataset):


def __init__(self, transform=None):

   #init data here

def __len__(self):
    return   #length of the data

def __getitem__(self, idx):
    #get images and labels here 
    #returned images must be tensor
    #labels should be int 
    return img1, img2 , label1, label2 

答案 2 :(得分:1)

为@Aldream的解决方案添加一个解决方案,当数据集的长度不同时,如果我们希望在同一时期通过它们,那么我们可以使用Python cycle()中的itertools标准库。使用@Aldrem的代码段,更新后的代码将如下所示:

from torch.utils.data import DataLoader, Dataset
from itertools import cycle

class DummyDataset(Dataset):
    """
    Dataset of numbers in [a,b] inclusive
    """

    def __init__(self, a=0, b=100):
        super(DummyDataset, self).__init__()
        self.a = a
        self.b = b

    def __len__(self):
        return self.b - self.a + 1

    def __getitem__(self, index):
        return index

dataloaders1 = DataLoader(DummyDataset(0, 100), batch_size=10, shuffle=True)
dataloaders2 = DataLoader(DummyDataset(0, 200), batch_size=10, shuffle=True)
num_epochs = 10

for epoch in num_epochs:
    for i, data in enumerate(zip(cycle(dataloaders1), dataloaders2)):
        print(data)

只有zip()的长度等于最小数据集(此处为100)的长度时,迭代器将被耗尽。但是使用cycle(),我们将再次重复最小的数据集,除非迭代器查看最大数据集(此处为200)中的所有样本。

P.S。总是可以争辩说,只要一个人随机采样,就可能不需要这种方法来实现收敛,但是使用这种方法,评估可能会更容易。

答案 3 :(得分:1)

如果要同时迭代两个数据集,则无需定义自己的数据集类,只需使用TensorDataset即可,如下所示:

dataset = torch.utils.data.TensorDataset(dataset1, dataset2)
dataloader = DataLoader(dataset, batch_size=128, shuffle=True)
for index, data in enumerate(dataloader):
    xb1, xb2 = data
    ....

如果您希望标签或对两个以上的数据集进行迭代,只需将它们作为参数送入数据集2之后的TensorDataset。

答案 4 :(得分:1)

https://api.foursquare.com/v2/venues/{{VENUE_ID}}?client_id={{client_id}}&client_secret={{client_secret}}&v={{v}} cycle() 可能会引起内存泄漏问题,尤其是在使用图像数据集时!为了解决这个问题,而不是像这样迭代:

zip()

您可以使用:

dataloaders1 = DataLoader(DummyDataset(0, 100), batch_size=10, shuffle=True)
dataloaders2 = DataLoader(DummyDataset(0, 200), batch_size=10, shuffle=True)
num_epochs = 10

for epoch in range(num_epochs):

    for i, (data1, data2) in enumerate(zip(cycle(dataloaders1), dataloaders2)):

        do_cool_things()

请记住,如果还使用标签,则在此示例中,应将dataloaders1 = DataLoader(DummyDataset(0, 100), batch_size=10, shuffle=True) dataloaders2 = DataLoader(DummyDataset(0, 200), batch_size=10, shuffle=True) num_epochs = 10 for epoch in range(num_epochs): dataloader_iterator = iter(dataloaders1) for i, data1 in enumerate(dataloaders2)): try: data2 = next(dataloader_iterator) except StopIteration: dataloader_iterator = iter(dataloaders1) data2 = next(dataloader_iterator) do_cool_things() 替换为data1,将(inputs1,targets1)替换为data2,如@Sajad Norouzi所说。

KUDOS与此:https://github.com/pytorch/pytorch/issues/1917#issuecomment-433698337