fastai / fastcore

Python supercharged for the fastai library
http://fastcore.fast.ai
Apache License 2.0
954 stars 274 forks source link

explode_types() feeds retain_type() with surprising arguments. #539

Open fakedrake opened 8 months ago

fakedrake commented 8 months ago
data_block = DataBlock(
    blocks=(ImageBlock, CategoryBlock), 
    get_x=existing(ColReader('thumbnail_path')),
    get_y=ColReader('label'),
    splitter=RandomSplitter(),
    item_tfms=Resize(224),
    batch_tfms=aug_transforms()
)
train = data_block.dataloaders(train_df, bs=4)

train.show_batch(4)

Gets

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[20], line 11
      1 data_block = DataBlock(
      2     blocks=(ImageBlock, CategoryBlock), 
      3     get_x=existing(ColReader('thumbnail_path')),
   (...)
      7     batch_tfms=aug_transforms()
      8 )
      9 train = data_block.dataloaders(train_df, bs=4)
---> 11 train.show_batch(4)

File /opt/conda/lib/python3.10/site-packages/fastai/data/core.py:151, in TfmdDL.show_batch(self, b, max_n, ctxs, show, unique, **kwargs)
    149 if b is None: b = self.one_batch()
    150 if not show: return self._pre_show_batch(b, max_n=max_n)
--> 151 show_batch(*self._pre_show_batch(b, max_n=max_n), ctxs=ctxs, max_n=max_n, **kwargs)
    152 if unique: self.get_idxs = old_get_idxs

File /opt/conda/lib/python3.10/site-packages/fastai/data/core.py:131, in TfmdDL._pre_show_batch(self, b, max_n)
    129 def _pre_show_batch(self, b, max_n=9):
    130     "Decode `b` to be ready for `show_batch`"
--> 131     b = self.decode(b)
    132     if hasattr(b, 'show'): return b,None,None
    133     its = self._decode_batch(b, max_n, full=False)

File /opt/conda/lib/python3.10/site-packages/fastai/data/core.py:115, in TfmdDL.decode(self, b)
    112 def decode(self, 
    113     b # Batch to decode
    114 ):
--> 115     return to_cpu(self.after_batch.decode(self._retain_dl(b)))

File /opt/conda/lib/python3.10/site-packages/fastai/data/core.py:86, in TfmdDL._retain_dl(self, b)
     84 def _retain_dl(self,b):
     85     if not getattr(self, '_types', None): self._one_pass()
---> 86     return retain_types(b, typs=self._types)

File /opt/conda/lib/python3.10/site-packages/fastcore/dispatch.py:199, in retain_types(new, old, typs)
    197 def retain_types(new, old=None, typs=None):
    198     "Cast each item of `new` to type of matching item in `old` if it's a superclass"
--> 199     if not is_listy(new): return retain_type(new, old, typs)
    200     if typs is not None:
    201         if isinstance(typs, dict):

File /opt/conda/lib/python3.10/site-packages/fastcore/dispatch.py:193, in retain_type(new, old, typ, as_copy)
    191     typ = old if isinstance(old,type) else type(old)
    192 # Do nothing the new type is already an instance of requested type (i.e. same type)
--> 193 if typ==NoneType or isinstance(new, typ): return new
    194 return retain_meta(old, cast(new, typ), as_copy=as_copy)

TypeError: isinstance() arg 2 must be a type, a tuple of types, or a union

The problem seems to be that explode_types() sometimes returns a dictionary which surprises retain_type() with a non-listy type.

ipdb>  p typ
{<class 'tuple'>: [<class 'fastai.torch_core.TensorImage'>, <class 'fastai.torch_core.TensorCategory'>]}

I am new to fastai and struggling to understand how to fix this without breaking anything else. Any advice?