Fastai v2 vision

Got it. Just wanted to be sure. Thank you!

@muellerzr you can use DALI to do this, BTW.

1 Like

Hi everyone,

Iā€™m following Camvid Image Segmentation tutorial but on a different binary dataset, which has mask labels that are still in [0; 255] scale. I want to normalize it to [0; 1] so that I can continue the workflow in the tutorial. Is there any way to do it?

I guess you just need to divide the values in the mask by 255.

Yes but I donā€™t know yet how to insert this step to the workflow of DataBlock

Can you share a link to your dataset? I will try.

The dataset is here. I really appreciate your support.

I was looking at the differences between the new versions of xresnet and noticed something that seemed a bit odd. The Self-Attention Layer gets placed in the same location for xresnet50 and xresnet101, despite the models varying in length. However, the Self-Attention Layer is placed in different locations in xresnet50, xresnet50_deep and xresnet50_deeper due to sa=sa and i==len(layers)-4 in lines 33-35 in xresnet.py:

blocks = [self._make_layer(ni=block_szs[i], nf=block_szs[i+1], blocks=l,
						   stride=1 if i==0 else 2, sa=sa and i==len(layers)-4, **kwargs)
		  for i,l in enumerate(layers)]

For the non-deep versions of xresnet50 & 101 the Self-Attention Layer is placed after the third ResBlock, and if I counted correctly itā€™s placed after the 13th ResBlock in xresnet50_deep. Is that correct?

Hello. What is the easiest way of swapping a standard pytorch dataloader into the DataBunch format? I have tried a couple of ways (documented in issues on Github) but all of them ran into a wall

See this notebook here @leaf:

Hi @muellerzr thank you so much for your help.

I have replicated an element of the DataLoader using MNIST, but I still cannot e.g. show_batch on neither the DataBunch nor any of its attributes. I would like to see if the data is loaded correctly.

Can you show your code along with the error? :slight_smile:

So I tried a bunch of variants:

import torchvision ast tv

kwargs = {'num_workers': 1, 'pin_memory': True}
train_loader = torch.utils.data.DataLoader(
    tv.datasets.MNIST('../data', train=True, download=True, transform=tv.transforms.Compose([
        tv.transforms.ToTensor(), tv.transforms.Normalize((0.1307,), (0.3081,))
    ])),
    batch_size=32, shuffle=True, **kwargs)

db_mnist = DataBunch(train_loader).cuda()

Most naively: db_mnist.show_batch() But I have also tried running it on db_mnist.train_ds and train_dl.

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-51-bc9d47422ad9> in <module>
----> 1 db_mnist.show_batch()

~/daisy-gan/venv/lib/python3.6/site-packages/fastcore/foundation.py in __getattr__(self, k)
    221             attr = getattr(self,self._default,None)
    222             if attr is not None: return getattr(attr, k)
--> 223         raise AttributeError(k)
    224     def __dir__(self): return custom_dir(self, self._dir() if self._xtra is None else self._dir())
    225 #     def __getstate__(self): return self.__dict__

AttributeError: show_batch

I will try running other examples in that part of repo and will report back.

EDIT 2:

When I try to load the data this way:

db_mnist = DataBlock(blocks=(ImageBlock))
db_mnist.databunch(train_loader)

I get the following error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-61-48884d511190> in <module>
      1 db_mnist = DataBlock(blocks=(ImageBlock))
----> 2 db_mnist.databunch(train_loader)
      3 dir(db_mnist)

~/daisy-gan/venv/lib/python3.6/site-packages/fastai2/data/block.py in databunch(self, source, path, type_tfms, item_tfms, batch_tfms, **kwargs)
     80 
     81     def databunch(self, source, path='.', type_tfms=None, item_tfms=None, batch_tfms=None, **kwargs):
---> 82         dsrc = self.datasource(source, type_tfms=type_tfms)
     83         item_tfms  = _merge_tfms(self.default_item_tfms,  item_tfms)
     84         batch_tfms = _merge_tfms(self.default_batch_tfms, batch_tfms)

~/daisy-gan/venv/lib/python3.6/site-packages/fastai2/data/block.py in datasource(self, source, type_tfms)
     77         type_tfms = L([self.default_type_tfms, type_tfms, labellers]).map_zip(
     78             lambda tt,tfm,l: L(l) + _merge_tfms(tt, tfm))
---> 79         return DataSource(items, tfms=type_tfms, splits=splits, dl_type=self.dl_type, n_inp=self.n_inp)
     80 
     81     def databunch(self, source, path='.', type_tfms=None, item_tfms=None, batch_tfms=None, **kwargs):

~/daisy-gan/venv/lib/python3.6/site-packages/fastai2/data/core.py in __init__(self, items, tfms, tls, n_inp, dl_type, **kwargs)
    233     def __init__(self, items=None, tfms=None, tls=None, n_inp=None, dl_type=None, **kwargs):
    234         super().__init__(dl_type=dl_type)
--> 235         self.tls = L(tls if tls else [TfmdList(items, t, **kwargs) for t in L(ifnone(tfms,[None]))])
    236         self.n_inp = (1 if len(self.tls)==1 else len(self.tls)-1) if n_inp is None else n_inp
    237 

~/daisy-gan/venv/lib/python3.6/site-packages/fastai2/data/core.py in <listcomp>(.0)
    233     def __init__(self, items=None, tfms=None, tls=None, n_inp=None, dl_type=None, **kwargs):
    234         super().__init__(dl_type=dl_type)
--> 235         self.tls = L(tls if tls else [TfmdList(items, t, **kwargs) for t in L(ifnone(tfms,[None]))])
    236         self.n_inp = (1 if len(self.tls)==1 else len(self.tls)-1) if n_inp is None else n_inp
    237 

~/daisy-gan/venv/lib/python3.6/site-packages/fastcore/foundation.py in __call__(cls, x, *args, **kwargs)
     39             return x
     40 
---> 41         res = super().__call__(*((x,) + args), **kwargs)
     42         res._newchk = 0
     43         return res

~/daisy-gan/venv/lib/python3.6/site-packages/fastai2/data/core.py in __init__(self, items, tfms, use_list, do_setup, as_item, split_idx, train_setup, splits, types)
    169                  splits=None, types=None):
    170         super().__init__(items, use_list=use_list)
--> 171         self.splits = L([slice(None),[]] if splits is None else splits).map(mask2idxs)
    172         if isinstance(tfms,TfmdList): tfms = tfms.tfms
    173         if isinstance(tfms,Pipeline): do_setup=False

~/daisy-gan/venv/lib/python3.6/site-packages/fastcore/foundation.py in map(self, f, *args, **kwargs)
    360              else f.format if isinstance(f,str)
    361              else f.__getitem__)
--> 362         return self._new(map(g, self))
    363 
    364     def filter(self, f, negate=False, **kwargs):

~/daisy-gan/venv/lib/python3.6/site-packages/fastcore/foundation.py in _new(self, items, *args, **kwargs)
    313     @property
    314     def _xtra(self): return None
--> 315     def _new(self, items, *args, **kwargs): return type(self)(items, *args, use_list=None, **kwargs)
    316     def __getitem__(self, idx): return self._get(idx) if is_indexer(idx) else L(self._get(idx), use_list=None)
    317     def copy(self): return self._new(self.items.copy())

~/daisy-gan/venv/lib/python3.6/site-packages/fastcore/foundation.py in __call__(cls, x, *args, **kwargs)
     39             return x
     40 
---> 41         res = super().__call__(*((x,) + args), **kwargs)
     42         res._newchk = 0
     43         return res

~/daisy-gan/venv/lib/python3.6/site-packages/fastcore/foundation.py in __init__(self, items, use_list, match, *rest)
    304         if items is None: items = []
    305         if (use_list is not None) or not _is_array(items):
--> 306             items = list(items) if use_list else _listify(items)
    307         if match is not None:
    308             if is_coll(match): match = len(match)

~/daisy-gan/venv/lib/python3.6/site-packages/fastcore/foundation.py in _listify(o)
    240     if isinstance(o, list): return o
    241     if isinstance(o, str) or _is_array(o): return [o]
--> 242     if is_iter(o): return list(o)
    243     return [o]
    244 

~/daisy-gan/venv/lib/python3.6/site-packages/fastcore/foundation.py in __call__(self, *args, **kwargs)
    206             if isinstance(v,_Arg): kwargs[k] = args.pop(v.i)
    207         fargs = [args[x.i] if isinstance(x, _Arg) else x for x in self.pargs] + args[self.maxi+1:]
--> 208         return self.fn(*fargs, **kwargs)
    209 
    210 # Cell

~/daisy-gan/venv/lib/python3.6/site-packages/fastcore/foundation.py in mask2idxs(mask)
    256     if len(mask)==0: return []
    257     it = mask[0]
--> 258     if hasattr(it,'item'): it = it.item()
    259     if isinstance(it,(bool,NoneType,np.bool_)): return [i for i,m in enumerate(mask) if m]
    260     return [int(i) for i in mask]

ValueError: only one element tensors can be converted to Python scalars

Which is an error I got a bunch of times, so I reckon maybe that is an issue.

@sgugger I think I need some advice on what to do here. (back to the heatmap issue). So say I want my image to go through and transform, adjust the TensorPointā€™s accordingly, and then go from there. I currently have my setup to be afterwards (in the PointScaler) to add a generateMaps call. However if I try this and grab a batch it doesnā€™t seem to apply the scaling (and heatmap generation)? What is the behavior supposed to be?

IE something like this:

#export
class HeatmapScaler(Transform):
    "Scale a tensor representing points"
    order = 1
    def __init__(self, do_scale=True, y_first=False): 
      self.do_scale,self.y_first = do_scale,y_first
      self.sig = 1
    def _grab_sz(self, x):
        self.sz = [x.shape[-1], x.shape[-2]] if isinstance(x, Tensor) else x.size
        return x
    
    def _get_sz(self, x):
        sz = x.get_meta('img_size')
        assert sz is not None or self.sz is not None, "Size could not be inferred, pass it in the init of your TensorPoint with `img_size=...`"
        return self.sz if sz is None else sz
    
    def setups(self, dl):
        its = dl.do_item(0)
        for t in its:
            if isinstance(t, TensorPoint): self.c = t.numel()
    
    def encodes(self, x:(PILBase,TensorImageBase)): return self._grab_sz(x)
    def decodes(self, x:(PILBase,TensorImageBase)): return self._grab_sz(x)
    
    def encodes(self, x:TensorPoint): return _scale_pnts(x, self._get_sz(x), self.do_scale, self.y_first)
    def decodes(self, x:TensorPoint): return _unscale_pnts(x.view(-1, 2), self._get_sz(x))

    def encodes(self, x:TensorHeatmap): return generateMaps(x, self.sig, self._get_sz(x))
    def decodes(self, x:TensorHeatmap): return generateMaps(x, self.sig, self._get_sz(x))

Would one_batch not show this change/transform due to it possibly going back as soon as something is visible? And if not, where would I need to go to see this :slight_smile:

@leaf The show_batch method only works with DataBunch built using the fastai library. We canā€™t magically know those tensors represent images and categories here. This DataBunch will work for training, but not the visualization methods.

For the second way, you should simply look at the examples in this notebook, there is one that loads MNIST. In general, a DataBlock needs more information than that.

@muellerzr
I donā€™t understand your problem.

So I set it up to where my GuassianBlock looks like so:

GaussianBlock = TransformBlock(type_tfms=TensorPoint.create, item_tfms=HeatmapScaler)

When I then datablock and bunch it and look at the yā€™s of my batch, I just see the scaled points, not the heatmaps. Did I set up my encodes/decodes correctly above to where it should be generating them upon a call to batch? As it seems to not be doing so (generating the heatmaps)

This also is dynamically generating my y's (take new points and make a new heatmap each time we transform the image) - which I think may be the issue

Edit: I also tried doing as_item=False

I donā€™t see any TensorHeatMap type so Iā€™m not sure how you expect this particular encodes/decodes function to be called.

Ah, so if I want it to go (off of a TensorPoint) I should change the encodes/decodes to be x:TensorPoint so it will call it?

Yes, the encodes/decodes method called is the one corresponding to the type of the object passed.

1 Like

Thank you! How do I ensure itā€™s grabbing what the new transformed image size is? As if I do something like so (assume GaussianBlock is now just with type_tfms=TensorPoint.create, hence why I call HeatmapScaler())

dblock.databunch(path, item_tfms=[Resize(224), HeatmapScaler()]

It doesnā€™t seem to be using the newly transformed size but instead the original image size. (Iā€™m using self.get_sz)

I can get around this by passing in a size to HeatmapScaler but it would be nice to know if there is a way to get this without doing so :slight_smile: