From 47454dc6af639f664214b3c7fdb96bb36e5b0eb6 Mon Sep 17 00:00:00 2001 From: myron Date: Wed, 28 Sep 2022 17:28:44 -0700 Subject: [PATCH 1/7] UpSample optional kernal_size for deconv mode Signed-off-by: myron --- monai/networks/blocks/upsample.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/monai/networks/blocks/upsample.py b/monai/networks/blocks/upsample.py index 68b7759a69..cd64b23397 100644 --- a/monai/networks/blocks/upsample.py +++ b/monai/networks/blocks/upsample.py @@ -40,6 +40,7 @@ def __init__( in_channels: Optional[int] = None, out_channels: Optional[int] = None, scale_factor: Union[Sequence[float], float] = 2, + kernel_size: Optional[Union[Sequence[float], float]] = None, size: Optional[Union[Tuple[int], int]] = None, mode: Union[UpsampleMode, str] = UpsampleMode.DECONV, pre_conv: Optional[Union[nn.Module, str]] = "default", @@ -54,6 +55,7 @@ def __init__( in_channels: number of channels of the input image. out_channels: number of channels of the output image. Defaults to `in_channels`. scale_factor: multiplier for spatial size. Has to match input size if it is a tuple. Defaults to 2. + kernel_size: kernel size used during UpsampleMode.DECONV. Defaults to `scale_factor`. size: spatial size of the output image. Only used when ``mode`` is ``UpsampleMode.NONTRAINABLE``. In torch.nn.functional.interpolate, only one of `size` or `scale_factor` should be defined, @@ -83,13 +85,21 @@ def __init__( if up_mode == UpsampleMode.DECONV: if not in_channels: raise ValueError(f"in_channels needs to be specified in the '{mode}' mode.") + + if not kernel_size: + kernel_size = scale_factor + kernel_size_ = ensure_tuple_rep(kernel_size, spatial_dims) + padding = tuple([(i-1)//2 for i in kernel_size_]) + self.add_module( "deconv", Conv[Conv.CONVTRANS, spatial_dims]( in_channels=in_channels, out_channels=out_channels or in_channels, - kernel_size=scale_factor_, + kernel_size=kernel_size_, stride=scale_factor_, + padding=padding, + output_padding=padding, bias=bias, ), ) From f4ae620869fc704c2f7ea0c19eb24a9afff554c7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 29 Sep 2022 00:33:14 +0000 Subject: [PATCH 2/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- monai/networks/blocks/upsample.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monai/networks/blocks/upsample.py b/monai/networks/blocks/upsample.py index cd64b23397..f6f0fc82fd 100644 --- a/monai/networks/blocks/upsample.py +++ b/monai/networks/blocks/upsample.py @@ -89,7 +89,7 @@ def __init__( if not kernel_size: kernel_size = scale_factor kernel_size_ = ensure_tuple_rep(kernel_size, spatial_dims) - padding = tuple([(i-1)//2 for i in kernel_size_]) + padding = tuple((i-1)//2 for i in kernel_size_) self.add_module( "deconv", @@ -98,7 +98,7 @@ def __init__( out_channels=out_channels or in_channels, kernel_size=kernel_size_, stride=scale_factor_, - padding=padding, + padding=padding, output_padding=padding, bias=bias, ), From 23fe9c5cc2278de588f61323baf52e1a34f214d7 Mon Sep 17 00:00:00 2001 From: myron Date: Fri, 30 Sep 2022 16:39:17 -0700 Subject: [PATCH 3/7] UpSample optional kernel_size for deconv mode. edit1 Signed-off-by: myron --- monai/networks/blocks/upsample.py | 12 ++++++++---- tests/test_upsample_block.py | 26 ++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/monai/networks/blocks/upsample.py b/monai/networks/blocks/upsample.py index f6f0fc82fd..357899eed6 100644 --- a/monai/networks/blocks/upsample.py +++ b/monai/networks/blocks/upsample.py @@ -87,9 +87,13 @@ def __init__( raise ValueError(f"in_channels needs to be specified in the '{mode}' mode.") if not kernel_size: - kernel_size = scale_factor - kernel_size_ = ensure_tuple_rep(kernel_size, spatial_dims) - padding = tuple((i-1)//2 for i in kernel_size_) + kernel_size_ = scale_factor_ + output_padding = padding = 0 + else: + kernel_size_ = ensure_tuple_rep(kernel_size, spatial_dims) + padding = tuple((k-1)//2 for k in kernel_size_) + output_padding = tuple(s - 1 - (k-1) % 2 for k,s in zip(kernel_size_, scale_factor_)) + self.add_module( "deconv", @@ -99,7 +103,7 @@ def __init__( kernel_size=kernel_size_, stride=scale_factor_, padding=padding, - output_padding=padding, + output_padding=output_padding, bias=bias, ), ) diff --git a/tests/test_upsample_block.py b/tests/test_upsample_block.py index fe27de65d5..709e0346ac 100644 --- a/tests/test_upsample_block.py +++ b/tests/test_upsample_block.py @@ -88,13 +88,35 @@ TEST_CASES_EQ.append(test_case) +TEST_CASES_EQ2 = [] +for s in range(2, 5): + for k in range(1, 7): + expected_shape = (16, 5, 4 * s, 5 * s, 6 * s) + for t in UpsampleMode: + test_case = [ + { + "spatial_dims": 3, + "in_channels": 3, + "out_channels": 5, + "mode": t, + "scale_factor": s, + "kernel_size": k, + "align_corners": False, + }, + (16, 3, 4, 5, 6), + expected_shape, + ] + TEST_CASES_EQ.append(test_case) + + + class TestUpsample(unittest.TestCase): - @parameterized.expand(TEST_CASES + TEST_CASES_EQ) + @parameterized.expand(TEST_CASES + TEST_CASES_EQ + TEST_CASES_EQ2) def test_shape(self, input_param, input_shape, expected_shape): net = UpSample(**input_param) with eval_mode(net): result = net(torch.randn(input_shape)) - self.assertEqual(result.shape, expected_shape) + self.assertEqual(result.shape, expected_shape, msg=str(input_param)) if __name__ == "__main__": From bdf7b9524cba75c77b4826e84b4cf6eaf194ed4f Mon Sep 17 00:00:00 2001 From: myron Date: Fri, 30 Sep 2022 16:50:16 -0700 Subject: [PATCH 4/7] UpSample optional kernel_size for deconv mode. edit2 Signed-off-by: myron --- monai/networks/blocks/upsample.py | 1 - tests/test_upsample_block.py | 1 - 2 files changed, 2 deletions(-) diff --git a/monai/networks/blocks/upsample.py b/monai/networks/blocks/upsample.py index 357899eed6..e256224fa4 100644 --- a/monai/networks/blocks/upsample.py +++ b/monai/networks/blocks/upsample.py @@ -94,7 +94,6 @@ def __init__( padding = tuple((k-1)//2 for k in kernel_size_) output_padding = tuple(s - 1 - (k-1) % 2 for k,s in zip(kernel_size_, scale_factor_)) - self.add_module( "deconv", Conv[Conv.CONVTRANS, spatial_dims]( diff --git a/tests/test_upsample_block.py b/tests/test_upsample_block.py index 709e0346ac..2f089ac8be 100644 --- a/tests/test_upsample_block.py +++ b/tests/test_upsample_block.py @@ -109,7 +109,6 @@ TEST_CASES_EQ.append(test_case) - class TestUpsample(unittest.TestCase): @parameterized.expand(TEST_CASES + TEST_CASES_EQ + TEST_CASES_EQ2) def test_shape(self, input_param, input_shape, expected_shape): From 3870509c4cd427f13fe923025c3da035c158c4d3 Mon Sep 17 00:00:00 2001 From: myron Date: Fri, 30 Sep 2022 16:55:14 -0700 Subject: [PATCH 5/7] UpSample optional kernel_size for deconv mode. edit3 format Signed-off-by: myron --- monai/networks/blocks/upsample.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monai/networks/blocks/upsample.py b/monai/networks/blocks/upsample.py index e256224fa4..bd220e9299 100644 --- a/monai/networks/blocks/upsample.py +++ b/monai/networks/blocks/upsample.py @@ -91,8 +91,8 @@ def __init__( output_padding = padding = 0 else: kernel_size_ = ensure_tuple_rep(kernel_size, spatial_dims) - padding = tuple((k-1)//2 for k in kernel_size_) - output_padding = tuple(s - 1 - (k-1) % 2 for k,s in zip(kernel_size_, scale_factor_)) + padding = tuple((k - 1) // 2 for k in kernel_size_) + output_padding = tuple(s - 1 - (k - 1) % 2 for k, s in zip(kernel_size_, scale_factor_)) self.add_module( "deconv", From 79b87508bde5dc61a9a3e285571da179295a192e Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sat, 1 Oct 2022 14:05:54 +0100 Subject: [PATCH 6/7] fixes typing Signed-off-by: Wenqi Li --- monai/networks/blocks/upsample.py | 4 ++-- tests/test_upsample_block.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/monai/networks/blocks/upsample.py b/monai/networks/blocks/upsample.py index bd220e9299..9c0afc714e 100644 --- a/monai/networks/blocks/upsample.py +++ b/monai/networks/blocks/upsample.py @@ -91,8 +91,8 @@ def __init__( output_padding = padding = 0 else: kernel_size_ = ensure_tuple_rep(kernel_size, spatial_dims) - padding = tuple((k - 1) // 2 for k in kernel_size_) - output_padding = tuple(s - 1 - (k - 1) % 2 for k, s in zip(kernel_size_, scale_factor_)) + padding = tuple((k - 1) // 2 for k in kernel_size_) # type: ignore + output_padding = tuple(s - 1 - (k - 1) % 2 for k, s in zip(kernel_size_, scale_factor_)) # type: ignore self.add_module( "deconv", diff --git a/tests/test_upsample_block.py b/tests/test_upsample_block.py index 2f089ac8be..f6bf5dc6ae 100644 --- a/tests/test_upsample_block.py +++ b/tests/test_upsample_block.py @@ -88,7 +88,7 @@ TEST_CASES_EQ.append(test_case) -TEST_CASES_EQ2 = [] +TEST_CASES_EQ2 = [] # type: ignore for s in range(2, 5): for k in range(1, 7): expected_shape = (16, 5, 4 * s, 5 * s, 6 * s) From b29add3d38d382bba6e1815b21c596d66d110057 Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sat, 1 Oct 2022 15:24:00 +0100 Subject: [PATCH 7/7] fixes downloading tests Signed-off-by: Wenqi Li --- tests/test_milmodel.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_milmodel.py b/tests/test_milmodel.py index ad04e96c60..3a6ea9a1bd 100644 --- a/tests/test_milmodel.py +++ b/tests/test_milmodel.py @@ -17,7 +17,7 @@ from monai.networks import eval_mode from monai.networks.nets import MILModel from monai.utils.module import optional_import -from tests.utils import test_script_save +from tests.utils import skip_if_downloading_fails, test_script_save models, _ = optional_import("torchvision.models") @@ -65,7 +65,8 @@ class TestMilModel(unittest.TestCase): @parameterized.expand(TEST_CASE_MILMODEL) def test_shape(self, input_param, input_shape, expected_shape): - net = MILModel(**input_param).to(device) + with skip_if_downloading_fails(): + net = MILModel(**input_param).to(device) with eval_mode(net): result = net(torch.randn(input_shape, dtype=torch.float).to(device)) self.assertEqual(result.shape, expected_shape)