Dataloader access two items at the same time

mhusseinsh: <p>Hello,</p>
<p>I am looping on dataloader, but I want to access two items and the same time<br>
Example:</p>
<pre><code class="lang-auto">dataset1 = ImageFolder(input_folder, transform=transform)
train_loader_a= DataLoader(dataset=dataset1, batch_size=batch_size, shuffle=train, drop_last=True, num_workers=num_workers)

dataset2 = ImageFolder(input_folder, transform=transform)
train_loader_b= DataLoader(dataset=dataset1, batch_size=batch_size, shuffle=train, drop_last=True, num_workers=num_workers)


for it, (images_a, images_b) in enumerate(zip(train_loader_a, train_loader_b)):
        images_a, images_b = Variable(images_a.cuda()), Variable(images_b.cuda())
</code></pre>
<p>Here in every iteration, I am loading one tensor from <code>train_loader_a</code>, and one tensor from <code>train_loader_b</code><br>
what I want to do, that for every iteration, I load two consecutive tensors from each dataloader, while restricting that this is within the same iteration, so for example<br>
<code>train_loader_a</code> has 5 images of names:</p>
<pre><code class="lang-auto">a_1
a_2
a_3
a_4
a_5
</code></pre>
<p><code>train_loader_b</code> has 5 images with names:</p>
<pre><code class="lang-auto">b_1
b_2
b_3
b_4
b_5
</code></pre>
<p><code>for it = 0,</code> i want to load <code>a_1</code>, <code>a_2</code> and <code>b_1</code>, <code>b_2</code><br>
<code>for it = 1,</code> i want to load <code>a_2</code>, <code>a_3</code> and <code>b_2</code>, <code>b_3</code><br>
<code>for it = 2,</code> i want to load <code>a_3</code>, <code>a_4</code> and <code>b_3</code>, <code>b_4</code></p>
<p>and so on</p>
<p>is there a way to do so ? I tried providing the indices like <code>train_loader_a[it+1]</code> but I received an error <code>TypeError: 'DataLoader' object does not support indexing</code></p>

ptrblck: <p>Are you shuffling the <code>Datasets</code>? If so, try to set <code>shuffle=False</code> and run it again.<br>
However, I’m a bit skeptical if your approach will always work, as you might want to use multiprocessing in your <code>DataLoaders</code>, which might lead to inconsistent racing between the workers.</p>
<p>I would rather create a new <code>Dataset</code>, initializing both of your datasets in it and just return deterministically two samples in <code>__getitem__</code>.<br>
The code would look like this:</p>
<pre><code class="lang-python">
class MyDataset(Dataset):
    def __init__(self, dataset1, dataset2):
        self.dataset1 = dataset1 # datasets should be sorted!
        self.dataset2 = dataset2

    def __getitem__(self, index):
        x1 = self.dataset1[index]
        x2 = self.dataset2[index]

        return x1, x2

    def __len__(self):
        return len(self.dataset1) # assuming both datasets have same length

dataset = MyDataset(dataset1, dataset2)
loader = DataLoader(dataset, batch_size=...)
</code></pre>
<p>Both your datasets created from <code>ImageFolder</code> should return sorted images.<br>
If that’s not the case, you would have to pass the image folder paths to <code>MyDataset</code>, sort the image paths for both folders, and lazily load the images in <code>__getitem__</code>.</p>

mhusseinsh: <p>I think this is not what I want<br>
what you have written will return one tensor from here and there</p>
<p>I want to return two consecutive tensors from the same dataset at the same time</p>
<p>so I already have two different loaders for both datasets</p>

ptrblck: <p>If you set the <code>batch_size=2</code>, you would get <code>a1, b1, a2, b2</code>. Would that work or do I still misunderstand you?</p>

mhusseinsh: <p>Ah okay, then without implementing your approach, if I set in the beginning the batchsize=2, i can get images_a[0] and images_a[1]</p>
<p>I tried it and it worked</p>
<p>Thanks a lot for your help</p>

mhusseinsh: <p>and for sure, in order to ensure that the frames are subsequent, I have to make sure that the list is sorted, and I am already doing so, without shuffling also</p>

ptrblck: <p>That could work, but I’m still concerned about the multiprocessing part, i.e. race conditions, which <em>might</em> mix up your order even though the paths are sorted.</p>

mhusseinsh: <p>Sorry I don’t get what you mean</p>
<p>I am not expert with torch, so I don’t get what you mean about race conditions, multiprocessing or so</p>

ptrblck: <p>If you set <code>num_workers &gt; 0</code> in your <code>DataLoader</code>, multiple workers will be created and load your batches of data in the background.<br>
E.g. for multiple workers you will get <code>batch1</code> from worker1, <code>batch2</code> from worker2 etc., then it will start with worker1 again.</p>
<p>I’m not sure, if the order is somehow enforced or if the next ready worker just puts his data into the queue.<br>
In the latter case, it might be that somehow the order might be broken, and worker2 finishes before worker1.<br>
This would yield your data like:</p>
<pre><code class="lang-python">a1, b1
a2, b2,
a4, b4,
a3, b3,
...
</code></pre>
<p>Would this be troublesome or can you handle this case?</p>

mhusseinsh: <p>i have <code>num_workers=4</code><br>
So you mean that for example I will receive</p>
<pre><code class="lang-auto">a1 a2, b1 b2
a2 a3, b2 b3
</code></pre>
<p>and then I can receive afterwards<br>
<code>a5 a6 b5 b6</code><br>
?</p>

ptrblck: <p>Apparently I’m mistaken and the order is enforced. At least I couldn’t get wrong ordering.</p>

mhusseinsh: <p>hi <a class="mention" href="/u/ptrblck">@ptrblck</a><br>
I am referring to the same task, but another matter in another <a href="https://discuss.pytorch.org/t/dataloader-as-a-list-shuffle-implicit-pairs/24525">issue</a>, if you can please have a look on it, maybe you can help</p>

Surya_Narayanan: <p>Hi folks, I was looking at this issue, because I too want to combine multiple dataloaders-</p>
<p>so if from <code>dataloaderA</code>, if i get sample <code>a_1, a_2, ..., a_batch_size</code><br>
and if from <code>dataloaderB</code>, if i get sample <code>b_1, b_2, ..., b_batch_size</code></p>
<p>I want to have a <code>dataloaderAB</code>, where I get <code>((a_1, a_2, ..., a_batch_size), (b_1, b_2, ..., b_batch_size))</code> when I iterate over <code>dataloaderAB</code>.</p>
<p>The issue that prevents me from using the previously suggested solution of making a dataset that yields a tuple of items in the following form is that each dataloader, uses a different collate function.</p>
<p>Any thoughts?</p>

ptrblck: <p>Assuming you want to load a single batch from each <code>DataLoader</code> wouldn’t the original approach using <code>zip</code> work?</p>