BloodAxe / pytorch-toolbelt

PyTorch extensions for fast R&D prototyping and Kaggle farming
MIT License
1.52k stars 122 forks source link

Is compute_pyramid_patch_weight_loss correctly imlemented? #23

Closed ternaus closed 4 years ago

ternaus commented 5 years ago

https://github.com/BloodAxe/pytorch-toolbelt/blob/develop/pytorch_toolbelt/inference/tiles.py#L33 can be deleted.

https://github.com/BloodAxe/pytorch-toolbelt/blob/develop/pytorch_toolbelt/inference/tiles.py#L28 https://github.com/BloodAxe/pytorch-toolbelt/blob/develop/pytorch_toolbelt/inference/tiles.py#L29

are never updated and stay zero?

P.S. Numpy is very slow. replacing sqrt and square speeds things up a lot.

sayakgis commented 4 years ago

I was trying to use ImageSlicer and CudaTileMerger for inference on big image, I trained UNET(RN34) with multiple channels as classes, using the ImageSlicer and CudaTileMerger gives abnormal result as seen in the attached snap, could you please suggest if I am missing something?

As seen on the comparison image many features which got extracted on simple mosaic method (stacking arrays without stride/overlap) which goes missing/improper shape using toolbelt. compare

ksenobojca commented 4 years ago

Try to normalize the data you put to integrate_batch (your model output) - apply softmax there. (Merger calculates weighted average, so it's a problem if for some reason your data is not normalized between tiles). If that does not help, check if the problem is only on image borders. There are minor issues on tiles lying on image borders (your problem looks different, but...). This is how it merges outputs of single color. _merge_pyramid For example, at the bottom, between white and black there is (more or less) constant gray and preferable would be smooth gradient. Unfortunately I don't think there is an easy fix for that... (but depending on preference it can be slightly improved)

BloodAxe commented 4 years ago

Hi! Thanks for pointing out for this issue. Will investigate that.

Meanwhile, you can use simple mean averaging instead pyramid, by sending np.ones(...) to weight= argument while creating CudaTileMerger and ImageSlicer. This should eliminate this artifacts.

ksenobojca commented 4 years ago

Have you tried mean and it helped? (because my intuition suggests it should make things worse - unless there is really a bug I did not stumble upon yet)

BloodAxe commented 4 years ago

I use mean averaging all the time without any issues. What is very important in tiled inference - make tiles overlap. In this way, edge effect can be dampened a lot. ImageSlicer(tile_size=512, tile_step=256, weight="mean") works best for me.

ksenobojca commented 4 years ago

@BloodAxe FYI - I believe following weighting is better than current pyramid (image above) implementation: x = np.arange(width) + 0.5 y = np.arange(height) + 0.5 De_x = np.minimum(x, width - x) De_y = np.minimum(y, height - y) res = De_x[np.newaxis].transpose() * De_y This code produces: _merge_test_1 You can also add more weight to centers of tiles by np.square(res), which produces: _merge_test In my opinion both of them look better than original one.

sayakgis commented 4 years ago

I was trying to use ImageSlicer and CudaTileMerger for inference on big image, I trained UNET(RN34) with multiple channels as classes, using the ImageSlicer and CudaTileMerger gives abnormal result as seen in the attached snap, could you please suggest if I am missing something?

As seen on the comparison image many features which got extracted on simple mosaic method (stacking arrays without stride/overlap) which goes missing/improper shape using toolbelt. compare

This issue got resolve with weight='mean', however actually the problem is not from the merger function, i use fastai unet predictions and wrapped under Cudatilemerger. And there was bug in my Windows version of code implementation, however in linuxvm is working fine on it.