How to get add aditional transform to get_transform in fastai?

I would like to add aditional augmenmentation this way:

   additional_aug=[zoom_crop(scale=(0.75,1.25), do_rand=False), 
                    brightness(), 
                    contrast()
                   ]
tfms = get_transforms(do_flip=True,flip_vert=True,max_lighting=0.2, xtra_tfms=additional_aug)

data = (ImageList.from_df(df=df,path='./',cols='path') 
        .split_by_rand_pct(0.2) 
        .label_from_df(cols='diagnosis',label_cls=FloatList) 
        .transform(tfms,size=sz,resize_method=ResizeMethod.SQUISH,padding_mode='zeros') 
        .databunch(bs=bs,num_workers=4) 
        .normalize(imagenet_stats)  
       )

But I get errors:

```
--------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/opt/conda/lib/python3.6/site-packages/fastai/data_block.py in _check_kwargs(ds, tfms, **kwargs)
    590         x = ds[0]
--> 591         try: x.apply_tfms(tfms, **kwargs)
    592         except Exception as e:

/opt/conda/lib/python3.6/site-packages/fastai/vision/image.py in apply_tfms(self, tfms, do_resolve, xtra, size, resize_method, mult, padding_mode, mode, remove_out)
    105         if resize_method <= 2 and size is not None: tfms = self._maybe_add_crop_pad(tfms)
--> 106         tfms = sorted(tfms, key=lambda o: o.tfm.order)
    107         if do_resolve: _resolve_tfms(tfms)

/opt/conda/lib/python3.6/site-packages/fastai/vision/image.py in <lambda>(o)
    105         if resize_method <= 2 and size is not None: tfms = self._maybe_add_crop_pad(tfms)
--> 106         tfms = sorted(tfms, key=lambda o: o.tfm.order)
    107         if do_resolve: _resolve_tfms(tfms)

AttributeError: 'list' object has no attribute 'tfm'

During handling of the above exception, another exception occurred:

Exception                                 Traceback (most recent call last)
<ipython-input-27-3daf86c69a96> in <module>
      2         .split_by_rand_pct(0.2)
      3         .label_from_df(cols='diagnosis',label_cls=FloatList)
----> 4         .transform(tfms,size=sz,resize_method=ResizeMethod.SQUISH,padding_mode='zeros')
      5         .databunch(bs=bs,num_workers=4)
      6         .normalize(imagenet_stats)

/opt/conda/lib/python3.6/site-packages/fastai/data_block.py in transform(self, tfms, **kwargs)
    500         if not tfms: tfms=(None,None)
    501         assert is_listy(tfms) and len(tfms) == 2, "Please pass a list of two lists of transforms (train and valid)."
--> 502         self.train.transform(tfms[0], **kwargs)
    503         self.valid.transform(tfms[1], **kwargs)
    504         if self.test: self.test.transform(tfms[1], **kwargs)

/opt/conda/lib/python3.6/site-packages/fastai/data_block.py in transform(self, tfms, tfm_y, **kwargs)
    719     def transform(self, tfms:TfmList, tfm_y:bool=None, **kwargs):
    720         "Set the `tfms` and `tfm_y` value to be applied to the inputs and targets."
--> 721         _check_kwargs(self.x, tfms, **kwargs)
    722         if tfm_y is None: tfm_y = self.tfm_y
    723         tfms_y = None if tfms is None else list(filter(lambda t: getattr(t, 'use_on_y', True), listify(tfms)))

/opt/conda/lib/python3.6/site-packages/fastai/data_block.py in _check_kwargs(ds, tfms, **kwargs)
    591         try: x.apply_tfms(tfms, **kwargs)
    592         except Exception as e:
--> 593             raise Exception(f"It's not possible to apply those transforms to your dataset:\n {e}")
    594 
    595 class LabelList(Dataset):

Exception: It's not possible to apply those transforms to your dataset:
 'list' object has no attribute 'tfm'
```

According to documentation xtra_tfms : Optional [ Collection [ Transform ]]= None ) → Collection [ Transform ]

How to get it work?

1 Like

zoom_crop returns a list so you should add a * before it to unlistify it:

additional_aug=[*zoom_crop(scale=(0.75,1.25), do_rand=False),...
2 Likes
additional_aug=[*zoom_crop(scale=(0.75,1.25), do_rand=False), 
                brightness(change=0.1), 
                contrast(scale=0.5)
               ]
tfms = get_transforms(do_flip=True,flip_vert=True,max_lighting=0.2,
                      xtra_tfms= additional_aug
                     ) 

That seems to solve only first problem, I then keep getting this error:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/opt/conda/lib/python3.6/site-packages/fastai/data_block.py in _check_kwargs(ds, tfms, **kwargs)
590 x = ds[0]
–> 591 try: x.apply_tfms(tfms, **kwargs)
592 except Exception as e:

/opt/conda/lib/python3.6/site-packages/fastai/vision/image.py in apply_tfms(self, tfms, do_resolve, xtra, size, resize_method, mult, padding_mode, mode, remove_out)
    106         tfms = sorted(tfms, key=lambda o: o.tfm.order)
--> 107         if do_resolve: _resolve_tfms(tfms)
    108         x = self.clone()

/opt/conda/lib/python3.6/site-packages/fastai/vision/image.py in _resolve_tfms(tfms)
    521     "Resolve every tfm in `tfms`."
--> 522     for f in listify(tfms): f.resolve()
    523 

/opt/conda/lib/python3.6/site-packages/fastai/vision/image.py in resolve(self)
    500                 rand_func = self.tfm.params[k]
--> 501                 self.resolved[k] = rand_func(*listify(v))
    502             # ...otherwise use the value directly

TypeError: log_uniform() missing 1 required positional argument: 'high'

During handling of the above exception, another exception occurred:

Exception                                 Traceback (most recent call last)
<ipython-input-29-8304c2f5defe> in <module>
      2         .split_by_rand_pct(0.2)
      3         .label_from_df(cols='diagnosis',label_cls=FloatList)
----> 4         .transform(tfms,size=sz,resize_method=ResizeMethod.SQUISH,padding_mode='zeros')
      5         .databunch(bs=bs,num_workers=4)
      6         .normalize(imagenet_stats)

/opt/conda/lib/python3.6/site-packages/fastai/data_block.py in transform(self, tfms, **kwargs)
    500         if not tfms: tfms=(None,None)
    501         assert is_listy(tfms) and len(tfms) == 2, "Please pass a list of two lists of transforms (train and valid)."
--> 502         self.train.transform(tfms[0], **kwargs)
    503         self.valid.transform(tfms[1], **kwargs)
    504         if self.test: self.test.transform(tfms[1], **kwargs)

/opt/conda/lib/python3.6/site-packages/fastai/data_block.py in transform(self, tfms, tfm_y, **kwargs)
    719     def transform(self, tfms:TfmList, tfm_y:bool=None, **kwargs):
    720         "Set the `tfms` and `tfm_y` value to be applied to the inputs and targets."
--> 721         _check_kwargs(self.x, tfms, **kwargs)
    722         if tfm_y is None: tfm_y = self.tfm_y
    723         tfms_y = None if tfms is None else list(filter(lambda t: getattr(t, 'use_on_y', True), listify(tfms)))

/opt/conda/lib/python3.6/site-packages/fastai/data_block.py in _check_kwargs(ds, tfms, **kwargs)
    591         try: x.apply_tfms(tfms, **kwargs)
    592         except Exception as e:
--> 593             raise Exception(f"It's not possible to apply those transforms to your dataset:\n {e}")
    594 
    595 class LabelList(Dataset):

Exception: It's not possible to apply those transforms to your dataset:
 log_uniform() missing 1 required positional argument: 'high'
1 Like

You need to pass ranges to brightness and contrast. So change=(0.,0.1) if you want a random number up to 0.1 or change=(0.1,0.1) if you really wanted 0.1 and nothing else.

2 Likes

It appears that brightness and contrast are controlled by the max_lighting argument. So there should be no need to pass them in as extra transforms.

Source:   
def get_transforms(... max_lighting:float=0.2... , xtra_tfms:...):
...
    if max_lighting:
        res.append(brightness(change=(0.5*(1-max_lighting), 0.5*(1+max_lighting)), p=p_lighting))
        res.append(contrast(scale=(1-max_lighting, 1/(1-max_lighting)), p=p_lighting))
 ...
1 Like