Unet_binary segmentation

Agree, this is very helpful, got what I needed to work for Segmenting some cells. Did anyone try and deploy a serving of this? I can get it working locally on my Flask application but just including the above:

class SegLabelListCustom(SegmentationLabelList):
def open(self, fn): return open_mask(fn, div=True)

class SegItemListCustom(SegmentationItemList):
_label_cls = SegLabelListCustom

In my Flask app prior to loading the .pkl:

learn = load_learner(path, 'cell_export.pkl')

But when I try and deploy on Render (using Gunicorn), the same Flask app gives the following error:

  File "/opt/render/project/src/.venv/bin/gunicorn", line 10, in <module>
    sys.exit(run())
  File "/opt/render/project/src/.venv/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 61, in run
    WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()
  File "/opt/render/project/src/.venv/lib/python3.7/site-packages/gunicorn/app/base.py", line 223, in run
    super(Application, self).run()
  File "/opt/render/project/src/.venv/lib/python3.7/site-packages/gunicorn/app/base.py", line 72, in run
    Arbiter(self).run()
  File "/opt/render/project/src/.venv/lib/python3.7/site-packages/gunicorn/arbiter.py", line 60, in __init__
    self.setup(app)
  File "/opt/render/project/src/.venv/lib/python3.7/site-packages/gunicorn/arbiter.py", line 120, in setup
    self.app.wsgi()
  File "/opt/render/project/src/.venv/lib/python3.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
    self.callable = self.load()
  File "/opt/render/project/src/.venv/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 52, in load
    return self.load_wsgiapp()
  File "/opt/render/project/src/.venv/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 41, in load_wsgiapp
    return util.import_app(self.app_uri)
  File "/opt/render/project/src/.venv/lib/python3.7/site-packages/gunicorn/util.py", line 350, in import_app
    __import__(module)
  File "/opt/render/project/src/app.py", line 49, in <module>
    learn = load_learner(path, export_file_name)
  File "/opt/render/project/src/.venv/lib/python3.7/site-packages/fastai/basic_train.py", line 598, in load_learner
    state = torch.load(source, map_location='cpu') if defaults.device == torch.device('cpu') else torch.load(source)
  File "/opt/render/project/src/.venv/lib/python3.7/site-packages/torch/serialization.py", line 387, in load
    return _load(f, map_location, pickle_module, **pickle_load_args)
  File "/opt/render/project/src/.venv/lib/python3.7/site-packages/torch/serialization.py", line 574, in _load
    result = unpickler.load()
AttributeError: Can't get attribute 'SegItemListCustom' on <module '__main__' from '/opt/render/project/src/.venv/bin/gunicorn'>

It seems like Gunicorn is not reading the custom classes. I have been searching StackOverflow but have not found an answer.

has anybody tried comparing U-NET with Mask-RCNN ?. In fastai , why do we use U-NET for segmentation ?.

There is a paper which talks about an ensemble of U-NET and Mask-RCNN

1 Like

Performance edge. Have a look at the kaggle data science bowl solutions to compare. Ensembles of unet/maskrcnn in this and other segmentation challenges (carvana, airbus, etc) haven’t been top performing. https://www.kaggle.com/c/data-science-bowl-2018/discussion

1 Like

I am trying the following code:
class SegLabelListCustom(SegmentationLabelList):
def open(self, fn): return open_mask(fn, div=True)

class SegItemListCustom(SegmentationLabelList):
_label_cls = SegLabelListCustom

src = (SegItemListCustom.from_folder(path_img)
.split_by_idx(valid_idx)
.label_from_func(get_y_fn, classes=codes))

and get the following error:

Traceback (most recent call last):
File “C:\Users\Mehran\Anaconda2\envs\test2\lib\site-packages\IPython\core\interactiveshell.py”, line 3296, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File “”, line 11, in
.label_from_func(get_y_fn, classes=codes))
File “C:\Users\Mehran\Anaconda2\envs\test2\lib\site-packages\fastai\data_block.py”, line 468, in _inner
self.process()
File “C:\Users\Mehran\Anaconda2\envs\test2\lib\site-packages\fastai\data_block.py”, line 522, in process
for ds,n in zip(self.lists, [‘train’,‘valid’,‘test’]): ds.process(xp, yp, name=n)
File “C:\Users\Mehran\Anaconda2\envs\test2\lib\site-packages\fastai\data_block.py”, line 699, in process
self.x.process(xp)
File “C:\Users\Mehran\Anaconda2\envs\test2\lib\site-packages\fastai\data_block.py”, line 75, in process
for p in self.processor: p.process(self)
File “C:\Users\Mehran\Anaconda2\envs\test2\lib\site-packages\fastai\vision\data.py”, line 372, in process
def process(self, ds:ItemList): ds.classes,ds.c = self.classes,len(self.classes)
TypeError: object of type ‘NoneType’ has no len()

Im also running in to some headaches here,

See attached screenshot. Now im wondering if it’s better to just try and convert into 0s and 1s?

HI @bluesky314, I have the same issue. can you please put how you defined ‘src’ and ‘data’ variables? as Jeremy named them.

Does this work with dataframes? I applied all the fixes.

class SegLabelListCustom(SegmentationLabelList):
def open(self, fn): return open_mask(fn, div=True)

class SegItemListCustom(SegmentationItemList):
_label_cls = SegLabelListCustom

src = (SegItemListCustom.from_df(trnval_df, path=path, cols=‘filename_x’)
.split_none()
.label_from_df(cols=‘filename_y’))

I am getting:

~/anaconda3/envs//lib/python3.6/site-packages/fastai/data_block.py in process(self)
    529         "Process the inner datasets."
    530         xp,yp = self.get_processors()
--> 531         for ds,n in zip(self.lists, ['train','valid','test']): ds.process(xp, yp, name=n)
    532         #progress_bar clear the outputs so in some case warnings issued during processing disappear.
    533         for ds in self.lists:

~/anaconda3/envs//lib/python3.6/site-packages/fastai/data_block.py in process(self, xp, yp, name)
    694     def process(self, xp:PreProcessor=None, yp:PreProcessor=None, name:str=None):
    695         "Launch the processing on `self.x` and `self.y` with `xp` and `yp`."
--> 696         self.y.process(yp)
    697         if getattr(self.y, 'filter_missing_y', False):
    698             filt = array([o is None for o in self.y.items])

~/anaconda3/envs//lib/python3.6/site-packages/fastai/data_block.py in process(self, processor)
     81         if processor is not None: self.processor = processor
     82         self.processor = listify(self.processor)
---> 83         for p in self.processor: p.process(self)
     84         return self
     85 

~/anaconda3/envs//lib/python3.6/site-packages/fastai/vision/data.py in process(self, ds)
    370     "`PreProcessor` that stores the classes for segmentation."
    371     def __init__(self, ds:ItemList): self.classes = ds.classes
--> 372     def process(self, ds:ItemList):  ds.classes,ds.c = self.classes,len(self.classes)
    373 
    374 class SegmentationLabelList(ImageList):

TypeError: object of type 'NoneType' has no len()

If I call the code without .label_from_df(), it works, but I can’t get the labels. The cols in my df are basically the filepath to the images. My masks are 3-channel JPEG, binary mask with numbers 0 or 255.


I am facing this error when training segmentation, don’t know how to solve it please help @ptrampert @jeremy @sgugger

Add a breakpoint before the return via set_trace() and look what is in input and what in targs, as it is quite clear that the sizes are not compatible, but hard to say why without more info.

1 Like


more details about my problem, how to add a breakpoint before set_trace().sorry if my questions are too basic as i am a newbie i am finding hard to rectify the problem @ptrampert

As you are in a segmentation setting and your images have a size of 256 x 256, you have to predict 256*256 pixel values, which is the 65536 elements of targs. Not clear, why your input only has 512.

set_trace() so to say is your breakpoint. The program will go into debug mode from this line on and you can debug. Also have a look here:

https://docs.python.org/3/library/pdb.html


i did what you said i am getting this. i couldn’t find the problem @ptrampert @sgugger @init_27

Quick question:

Can someone explain (or point me to where there is an explanation) on why we need to define a new class around SegmentationImageList and SegmentationItemList for a binary segmentation problem? I am not seeing what these new classes are achieving.

I believe it is so we can set div=True to load the masks as a float between 0-1 instead of 0-255

1 Like

For binary if the classes are 0 and 255 it should work with div=True, yes. But if you have 0 and e.g. 2, it won’t work.

@ harshasatyavardhan Regarding the ste_trace(), you must place it at the spot where the problem is, means after the line targs = … and before the return line in the accuracy function.

1 Like


something strange thing happening when I am training my data set I can’t predict the iou and dice is not improving and acc_carvana is static .when I see the results the segmentation is not appearing @ptrampert @daveluo @digitalspecialists @sgugger @NicWick

Just for future reference, ImageItemList is renamed to ImageList. https://docs.fast.ai/vision.data.html#ImageList

1 Like

you might need more data. Try augmenting.

i have totally 600 images and 600 masks isnt it enough.its a medical dataset.but why the metrics are so different .iou and dice are showing zero and acc_carvana is static @harikrishnanrajeev

i did face similar situation before and adding more data helped. Try adding more data or do data augmentation. How many classes do you have ?.