lr_find(learn)
? notlearn.lr_find()
? I guess you can use both, but I am not used to the way you used it.
just saw that this was the way shown in the last lesson… but it is new to me.
Oops - that wasn’t intentional. learn.lr_find
is recommended, but both are fine.
learn.lr_find gives the same error:
How may be debug this? I read somewhere we should convert the tensors to cpu and try. I tried doing that for data set and data bunch objects but got error saying the have no attribute as .cpu()
I think I have spotted the error. After visualising more of my data I see it is empty somehow:
I changed from bs 8 to 4 and now the finder gave me:
Scrolling all the way at the bottom of the error is :
So I guess there is some mismatch of shapes but don’t know where this happened and why the data was not read fully. There is an accompanying csv, I don’t know if that supplementary or any use for this challenge.
Maybe we should shift this to fastai users
Did you check you masks don’t have values of 0 and 255? That happens sometimes. If that’s the case, you should change the function that opens them to divide by 255. This is done by adding
...datasets(SegmentationDataset)
.setattr(mask_opener, partial(open_mask, div=True))
in the data block API. You are changing the function used to open the masks (mask_opener
) by changing the value of one of its argument (hence the partial) that’s called div
to True.
Since there are only two classes, the classes in the masks are exactly 0 and 255…
I was also running into this exact device-side assert error with a binary segmentation problem.
If your binary masks have values of 0 and 255 for the 2 classes like mine do, I can confirm that @sgugger’s suggestion to change the default behavior of mask_opener
to div=True
fixes that particular problem (by converting class “255” to class “1”).
A few other small points I’ve discovered while fixing this:
-
If you get a
cuda runtime error (59) : device-side assert triggered
, you have to restart the kernel or you’ll keep getting the same error when you try to create the Learner even after you’ve fixed the label problem. -
in fastai v1.0.21, the exact data block
.set_attr()
line that works for me is:
.set_attr(mask_opener=partial(open_mask, div=True))
-
The order of the functions called in the data block API matter. This works:
data = (src.datasets(SegmentationDataset, classes=codes)
.set_attr(mask_opener=partial(open_mask, div=True))
.transform(get_transforms(), size=size, tfm_y=True)
.databunch(bs=bs)
.normalize(imagenet_stats))
While this doesn’t:
data = (src.datasets(SegmentationDataset, classes=codes)
.transform(get_transforms(), size=size, tfm_y=True)
.set_attr(mask_opener=partial(open_mask, div=True))
.databunch(bs=bs)
.normalize(imagenet_stats))
I just pushed div
as an argument to SegmentDataset
since it seems a lot of people need it. So now,
data = (src.datasets(SegmentationDataset, classes=codes, div=True)
.transform(get_transforms(), size=size, tfm_y=True)
.databunch(bs=bs)
.normalize(imagenet_stats))
should work.
And hi Dave, nice to see you again
Yup this worked! Thanks
That error bothered me for a while. It works now. Thanks
Did anyone try to give a single class because because it is binary(it supposed to predict 0 or 1 for each pixel)?
hello
I am trying to do binary as well.
I am getting this error…Thanks
src = (ImageFileList.from_folder(path_img)
.label_from_func(get_y_fn))
data = (src.datasets(SegmentationDataset, classes=codes)
.transform(get_transforms(), size=size, tfm_y=True)
.databunch(bs=bs)
.normalize(imagenet_stats))
AttributeError Traceback (most recent call last)
in
----> 1 data = (src.datasets(SegmentationDataset, classes=codes)
2 .transform(get_transforms(), size=size, tfm_y=True)
3 .databunch(bs=bs)
4 .normalize(imagenet_stats))
AttributeError: ‘ImageLabelList’ object has no attribute ‘datasets’
@sgugger My mask has 0 and 255 as its values(binary segmentation). How do i use div = True for open_mask with SegmentationItemList for that 255 is converted to 1.
Just slightly change the source code of SegmentationLabelList in your custom SegmentationLL
class SegmentationLL(ImageItemList):
def __init__(self, items:Iterator, classes:Collection=None, **kwargs):
super().__init__(items, **kwargs)
self.classes,self.loss_func,self.create_func = classes,CrossEntropyFlat(),partial(open_mask, div=True)
self.c = len(self.classes)
def new(self, items, classes=None, **kwargs):
return self.__class__(items, ifnone(classes, self.classes), **kwargs)
Or even shorter:
class SegmentationLL(SegmentationItemList):
def __init__(self, items:Iterator, classes:Collection=None, **kwargs):
super().__init__(items, classes, **kwargs)
self.create_func = partial(open_mask, div=True)
@sgugger I defined a new class in my code as suggested. But i am getting name 'kwarg' is not defined
error. Where can i find the definition of kwarg
? What should i do?
It should be kwargs
instead kwarg
With a double **, I edited my post.
@sgugger here is my code used for segmentation. Weirdly i am getting very high validation loss in few epochs while training and dice accuracy are not bad. What could be the reason for this?
class SegmentationLabelList(ImageItemList):
def __init__(self, items:Iterator, classes:Collection=None, **kwargs):
super().__init__(items, **kwargs)
self.classes,self.loss_func,self.create_func = classes,CrossEntropyFlat(),partial(open_mask, div=True)
self.c = len(self.classes)
def new(self, items, classes=None, **kwargs):
return self.__class__(items, ifnone(classes, self.classes), **kwargs)
class SegmentationItemList(ImageItemList):
def __post_init__(self):
super().__post_init__()
self._label_cls = SegmentationLabelList
src = (SegmentationItemList.from_folder(path_img)
.random_split_by_pct(0.2)
.label_from_func(get_y_fn, classes=codes))
data = (src.transform(get_transforms(), size=size, tfm_y=True)
.databunch(bs=bs)
.normalize(imagenet_stats))
def dice(input:Tensor, targs:Tensor, iou:bool=True)->Rank0Tensor:
"Dice coefficient metric for binary target. If iou=True, returns iou metric, classic for segmentation problems."
n = targs.shape[0]
input = input.argmax(dim=1).view(n,-1)
targs = targs.view(n,-1)
intersect = (input*targs).sum().float()
union = (input+targs).sum().float()
if not iou: return 2. * intersect / union
else: return intersect / (union-intersect+1.0)
learn = Learner.create_unet(data, models.resnet34, metrics=dice)