Data.normalize raises a RuntimeError

Hi,

I have my dataset folder organized in Imagenet format. On using ImageDataBunch.from_folder the dataset is loaded correctly (class names and count are correct). But when I try to normalize the data a RuntimeError is raised. @sgugger Could you please let me know what causes this kind of issue.

from fastai import *
from fastai.vision import *

data = ImageDataBunch.from_folder('./Images/', size=224)
data.normalize(imagenet_stats)

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-4-eb38bee88fda> in <module>
      1 data = ImageDataBunch.from_folder('./Images/', size=224)
----> 2 data.normalize(imagenet_stats)

~/anaconda3/envs/fastai/lib/python3.6/site-packages/fastai/vision/data.py in normalize(self, stats)
    340     def normalize(self, stats:Collection[Tensor]=None)->None:
    341         "Add normalize transform using `stats` (defaults to `DataBunch.batch_stats`)"
--> 342         stats = ifnone(stats, self.batch_stats())
    343         if getattr(self,'norm',False): raise Exception('Can not call normalize twice')
    344         self.norm,self.denorm = normalize_funcs(*stats)

~/anaconda3/envs/fastai/lib/python3.6/site-packages/fastai/vision/data.py in batch_stats(self, funcs)
    335         "Grab a batch of data and call reduction function `func` per channel"
    336         funcs = ifnone(funcs, [torch.mean,torch.std])
--> 337         x = self.valid_dl.one_batch()[0].cpu()
    338         return [func(channel_view(x), 1) for func in funcs]
    339 

~/anaconda3/envs/fastai/lib/python3.6/site-packages/fastai/basic_data.py in one_batch(self)
     57         self.num_workers = 0
     58         it = iter(self)
---> 59         try:     return next(it)
     60         finally: self.num_workers = w
     61 

~/anaconda3/envs/fastai/lib/python3.6/site-packages/fastai/basic_data.py in __iter__(self)
     50     def __iter__(self):
     51         "Process and returns items from `DataLoader`."
---> 52         for b in self.dl: yield self.proc_batch(b)
     53 
     54     def one_batch(self)->Collection[Tensor]:

~/anaconda3/envs/fastai/lib/python3.6/site-packages/torch/utils/data/dataloader.py in __next__(self)
    613         if self.num_workers == 0:  # same-process loading
    614             indices = next(self.sample_iter)  # may raise StopIteration
--> 615             batch = self.collate_fn([self.dataset[i] for i in indices])
    616             if self.pin_memory:
    617                 batch = pin_memory_batch(batch)

~/anaconda3/envs/fastai/lib/python3.6/site-packages/fastai/torch_core.py in data_collate(batch)
     89 def data_collate(batch:ItemsList)->Tensor:
     90     "Convert `batch` items to tensor data."
---> 91     return torch.utils.data.dataloader.default_collate(to_data(batch))
     92 
     93 def requires_grad(m:nn.Module, b:Optional[bool]=None)->Optional[bool]:

~/anaconda3/envs/fastai/lib/python3.6/site-packages/torch/utils/data/dataloader.py in default_collate(batch)
    230     elif isinstance(batch[0], container_abcs.Sequence):
    231         transposed = zip(*batch)
--> 232         return [default_collate(samples) for samples in transposed]
    233 
    234     raise TypeError((error_msg.format(type(batch[0]))))

~/anaconda3/envs/fastai/lib/python3.6/site-packages/torch/utils/data/dataloader.py in <listcomp>(.0)
    230     elif isinstance(batch[0], container_abcs.Sequence):
    231         transposed = zip(*batch)
--> 232         return [default_collate(samples) for samples in transposed]
    233 
    234     raise TypeError((error_msg.format(type(batch[0]))))

~/anaconda3/envs/fastai/lib/python3.6/site-packages/torch/utils/data/dataloader.py in default_collate(batch)
    207             storage = batch[0].storage()._new_shared(numel)
    208             out = batch[0].new(storage)
--> 209         return torch.stack(batch, 0, out=out)
    210     elif elem_type.__module__ == 'numpy' and elem_type.__name__ != 'str_' \
    211             and elem_type.__name__ != 'string_':

RuntimeError: invalid argument 0: Sizes of tensors must match except in dimension 0. Got 300 and 498 in dimension 2 at /opt/conda/conda-bld/pytorch-nightly_1539939344418/work/aten/src/TH/generic/THTensorMoreMath.cpp:1317

You didn’t specify any transforms which is why it doesn’t work. Put a least a crop so that it know how to get to the 224 by 224 size once it has resized the smallest dimension to 224.

And don’t forget not to @ person when a lot of people can actually answer you, please.

2 Likes

Thanks for the response, it works. Sorry for tagging you !!

I’m having a similar problem. I’m running the line below:

# Create the image data bunch
data = ImageDataBunch.from_folder(PATH, ds_fms=get_transforms(), size=112)
data.normalize(imagenet_stats)

And got the same error as Chaitanya, with the only difference that mine shows this:

invalid argument 0: Sizes of tensors must match except in dimension 0. Got 240 and 180 in dimension 3 at /opt/conda/conda-bld/pytorch-nightly_1540036376816/work/aten/src/TH/generic/THTensorMoreMath.cpp:1317

The data bunch creates without the normalize line - I can access other parts of the data bunch. This only errors when I try to normalize or show a batch.

OH FOR THE LOVE OF…

After almost two hours of bashing my head in on this error… I mis-spelled “ds_tfms”… forgot the t… ugh.

1 Like

It will be great if notebooks could point out this type of errors like other IDEs, however, it will be good idea to use the tab completion feature of jupyter notebooks and letting it guide us, rather than we typing it all ourselves.

The problem is that ds_tfms isn’t actually an argument of ImageDataBunch.from_folder; it’s a keyword argument that’s passed on. I’d be extremely surprised if any IDEs would pick this up.

In this particular case the call to ImageDataBunch.create could fail if its kwargs are Truthy and ds_tfms is Falsy (since otherwise they’re not used); but there may be other reasons to allow this behaviour (e.g. to have old code still run after a API change).