Custom dataloader and transform errors

username: Ashutosh_Mishra
cooked: <p>I have written a custom dataset class to load an image from a path along with two transform functions as given below:</p>
<pre><code>class TestDataset(torch.utils.data.Dataset):

def __init__(self, root, split, transform=None):
    self.image_path = list()
    for (dirpath, dirnames, filenames) in os.walk(root + split):
        self.image_path += [os.path.join(dirpath, file) for file in filenames if file.endswith(('.jpg','.png'))]
    self.transform = transform

def __getitem__(self,index):
    filename = self.image_path[index]
    with Image.open(filename) as f:
        image = f.convert('RGB')
    image = image.resize((640,480), Image.ANTIALIAS)
    if self.transform != None:
        image = self.transform(image)
    return image

def __len__(self):
    return len(self.image_path)

d_test = TestDataset(datadir, 'test', transform=ttransforms.Compose([ttransforms.ToTensor(), 
ttransforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))]))

loader_test = DataLoader(d_test, num_workers=4, batch_size=1, shuffle=False)
</code></pre>
<p>When I enumerate over the dataloader, I get the following error:</p>
<pre><code>for iter, img in enumerate(loader_test):
    img = img.cuda()
    model = model.cuda()
    #.........CODE .........#

   Traceback (most recent call last):
   File "test_script.py", line 53, in &lt;module&gt;
   for iter, img in enumerate(loader_test):
   File "/home/ashutosh.mishra/miniconda3/envs/pytorch/lib/python3.7/site- 
   packages/torch/utils/data/d$taloader.py", line 363, in __next__
   data = self._next_data()
   File "/home/ashutosh.mishra/miniconda3/envs/pytorch/lib/python3.7/site- 
   packages/torch/utils/data/d$taloader.py", line 989, in _next_data
   return self._process_data(data)
   File "/home/ashutosh.mishra/miniconda3/envs/pytorch/lib/python3.7/site- 
   packages/torch/utils/data/d$taloader.py", line 1014, in _process_data
   data.reraise()
   File "/home/ashutosh.mishra/miniconda3/envs/pytorch/lib/python3.7/site-packages/torch/_utils.py", 
   $ine 395, in reraise
   raise self.exc_type(msg)
   TypeError: Caught TypeError in DataLoader worker process 0.
   Original Traceback (most recent call last):
   File "/home/ashutosh.mishra/miniconda3/envs/pytorch/lib/python3.7/site- 
   packages/torch/utils/data/_$tils/worker.py", line 185, in _worker_loop
   data = fetcher.fetch(index)
   File "/home/ashutosh.mishra/miniconda3/envs/pytorch/lib/python3.7/site- 
   packages/torch/utils/data/_$tils/fetch.py", line 44, in fetch
   data = [self.dataset[idx] for idx in possibly_batched_index]
   File "/home/ashutosh.mishra/miniconda3/envs/pytorch/lib/python3.7/site- 
   packages/torch/utils/data/_$tils/fetch.py", line 44, in &lt;listcomp&gt;
   data = [self.dataset[idx] for idx in possibly_batched_index]
   File "/home/ashutosh.mishra/VPGNet-Pytorch/Exp7_unet/test_dataset.py", line 26, in __getitem__
   image = self.transform(image)
   File "/home/ashutosh.mishra/VPGNet-Pytorch/Exp7_unet/test_transform.py", line 67, in __call__
   args = t(*args)
   TypeError: __call__() takes 2 positional arguments but 4 were given
</code></pre>
<p>My transform compose looks like this:</p>
<pre><code>class Compose(object):
"""Composes several transforms together."""

def __init__(self, transforms):
    self.transforms = transforms

def __call__(self, *args):
    for t in self.transforms:
         args = t(*args)
    return args
</code></pre>
<p>I am not able to figure out what is the source of the error since we load single images in the dataloader and enumerate on it. Apart from it, the transforms compose is the standard class which is used to compose different transformations.</p>

username: ptrblck
cooked: <aside class="quote no-group" data-username="Ashutosh_Mishra" data-post="1" data-topic="99768">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/ashutosh_mishra/48/14048_2.png" class="avatar"> Ashutosh_Mishra:</div>
<blockquote>
<p>Apart from it, the transforms compose is the standard class which is used to compose different transformations.</p>
</blockquote>
</aside>
<p>It’s not completely identical, since you are using <code>*args</code> instead of <code>img</code>, which will unwrap the image tensor.<br>
I.e. the error is raised in the second transformation, which will use <code>args</code> to pass an image tensor in the shape <code>[channels, height, width]</code> to <code>Normalize</code>. Using <code>t(*args)</code> will unwrap the image tensor in <code>dim0</code> and if it’s containing 3 channels, you’ll get the raised error.</p>
<p>What’s your use case to reimplement <code>transforms.Compose</code> in this way?</p>

username: Ashutosh_Mishra
cooked: <p>Thanks for your reply. I already had the transform file having different transforms hence didn’t use inbuilt torchvision one. I actually checked upon my torchvision version installed and it gives the following error</p>
<pre><code>AttributeError: module 'torchvision.transforms' has no attribute 'Compose' 
</code></pre>
<p>But, changing *args to image in the compose function worked as required.<br>
Thanks again!</p>

username: ptrblck
cooked: <p>Which <code>torchvision</code> version are you using? I would have guessed <code>Compose</code> was added pretty early.</p>