Dataloader for multi-task Model with unbalanced data

username: abhi8569
cooked: <p>Hello Everyone,</p>
<p>I am trying to train a multi-task model with two different sets of the dataset for the tasks. I split the training data into train(80%) and validation data(20%). Detail of the dataset that I have created:</p>
<ul>
<li>
<p>Each pair of the image and label for the Task 1 Data has been packed inside a dictionary with two keys<br>
Total :  5255<br>
Train Data :  4204<br>
Validation Data :  1051</p>
</li>
<li>
<p>For task 2, data is the form of a list<br>
Total :  1108<br>
Train Data :  886<br>
Validation Data :  222</p>
</li>
</ul>
<p>I have concatenated the data using</p>
<pre><code class="lang-auto">combined_training_dataset = torch.utils.data.ConcatDataset([task_1_train_set, task_2_train_set])
</code></pre>
<p>Combined Train Dataset :  5090</p>
<p>To train the model, I want each batch to have data from only one of the datasets and data coming from each dataset one after another.</p>
<p>I have been following <a href="https://towardsdatascience.com/unbalanced-data-loading-for-multi-task-learning-in-pytorch-e030ad5033b#" rel="nofollow noopener">this</a> blog to fulfill my requirement. This is how I am creating the loader:</p>
<pre><code class="lang-auto">combined_train_loader = torch.utils.data.DataLoader(dataset=combined_training_dataset, 
                                           sampler=BalancedBatchSchedulerSampler(dataset=combined_training_dataset,
                                                                       batch_size=10),
                                           batch_size=10,
                                           shuffle=False,
                                           pin_memory=True)
</code></pre>
<p>I am using code from unbalanced loader part of the blog but getting this error:</p>
<pre><code class="lang-auto">&lt;ipython-input-14-7948015c2ea8&gt; in print_dataloader(loader, num_of_image, avDev)
      6 def print_dataloader(loader, num_of_image = 5, avDev = torch.device("cuda")):
      7     print("\n*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Training Image Samples *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*")
----&gt; 8     for num_batch, batch in enumerate(loader):
      9         if num_batch &lt; 2:
     10             if batch.__class__.__name__ == "dict" :

~/anaconda3/lib/python3.7/site-packages/torch/utils/data/dataloader.py in __next__(self)
    343 
    344     def __next__(self):
--&gt; 345         index = self._next_index()  # may raise StopIteration
    346         data = self._dataset_fetcher.fetch(index)  # may raise StopIteration
    347         if self._pin_memory:

~/anaconda3/lib/python3.7/site-packages/torch/utils/data/dataloader.py in _next_index(self)
    316 
    317     def _next_index(self):
--&gt; 318         return next(self._sampler_iter)  # may raise StopIteration
    319 
    320     def __next__(self):

~/anaconda3/lib/python3.7/site-packages/torch/utils/data/sampler.py in __iter__(self)
    198     def __iter__(self):
    199         batch = []
--&gt; 200         for idx in self.sampler:
    201             batch.append(idx)
    202             if len(batch) == self.batch_size:

&lt;ipython-input-26-e18eba551d35&gt; in __iter__(self)
     89             else:
     90                 # the second unbalanced dataset is changed
---&gt; 91                 sampler = ExampleImbalancedDatasetSampler(cur_dataset)
     92             samplers_list.append(sampler)
     93             cur_sampler_iterator = sampler.__iter__()

&lt;ipython-input-26-e18eba551d35&gt; in __init__(self, dataset, indices, num_samples, callback_get_label)
     28         label_to_count = {}
     29         for idx in self.indices:
---&gt; 30             label = self._get_label(dataset, idx)
     31             if label in label_to_count:
     32                 label_to_count[label] += 1

&lt;ipython-input-26-e18eba551d35&gt; in _get_label(self, dataset, idx)
     63     """
     64     def _get_label(self, dataset, idx):
---&gt; 65         return dataset.samples[idx].item()
     66 
     67 

AttributeError: 'Subset' object has no attribute 'samples'
</code></pre>
<p>Can you suggest a solution or any other approach to achieve what I want?</p>
<p>TIA</p>

username: ptrblck
cooked: <p>You would most likely have to change the call in <code>_get_label</code> here:</p>
<pre><code class="lang-python">class ExampleImbalancedDatasetSampler(ImbalancedDatasetSampler):
    """
    ImbalancedDatasetSampler is taken from https://github.com/ufoym/imbalanced-dataset-sampler/blob/master/sampler.py
    In order to be able to show the usage of ImbalancedDatasetSampler in this example I am editing the _get_label
    to fit my datasets
    """
    def _get_label(self, dataset, idx):
        return dataset.samples[idx].item()
</code></pre>
<p>I haven’t checked the reference implementation, but based on the function name I assume you are supposed to return the target tensor here.</p>

username: abhi8569
cooked: <p><a class="mention" href="/u/ptrblck">@ptrblck</a> I am not sure what exactly you mean by target tensor. I have two dataset with different types of elements in it (dict and list). Do I need to check for the dataset and return tensor accordingly?</p>

username: ptrblck
cooked: <p>Based on the blog post you shared, it seems you are dealing with two datasets.<br>
One is balanced and uses the <code>RandomSampler</code>, while the other is imbalanced and calls into <code>ExampleImbalancedDatasetSampler</code>.</p>
<p>Inside the <code>ExampleImbalancedDatasetSampler</code>, <code>dataset.samples</code> is used, which is apparently raising the error.<br>
I’m not sure, what kind of datasets you are using, but you should change the <code>dataset.samples</code> call to whatever fits your dataset.</p>