This is a question that has been bothering me for a while. Ususally, I initialize both batch_trfms and item_trfms within the initialization of the datablock, e.g.
b = DataBlock(
blocks=(ImageBlock, CategoryBlock),
splitter=RandomSplitter(valid_pct=0.2, seed=42),
get_x=ColReader('objID', pref='/home/svu/e0148772/images-sdss/', suff='.jpg'),
get_y=ColReader('AGN'),
batch_tfms=[Normalize()],
item_trfms=[DihedralItem(p=1.)])
But when I used to initialize the trfms in dataloders as follows, the code would still run, w/o performing the actual transformations:
dl = ImageDataLoaders.from_dblock(b, df, bs=64, batch_tfms=[Normalize()], item_trfms=[DihedralItem(p=1.)])
So I checked the source code for ImageDataLoaders. In fastai/fastai/data/core.py:
@classmethod
def from_dblock(cls, dblock, source, path='.', bs=64, val_bs=None, shuffle=True, device=None, **kwargs):
return dblock.dataloaders(source, path=path, bs=bs, val_bs=val_bs, shuffle=shuffle, device=device, **kwargs)
and when I click on dblock.dataloaders, which goes to dataloaders(…) in fastai/fastai/data/block.py
def dataloaders(self, source, path='.', verbose=False, **kwargs):
dsets = self.datasets(source, verbose=verbose)
kwargs = {**self.dls_kwargs, **kwargs, 'verbose': verbose}
return dsets.dataloaders(path=path, after_item=self.item_tfms, after_batch=self.batch_tfms, **kwargs)
It seems that the trfms intialized in ImageDataLoaders will be performed, and in fact will override the trfms defined in the initialization of DataBlock. So why aren’t they performed?