Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Aggregator smaller model outputs - Ready to be reviewed #1002

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

wahabk
Copy link
Contributor

@wahabk wahabk commented Nov 20, 2022

This is to reference #{1001}.

I have described the issue and planned fix in detail I believe, this is a draft PR to ask for some help

I have made most changes I believe, but this is a broken draft to show you my idea, let me know if the assertions are insufficient or if argument/attribute names are not clear

The bit I'm confused with is the subject padding, the subject is now forced to be padded and the padding is set to be at least the difference between input and output. and the final aggregator output tensor isn't padded

So say I have an input tensor with shape (128.128.128) , with a patch_size of (64,64,64) and a model output size of (60,60,60)

The patch_difference is set to be (4,4,4) and overlap is made to be at least equal to this, when the subject is padded in the GridSampler does that mean it's shape is now (136,136,136)?

Description
#1001

Checklist

  • I have read the CONTRIBUTING docs and have a developer setup (especially important are pre-commitand pytest)
  • Non-breaking change (would not break existing functionality)
  • Breaking change (would cause existing functionality to change)
  • Tests added or modified to cover the changes
  • Integration tests passed locally by running pytest
  • In-line docstrings updated
  • Documentation updated, tested running make html inside the docs/ folder
  • This pull request is ready to be reviewed
  • If the PR is ready and there are multiple commits, I have squashed them and force-pushed

check patch_size v patch_size in init hann
check _crop_patch for Volume_padded
and if overlap is bigger than patch_diff
@codecov
Copy link

codecov bot commented Nov 27, 2022

Codecov Report

Merging #1002 (df0eca3) into main (aa4d609) will increase coverage by 0.03%.
The diff coverage is 89.65%.

@@            Coverage Diff             @@
##             main    #1002      +/-   ##
==========================================
+ Coverage   86.47%   86.51%   +0.03%     
==========================================
  Files          91       91              
  Lines        5774     5798      +24     
==========================================
+ Hits         4993     5016      +23     
- Misses        781      782       +1     
Impacted Files Coverage Δ
src/torchio/data/sampler/grid.py 97.77% <85.71%> (-2.23%) ⬇️
src/torchio/data/inference/aggregator.py 96.12% <93.33%> (-0.52%) ⬇️
...hio/transforms/augmentation/spatial/random_flip.py 100.00% <0.00%> (+2.85%) ⬆️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

to depend  on  patch_diffs  and model_output_size

Expanded test_inference for different overlap modes

Tests now working except for hann
Fixed for average but other crop and hann broken
check patch_size v patch_size in init hann
check _crop_patch for Volume_padded
and if overlap is bigger than patch_diff

changed crop_patch and hann window

to depend  on  patch_diffs  and model_output_size

Expanded test_inference for different overlap modes

Tests now working except for hann

add docstring
@wahabk
Copy link
Contributor Author

wahabk commented Nov 29, 2022

This fixes #1001.

I have described the issue and in detail I believe #1001, I think this is PR is ready to be merged except for the final questions. I'm still getting my feet wet with PRs so would appreciate some guidance.

TLDR for why this is important:

I believe tio grid sampling and aggregating should be able to handle smaller model outputs. My model predictions are terrible even with averaging or hann windowing. Unfortunately most popular model libraries (such as the great monai) only provide models with the same output size and input. But it is crucial in my application to let the model see a bigger input ROI than semantic label outputs - by padding convolutions, as this gives context for the prediction. The original unet paper uses padded convolutions for smaller outputs than inputs.

Description

Summary of changes:

  • Add argument to GridSampler called model_output_size in case it is smaller than patch_size
  • This then computes patch_diffs which is the difference between them
  • GridSampler now makes sure that overlap_size is at least the same as patch_diffs
  • The locations are changed to fit the smaller patch_size
  • If overlap_mode is 'crop' it changes GridAggregator._crop_patch to only crop half_overlap - patch_diffs
  • If overlap_mode is 'hann' it makes the hann window of shape model_output_size instead of patch_size

Final questions before you agree:

  • The reason this bug was hidden from me is because the assertion in GridAggregator.add_batch checks target_spatial_shape from the provided batch, and not from self.patch_size. I belive this should be changed?
  • Does the kwarg name model_output_size make sense?
  • Are my new assertions thorough enough? Particularly in GridSampler.__init__() and GridAggregator.add_batch()
  • I have added a for loop in test_inference.py and test_inference_smaller.py that checks for different overlap_modes, however, the default tests fail under overlap mode 'hann'

Checklist

  • I have read the CONTRIBUTING docs and have a developer setup (especially important are pre-commitand pytest)
  • Non-breaking change (would not break existing functionality)
  • Breaking change (would cause existing functionality to change)
  • Tests added or modified to cover the changes
  • Integration tests passed locally by running pytest
  • In-line docstrings updated
  • Documentation updated, tested running make html inside the docs/ folder
  • This pull request is ready to be reviewed
  • If the PR is ready and there are multiple commits, I have squashed them and force-pushed

@wahabk wahabk marked this pull request as ready for review November 29, 2022 15:53
@wahabk
Copy link
Contributor Author

wahabk commented Nov 29, 2022

@fepegar This is ready now when you have time to review. Please read the second comment, the first was the draft PR.

I tried squashing my commits using the tutorial, did it work correctly?

Any edits or requests you have in mind let me know and I will edit the PR.

@wahabk wahabk changed the title Aggregator smaller model outputs - draft edits to show where to make changes Aggregator smaller model outputs - Ready to be reviewed Dec 14, 2022
@fepegar
Copy link
Owner

fepegar commented Feb 11, 2023

Hi, @wahabk. Thanks for the PR. Apologies for the delay. I will take a look at all this as soon as possible.

from ...utils import TorchioTestCase


class TestInference(TorchioTestCase):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can add a test in the other file instead of creating this file which looks very similar.

for overlap_mode in [
'average',
'crop',
]: # not checking for 'hann' since assertiion fails
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know why the assertion fails?

self.padding_mode = 'constant'
self.patch_diffs = (
np.array(patch_size) - np.array(self.model_output_size)
) // 2
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the differences are not divisible by 2?

# but remove input and output patch_diffs
# If patch_overlap is not bigger than patch_diffs.
# No need for cropping if output size is smaller
crop_ini = half_overlap.copy() - patch_diffs
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this add instead of substract? Maybe I've misunderstood.

target_spatial_shape = tuple(patch_sizes[0])
if input_spatial_shape != target_spatial_shape:
# Should target size be self.patch_size?
target_spatial_shape = tuple(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it a tuple with only one element?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants