Repository: Project-MONAI/MONAI

Issue:
AttributeError: 'PerceptualLoss' object has no attribute 'channel_wise'
```
[2024-04-21T01:34:48.412Z] ======================================================================
[2024-04-21T01:34:48.412Z] ERROR: test_shape_10 (tests.test_perceptual_loss.TestPerceptualLoss)
[2024-04-21T01:34:48.412Z] ----------------------------------------------------------------------
[2024-04-21T01:34:48.412Z] Traceback (most recent call last):
[2024-04-21T01:34:48.412Z]   File "/usr/local/lib/python3.10/dist-packages/parameterized/parameterized.py", line 620, in standalone_func
[2024-04-21T01:34:48.412Z]     return func(*(a + p.args), **p.kwargs, **kw)
[2024-04-21T01:34:48.412Z]   File "/opt/monai/tests/test_perceptual_loss.py", line 85, in test_shape
[2024-04-21T01:34:48.412Z]     result = loss(torch.randn(input_shape), torch.randn(target_shape))
[2024-04-21T01:34:48.412Z]   File "/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py", line 1511, in _wrapped_call_impl
[2024-04-21T01:34:48.412Z]     return self._call_impl(*args, **kwargs)
[2024-04-21T01:34:48.412Z]   File "/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py", line 1520, in _call_impl
[2024-04-21T01:34:48.412Z]     return forward_call(*args, **kwargs)
[2024-04-21T01:34:48.412Z]   File "/opt/monai/monai/losses/perceptual.py", line 184, in forward
[2024-04-21T01:34:48.412Z]     if self.channel_wise:
[2024-04-21T01:34:48.412Z]   File "/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py", line 1688, in __getattr__
[2024-04-21T01:34:48.412Z]     raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
[2024-04-21T01:34:48.412Z] AttributeError: 'PerceptualLoss' object has no attribute 'channel_wise'
[2024-04-21T01:34:48.412Z] 
```
AttributeError: 'PerceptualLoss' object has no attribute 'channel_wise'
```
[2024-04-21T01:34:48.412Z] ======================================================================
[2024-04-21T01:34:48.412Z] ERROR: test_shape_10 (tests.test_perceptual_loss.TestPerceptualLoss)
[2024-04-21T01:34:48.412Z] ----------------------------------------------------------------------
[2024-04-21T01:34:48.412Z] Traceback (most recent call last):
[2024-04-21T01:34:48.412Z]   File "/usr/local/lib/python3.10/dist-packages/parameterized/parameterized.py", line 620, in standalone_func
[2024-04-21T01:34:48.412Z]     return func(*(a + p.args), **p.kwargs, **kw)
[2024-04-21T01:34:48.412Z]   File "/opt/monai/tests/test_perceptual_loss.py", line 85, in test_shape
[2024-04-21T01:34:48.412Z]     result = loss(torch.randn(input_shape), torch.randn(target_shape))
[2024-04-21T01:34:48.412Z]   File "/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py", line 1511, in _wrapped_call_impl
[2024-04-21T01:34:48.412Z]     return self._call_impl(*args, **kwargs)
[2024-04-21T01:34:48.412Z]   File "/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py", line 1520, in _call_impl
[2024-04-21T01:34:48.412Z]     return forward_call(*args, **kwargs)
[2024-04-21T01:34:48.412Z]   File "/opt/monai/monai/losses/perceptual.py", line 184, in forward
[2024-04-21T01:34:48.412Z]     if self.channel_wise:
[2024-04-21T01:34:48.412Z]   File "/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py", line 1688, in __getattr__
[2024-04-21T01:34:48.412Z]     raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
[2024-04-21T01:34:48.412Z] AttributeError: 'PerceptualLoss' object has no attribute 'channel_wise'
[2024-04-21T01:34:48.412Z] 
```


Discussion:

Resolving patch:
diff --git a/monai/losses/perceptual.py b/monai/losses/perceptual.py
--- a/monai/losses/perceptual.py
+++ b/monai/losses/perceptual.py
@@ -125,6 +125,7 @@ def __init__(
             self.perceptual_function = LPIPS(pretrained=pretrained, net=network_type, verbose=False)
         self.is_fake_3d = is_fake_3d
         self.fake_3d_ratio = fake_3d_ratio
+        self.channel_wise = channel_wise
 
     def _calculate_axis_loss(self, input: torch.Tensor, target: torch.Tensor, spatial_axis: int) -> torch.Tensor:
         """


Test patch:
diff --git a/tests/test_clip_intensity_percentiles.py b/tests/test_clip_intensity_percentiles.py
--- a/tests/test_clip_intensity_percentiles.py
+++ b/tests/test_clip_intensity_percentiles.py
@@ -31,7 +31,7 @@ def test_hard_clipping_two_sided(self, p):
         result = hard_clipper(im)
         lower, upper = percentile(im, (5, 95))
         expected = clip(convert_to_tensor(im), lower, upper)
-        assert_allclose(result, p(expected), type_test="tensor", rtol=1e-7, atol=0)
+        assert_allclose(result, p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])
     def test_hard_clipping_one_sided_high(self, p):
@@ -40,7 +40,7 @@ def test_hard_clipping_one_sided_high(self, p):
         result = hard_clipper(im)
         lower, upper = percentile(im, (0, 95))
         expected = clip(im, lower, upper)
-        assert_allclose(result, p(expected), type_test="tensor", rtol=1e-7, atol=0)
+        assert_allclose(result, p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])
     def test_hard_clipping_one_sided_low(self, p):
@@ -49,7 +49,7 @@ def test_hard_clipping_one_sided_low(self, p):
         result = hard_clipper(im)
         lower, upper = percentile(im, (5, 100))
         expected = clip(im, lower, upper)
-        assert_allclose(result, p(expected), type_test="tensor", rtol=1e-7, atol=0)
+        assert_allclose(result, p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])
     def test_soft_clipping_two_sided(self, p):
@@ -89,7 +89,7 @@ def test_channel_wise(self, p):
         for i, c in enumerate(im):
             lower, upper = percentile(c, (5, 95))
             expected = clip(c, lower, upper)
-            assert_allclose(result[i], p(expected), type_test="tensor", rtol=1e-7, atol=0)
+            assert_allclose(result[i], p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     def test_ill_sharpness_factor(self):
         with self.assertRaises(ValueError):
@@ -121,7 +121,7 @@ def test_hard_clipping_two_sided(self, p):
         result = hard_clipper(im)
         lower, upper = percentile(im, (5, 95))
         expected = clip(im, lower, upper)
-        assert_allclose(result, p(expected), type_test="tensor", rtol=1e-7, atol=0)
+        assert_allclose(result, p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])
     def test_hard_clipping_one_sided_high(self, p):
@@ -130,7 +130,7 @@ def test_hard_clipping_one_sided_high(self, p):
         result = hard_clipper(im)
         lower, upper = percentile(im, (0, 95))
         expected = clip(im, lower, upper)
-        assert_allclose(result, p(expected), type_test="tensor", rtol=1e-7, atol=0)
+        assert_allclose(result, p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])
     def test_hard_clipping_one_sided_low(self, p):
@@ -139,7 +139,7 @@ def test_hard_clipping_one_sided_low(self, p):
         result = hard_clipper(im)
         lower, upper = percentile(im, (5, 100))
         expected = clip(im, lower, upper)
-        assert_allclose(result, p(expected), type_test="tensor", rtol=1e-7, atol=0)
+        assert_allclose(result, p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])
     def test_soft_clipping_two_sided(self, p):
@@ -179,7 +179,7 @@ def test_channel_wise(self, p):
         for i, c in enumerate(im):
             lower, upper = percentile(c, (5, 95))
             expected = clip(c, lower, upper)
-            assert_allclose(result[i], p(expected), type_test="tensor", rtol=1e-7, atol=0)
+            assert_allclose(result[i], p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
 
 if __name__ == "__main__":
diff --git a/tests/test_clip_intensity_percentilesd.py b/tests/test_clip_intensity_percentilesd.py
--- a/tests/test_clip_intensity_percentilesd.py
+++ b/tests/test_clip_intensity_percentilesd.py
@@ -19,7 +19,6 @@
 from monai.transforms import ClipIntensityPercentilesd
 from monai.transforms.utils import soft_clip
 from monai.transforms.utils_pytorch_numpy_unification import clip, percentile
-from monai.utils.type_conversion import convert_to_tensor
 from tests.utils import TEST_NDARRAYS, NumpyImageTestCase2D, NumpyImageTestCase3D, assert_allclose
 
 
@@ -32,8 +31,8 @@ def test_hard_clipping_two_sided(self, p):
         im = p(self.imt)
         result = hard_clipper({key: im})
         lower, upper = percentile(im, (5, 95))
-        expected = clip(convert_to_tensor(im), lower, upper)
-        assert_allclose(result[key], p(expected), type_test="tensor", rtol=1e-7, atol=0)
+        expected = clip(im, lower, upper)
+        assert_allclose(result[key], p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])
     def test_hard_clipping_one_sided_high(self, p):
@@ -43,7 +42,7 @@ def test_hard_clipping_one_sided_high(self, p):
         result = hard_clipper({key: im})
         lower, upper = percentile(im, (0, 95))
         expected = clip(im, lower, upper)
-        assert_allclose(result[key], p(expected), type_test="tensor", rtol=1e-7, atol=0)
+        assert_allclose(result[key], p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])
     def test_hard_clipping_one_sided_low(self, p):
@@ -53,7 +52,7 @@ def test_hard_clipping_one_sided_low(self, p):
         result = hard_clipper({key: im})
         lower, upper = percentile(im, (5, 100))
         expected = clip(im, lower, upper)
-        assert_allclose(result[key], p(expected), type_test="tensor", rtol=1e-7, atol=0)
+        assert_allclose(result[key], p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])
     def test_soft_clipping_two_sided(self, p):
@@ -97,7 +96,7 @@ def test_channel_wise(self, p):
         for i, c in enumerate(im):
             lower, upper = percentile(c, (5, 95))
             expected = clip(c, lower, upper)
-            assert_allclose(result[key][i], p(expected), type_test="tensor", rtol=1e-7, atol=0)
+            assert_allclose(result[key][i], p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     def test_ill_sharpness_factor(self):
         key = "img"
@@ -135,7 +134,7 @@ def test_hard_clipping_two_sided(self, p):
         result = hard_clipper({key: im})
         lower, upper = percentile(im, (5, 95))
         expected = clip(im, lower, upper)
-        assert_allclose(result[key], p(expected), type_test="tensor", rtol=1e-7, atol=0)
+        assert_allclose(result[key], p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])
     def test_hard_clipping_one_sided_high(self, p):
@@ -145,7 +144,7 @@ def test_hard_clipping_one_sided_high(self, p):
         result = hard_clipper({key: im})
         lower, upper = percentile(im, (0, 95))
         expected = clip(im, lower, upper)
-        assert_allclose(result[key], p(expected), type_test="tensor", rtol=1e-7, atol=0)
+        assert_allclose(result[key], p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])
     def test_hard_clipping_one_sided_low(self, p):
@@ -155,7 +154,7 @@ def test_hard_clipping_one_sided_low(self, p):
         result = hard_clipper({key: im})
         lower, upper = percentile(im, (5, 100))
         expected = clip(im, lower, upper)
-        assert_allclose(result[key], p(expected), type_test="tensor", rtol=1e-7, atol=0)
+        assert_allclose(result[key], p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])
     def test_soft_clipping_two_sided(self, p):
@@ -199,7 +198,7 @@ def test_channel_wise(self, p):
         for i, c in enumerate(im):
             lower, upper = percentile(c, (5, 95))
             expected = clip(c, lower, upper)
-            assert_allclose(result[key][i], p(expected), type_test="tensor", rtol=1e-7, atol=0)
+            assert_allclose(result[key][i], p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
 
 if __name__ == "__main__":