From 69586492532c905f7ecf7a40f6f98a8421d0b0e1 Mon Sep 17 00:00:00 2001 From: chaliebudd Date: Mon, 29 Mar 2021 10:03:42 +0100 Subject: [PATCH 1/4] Fixing error in saving non-pytorch-variable parameters for backwards pass Signed-off-by: chaliebudd --- monai/networks/layers/filtering.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/monai/networks/layers/filtering.py b/monai/networks/layers/filtering.py index 83a33bc609..b47f6c13f7 100644 --- a/monai/networks/layers/filtering.py +++ b/monai/networks/layers/filtering.py @@ -47,15 +47,17 @@ class BilateralFilter(torch.autograd.Function): @staticmethod def forward(ctx, input, spatial_sigma=5, color_sigma=0.5, fast_approx=True): - ctx.save_for_backward(spatial_sigma, color_sigma, fast_approx) + ctx.ss = spatial_sigma + ctx.cs = color_sigma + ctx.fa = fast_approx output_data = _C.bilateral_filter(input, spatial_sigma, color_sigma, fast_approx) return output_data @staticmethod def backward(ctx, grad_output): - spatial_sigma, color_sigma, fast_approx = ctx.saved_variables + spatial_sigma, color_sigma, fast_approx = ctx.ss, ctx.cs, ctx.fa grad_input = _C.bilateral_filter(grad_output, spatial_sigma, color_sigma, fast_approx) - return grad_input + return grad_input, None, None, None class PHLFilter(torch.autograd.Function): From 3859d49449565f3e3350fc08b4c82031a2b01970 Mon Sep 17 00:00:00 2001 From: chaliebudd Date: Mon, 29 Mar 2021 11:52:14 +0100 Subject: [PATCH 2/4] Adding unit tests to check bilateral filter backwards runs Signed-off-by: chaliebudd --- tests/test_bilateral_approx_cpu.py | 18 ++++++++++++ tests/test_bilateral_approx_cuda.py | 18 ++++++++++++ tests/test_bilateral_precise.py | 43 ++++++++++++++++++++++++++--- 3 files changed, 75 insertions(+), 4 deletions(-) diff --git a/tests/test_bilateral_approx_cpu.py b/tests/test_bilateral_approx_cpu.py index 71cf53519c..e034f30169 100644 --- a/tests/test_bilateral_approx_cpu.py +++ b/tests/test_bilateral_approx_cpu.py @@ -14,6 +14,7 @@ import numpy as np import torch from parameterized import parameterized +from torch.autograd import gradcheck from monai.networks.layers.filtering import BilateralFilter from tests.utils import skip_if_no_cpp_extention @@ -376,6 +377,23 @@ def test_cpu_approx(self, test_case_description, sigmas, input, expected): # Ensure result are as expected np.testing.assert_allclose(output, expected, atol=1e-5) + @parameterized.expand(TEST_CASES) + def test_cpu_approx_backwards(self, test_case_description, sigmas, input, expected): + + # Params to determine the implementation to test + device = torch.device("cpu") + fast_approx = True + + # Prepare input tensor + input_tensor = torch.from_numpy(np.array(input)).to(dtype=torch.float, device=device) + input_tensor.requires_grad = True + + # Prepare args + args = (input_tensor, *sigmas, fast_approx) + + # Run grad check + gradcheck(BilateralFilter.apply, args, raise_exception=False) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_bilateral_approx_cuda.py b/tests/test_bilateral_approx_cuda.py index d0515d60e5..3deb70bc50 100644 --- a/tests/test_bilateral_approx_cuda.py +++ b/tests/test_bilateral_approx_cuda.py @@ -14,6 +14,7 @@ import numpy as np import torch from parameterized import parameterized +from torch.autograd import gradcheck from monai.networks.layers.filtering import BilateralFilter from tests.utils import skip_if_no_cpp_extention, skip_if_no_cuda @@ -381,6 +382,23 @@ def test_cuda_approx(self, test_case_description, sigmas, input, expected): # Ensure result are as expected np.testing.assert_allclose(output, expected, atol=1e-2) + @parameterized.expand(TEST_CASES) + def test_cpu_approx_backwards(self, test_case_description, sigmas, input, expected): + + # Params to determine the implementation to test + device = torch.device("cuda") + fast_approx = True + + # Prepare input tensor + input_tensor = torch.from_numpy(np.array(input)).to(dtype=torch.float, device=device) + input_tensor.requires_grad = True + + # Prepare args + args = (input_tensor, *sigmas, fast_approx) + + # Run grad check + gradcheck(BilateralFilter.apply, args, raise_exception=False) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_bilateral_precise.py b/tests/test_bilateral_precise.py index b02f3f04df..83d61f8bfe 100644 --- a/tests/test_bilateral_precise.py +++ b/tests/test_bilateral_precise.py @@ -14,6 +14,7 @@ import numpy as np import torch from parameterized import parameterized +from torch.autograd import gradcheck from monai.networks.layers.filtering import BilateralFilter from tests.utils import skip_if_no_cpp_extention, skip_if_no_cuda @@ -361,9 +362,9 @@ @skip_if_no_cpp_extention -class BilateralFilterTestCaseCpuPrecised(unittest.TestCase): +class BilateralFilterTestCaseCpuPrecise(unittest.TestCase): @parameterized.expand(TEST_CASES) - def test_cpu_precised(self, test_case_description, sigmas, input, expected): + def test_cpu_precise(self, test_case_description, sigmas, input, expected): # Params to determine the implementation to test device = torch.device("cpu") @@ -375,13 +376,30 @@ def test_cpu_precised(self, test_case_description, sigmas, input, expected): # Ensure result are as expected np.testing.assert_allclose(output, expected, atol=1e-5) +git + @parameterized.expand(TEST_CASES) + def test_cpu_precise_backwards(self, test_case_description, sigmas, input, expected): + + # Params to determine the implementation to test + device = torch.device("cpu") + fast_approx = False + + # Prepare input tensor + input_tensor = torch.from_numpy(np.array(input)).to(dtype=torch.float, device=device) + input_tensor.requires_grad = True + + # Prepare args + args = (input_tensor, *sigmas, fast_approx) + + # Run grad check + gradcheck(BilateralFilter.apply, args, raise_exception=False) @skip_if_no_cuda @skip_if_no_cpp_extention -class BilateralFilterTestCaseCudaPrecised(unittest.TestCase): +class BilateralFilterTestCaseCudaPrecise(unittest.TestCase): @parameterized.expand(TEST_CASES) - def test_cuda_precised(self, test_case_description, sigmas, input, expected): + def test_cuda_precise(self, test_case_description, sigmas, input, expected): # Skip this test if not torch.cuda.is_available(): @@ -398,6 +416,23 @@ def test_cuda_precised(self, test_case_description, sigmas, input, expected): # Ensure result are as expected np.testing.assert_allclose(output, expected, atol=1e-5) + @parameterized.expand(TEST_CASES) + def test_cuda_precise_backwards(self, test_case_description, sigmas, input, expected): + + # Params to determine the implementation to test + device = torch.device("cuda") + fast_approx = False + + # Prepare input tensor + input_tensor = torch.from_numpy(np.array(input)).to(dtype=torch.float, device=device) + input_tensor.requires_grad = True + + # Prepare args + args = (input_tensor, *sigmas, fast_approx) + + # Run grad check + gradcheck(BilateralFilter.apply, args, raise_exception=False) + if __name__ == "__main__": unittest.main() From ee0204c2433ca1c6461810200a4c603c16c7f73d Mon Sep 17 00:00:00 2001 From: chaliebudd Date: Mon, 29 Mar 2021 12:00:02 +0100 Subject: [PATCH 3/4] fixing typo introduced by merge Signed-off-by: chaliebudd --- tests/test_bilateral_precise.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_bilateral_precise.py b/tests/test_bilateral_precise.py index f129735587..8938072b6f 100644 --- a/tests/test_bilateral_precise.py +++ b/tests/test_bilateral_precise.py @@ -361,7 +361,7 @@ ] -@skip_if_no_cpp_extention +@skip_if_no_cpp_extension class BilateralFilterTestCaseCpuPrecise(unittest.TestCase): @parameterized.expand(TEST_CASES) def test_cpu_precise(self, test_case_description, sigmas, input, expected): @@ -396,7 +396,7 @@ def test_cpu_precise_backwards(self, test_case_description, sigmas, input, expec @skip_if_no_cuda -@skip_if_no_cpp_extention +@skip_if_no_cpp_extension class BilateralFilterTestCaseCudaPrecise(unittest.TestCase): @parameterized.expand(TEST_CASES) def test_cuda_precise(self, test_case_description, sigmas, input, expected): From e32d2274f732aca7aa0e517002d462c506acfd1d Mon Sep 17 00:00:00 2001 From: chaliebudd Date: Mon, 29 Mar 2021 12:04:43 +0100 Subject: [PATCH 4/4] code reformatting Signed-off-by: chaliebudd --- tests/test_bilateral_precise.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_bilateral_precise.py b/tests/test_bilateral_precise.py index 8938072b6f..df4d0c2500 100644 --- a/tests/test_bilateral_precise.py +++ b/tests/test_bilateral_precise.py @@ -376,7 +376,7 @@ def test_cpu_precise(self, test_case_description, sigmas, input, expected): # Ensure result are as expected np.testing.assert_allclose(output, expected, atol=1e-5) - + @parameterized.expand(TEST_CASES) def test_cpu_precise_backwards(self, test_case_description, sigmas, input, expected):