From c4008573428acf485600bcbb98ae67a78eb127a6 Mon Sep 17 00:00:00 2001 From: adityagandhamal Date: Sun, 2 Oct 2022 00:08:26 +0530 Subject: [PATCH 1/8] Add ValueError --- torchvision/ops/ciou_loss.py | 9 +++++++-- torchvision/ops/diou_loss.py | 7 ++++++- torchvision/ops/focal_loss.py | 6 ++++++ torchvision/ops/giou_loss.py | 8 ++++++-- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/torchvision/ops/ciou_loss.py b/torchvision/ops/ciou_loss.py index a9f20a5f4c8..d1df2b4a340 100644 --- a/torchvision/ops/ciou_loss.py +++ b/torchvision/ops/ciou_loss.py @@ -63,9 +63,14 @@ def complete_box_iou_loss( alpha = v / (1 - iou + v + eps) loss = diou_loss + alpha * v - if reduction == "mean": + + # Check reduction option and return loss accordingly + if reduction == "none": + pass + elif reduction == "mean": loss = loss.mean() if loss.numel() > 0 else 0.0 * loss.sum() elif reduction == "sum": loss = loss.sum() - + else: + raise ValueError(f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'") return loss diff --git a/torchvision/ops/diou_loss.py b/torchvision/ops/diou_loss.py index 2187aea4cc5..2749c29729a 100644 --- a/torchvision/ops/diou_loss.py +++ b/torchvision/ops/diou_loss.py @@ -50,10 +50,15 @@ def distance_box_iou_loss( loss, _ = _diou_iou_loss(boxes1, boxes2, eps) - if reduction == "mean": + # Check reduction option and return loss accordingly + if reduction == "none": + pass + elif reduction == "mean": loss = loss.mean() if loss.numel() > 0 else 0.0 * loss.sum() elif reduction == "sum": loss = loss.sum() + else: + raise ValueError(f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'") return loss diff --git a/torchvision/ops/focal_loss.py b/torchvision/ops/focal_loss.py index c8cc9a8ac14..d3785253be3 100644 --- a/torchvision/ops/focal_loss.py +++ b/torchvision/ops/focal_loss.py @@ -32,6 +32,12 @@ def sigmoid_focal_loss( Loss tensor with the reduction option applied. """ # Original implementation from https://github.com/facebookresearch/fvcore/blob/master/fvcore/nn/focal_loss.py + + # Check reduction option + modes = ["none", "mean", "sum"] + if reduction not in modes: + raise ValueError(f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'") + if not torch.jit.is_scripting() and not torch.jit.is_tracing(): _log_api_usage_once(sigmoid_focal_loss) p = torch.sigmoid(inputs) diff --git a/torchvision/ops/giou_loss.py b/torchvision/ops/giou_loss.py index 0c555ec4fe9..1778f74c8b2 100644 --- a/torchvision/ops/giou_loss.py +++ b/torchvision/ops/giou_loss.py @@ -62,9 +62,13 @@ def generalized_box_iou_loss( loss = 1 - miouk - if reduction == "mean": + # Check reduction option and return loss accordingly + if reduction == "none": + pass + elif reduction == "mean": loss = loss.mean() if loss.numel() > 0 else 0.0 * loss.sum() elif reduction == "sum": loss = loss.sum() - + else: + raise ValueError(f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'") return loss From b81ce34244eed48427b362c997e4eef76bfdf8a5 Mon Sep 17 00:00:00 2001 From: adityagandhamal Date: Sun, 2 Oct 2022 02:03:40 +0530 Subject: [PATCH 2/8] Add tests for ValueError --- test/test_ops.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/test_ops.py b/test/test_ops.py index b34fbe7f254..36d7ffbb897 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1367,6 +1367,8 @@ def assert_empty_loss(iou_fn, dtype, device): loss = iou_fn(box1, box2, reduction="none") assert loss.numel() == 0, f"{str(iou_fn)} for two empty box should be empty" +def assert_reduction_mode(iou_fn, box1, box2, reduction): + assert iou_fn(box1, box2, reduction) == ValueError class TestGeneralizedBoxIouLoss: # We refer to original test: https://github.com/facebookresearch/fvcore/blob/main/tests/test_giou_loss.py @@ -1394,6 +1396,11 @@ def test_giou_loss(self, dtype, device): assert_iou_loss(ops.generalized_box_iou_loss, box1s, box2s, 2.5, device=device, reduction="sum") assert_iou_loss(ops.generalized_box_iou_loss, box1s, box2s, 1.25, device=device, reduction="mean") + # Test reduction value + # reduction value other than ["none", "mean", "sum"] should raise a ValueError + with pytest.raises(ValueError, match="Invalid"): + assert_reduction_mode(ops.generalized_box_iou_loss, box1s, box2s, reduction="xyz") + @pytest.mark.parametrize("device", cpu_and_gpu()) @pytest.mark.parametrize("dtype", [torch.float32, torch.half]) def test_empty_inputs(self, dtype, device): @@ -1412,6 +1419,9 @@ def test_ciou_loss(self, dtype, device): assert_iou_loss(ops.complete_box_iou_loss, box1, box4, 1.2500, device=device) assert_iou_loss(ops.complete_box_iou_loss, box1s, box2s, 1.2250, device=device, reduction="mean") assert_iou_loss(ops.complete_box_iou_loss, box1s, box2s, 2.4500, device=device, reduction="sum") + + with pytest.raises(ValueError, match="Invalid"): + assert_reduction_mode(ops.complete_box_iou_loss, box1s, box2s, reduction="xyz") @pytest.mark.parametrize("device", cpu_and_gpu()) @pytest.mark.parametrize("dtype", [torch.float32, torch.half]) @@ -1431,6 +1441,9 @@ def test_distance_iou_loss(self, dtype, device): assert_iou_loss(ops.distance_box_iou_loss, box1, box4, 1.2500, device=device) assert_iou_loss(ops.distance_box_iou_loss, box1s, box2s, 1.2250, device=device, reduction="mean") assert_iou_loss(ops.distance_box_iou_loss, box1s, box2s, 2.4500, device=device, reduction="sum") + + with pytest.raises(ValueError, match="Invalid"): + assert_reduction_mode(ops.distance_box_iou_loss, box1s, box2s, reduction="xyz") @pytest.mark.parametrize("device", cpu_and_gpu()) @pytest.mark.parametrize("dtype", [torch.float32, torch.half]) @@ -1553,6 +1566,15 @@ def test_jit(self, alpha, gamma, reduction, device, dtype, seed): tol = 1e-3 if dtype is torch.half else 1e-5 torch.testing.assert_close(focal_loss, scripted_focal_loss, rtol=tol, atol=tol) + + # Raise ValueError for anonymous reduction mode + def test_reduction_mode(self, dtype=torch.float32, device=cpu_and_gpu(), reduction="xyz"): + inputs, targets = self._generate_diverse_input_target_pair(dtype=dtype, device=device) + with pytest.raises(ValueError, match="Invalid"): + ops.sigmoid_focal_loss(inputs, targets, reduction) == ValueError + + + class TestMasksToBoxes: From 2d7466f3b9be1a9dcb9fffea6899d87948fee9ad Mon Sep 17 00:00:00 2001 From: adityagandhamal Date: Sun, 2 Oct 2022 02:51:59 +0530 Subject: [PATCH 3/8] Add tests for ValueError --- test/test_ops.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/test_ops.py b/test/test_ops.py index 36d7ffbb897..a16924e3752 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1568,10 +1568,15 @@ def test_jit(self, alpha, gamma, reduction, device, dtype, seed): torch.testing.assert_close(focal_loss, scripted_focal_loss, rtol=tol, atol=tol) # Raise ValueError for anonymous reduction mode - def test_reduction_mode(self, dtype=torch.float32, device=cpu_and_gpu(), reduction="xyz"): - inputs, targets = self._generate_diverse_input_target_pair(dtype=dtype, device=device) + @pytest.mark.parametrize("device", cpu_and_gpu()) + @pytest.mark.parametrize("dtype", [torch.float32, torch.half]) + def test_reduction_mode(self, device, dtype, reduction="xyz"): + if device == "cpu" and dtype is torch.half: + pytest.skip("Currently torch.half is not fully supported on cpu") + torch.random.manual_seed(0) + inputs, targets = self._generate_diverse_input_target_pair(device=device, dtype=dtype) with pytest.raises(ValueError, match="Invalid"): - ops.sigmoid_focal_loss(inputs, targets, reduction) == ValueError + ops.sigmoid_focal_loss(inputs, targets, 0.25, 2, reduction) == ValueError From e178f3681a9211b025a8dcd45a7ce961e40c75a7 Mon Sep 17 00:00:00 2001 From: adityagandhamal Date: Sun, 2 Oct 2022 02:52:35 +0530 Subject: [PATCH 4/8] Add ValueError --- torchvision/ops/ciou_loss.py | 4 +++- torchvision/ops/diou_loss.py | 4 +++- torchvision/ops/focal_loss.py | 4 +++- torchvision/ops/giou_loss.py | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/torchvision/ops/ciou_loss.py b/torchvision/ops/ciou_loss.py index d1df2b4a340..75a1c4cb1f3 100644 --- a/torchvision/ops/ciou_loss.py +++ b/torchvision/ops/ciou_loss.py @@ -72,5 +72,7 @@ def complete_box_iou_loss( elif reduction == "sum": loss = loss.sum() else: - raise ValueError(f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'") + raise ValueError( + f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'" + ) return loss diff --git a/torchvision/ops/diou_loss.py b/torchvision/ops/diou_loss.py index 2749c29729a..caf62bd2cbf 100644 --- a/torchvision/ops/diou_loss.py +++ b/torchvision/ops/diou_loss.py @@ -58,7 +58,9 @@ def distance_box_iou_loss( elif reduction == "sum": loss = loss.sum() else: - raise ValueError(f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'") + raise ValueError( + f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'" + ) return loss diff --git a/torchvision/ops/focal_loss.py b/torchvision/ops/focal_loss.py index d3785253be3..6d546c1ac8b 100644 --- a/torchvision/ops/focal_loss.py +++ b/torchvision/ops/focal_loss.py @@ -36,7 +36,9 @@ def sigmoid_focal_loss( # Check reduction option modes = ["none", "mean", "sum"] if reduction not in modes: - raise ValueError(f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'") + raise ValueError( + f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'" + ) if not torch.jit.is_scripting() and not torch.jit.is_tracing(): _log_api_usage_once(sigmoid_focal_loss) diff --git a/torchvision/ops/giou_loss.py b/torchvision/ops/giou_loss.py index 1778f74c8b2..03ef8e62291 100644 --- a/torchvision/ops/giou_loss.py +++ b/torchvision/ops/giou_loss.py @@ -70,5 +70,7 @@ def generalized_box_iou_loss( elif reduction == "sum": loss = loss.sum() else: - raise ValueError(f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'") + raise ValueError( + f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'" + ) return loss From 5a208ecab4469e63b6dab91981d59132b623533a Mon Sep 17 00:00:00 2001 From: adityagandhamal Date: Tue, 4 Oct 2022 19:09:30 +0530 Subject: [PATCH 5/8] Change to if/else --- torchvision/ops/focal_loss.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/torchvision/ops/focal_loss.py b/torchvision/ops/focal_loss.py index 6d546c1ac8b..07ee4ace869 100644 --- a/torchvision/ops/focal_loss.py +++ b/torchvision/ops/focal_loss.py @@ -34,8 +34,7 @@ def sigmoid_focal_loss( # Original implementation from https://github.com/facebookresearch/fvcore/blob/master/fvcore/nn/focal_loss.py # Check reduction option - modes = ["none", "mean", "sum"] - if reduction not in modes: + if reduction != "none" or reduction != "mean" or reduction != "sum": raise ValueError( f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'" ) From 9100f36f23e102413f9a1ee3a38ac59b25db8875 Mon Sep 17 00:00:00 2001 From: adityagandhamal Date: Tue, 4 Oct 2022 19:11:36 +0530 Subject: [PATCH 6/8] Ammend iou_fn tests --- test/test_ops.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test/test_ops.py b/test/test_ops.py index a16924e3752..86f332bdb54 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1367,8 +1367,6 @@ def assert_empty_loss(iou_fn, dtype, device): loss = iou_fn(box1, box2, reduction="none") assert loss.numel() == 0, f"{str(iou_fn)} for two empty box should be empty" -def assert_reduction_mode(iou_fn, box1, box2, reduction): - assert iou_fn(box1, box2, reduction) == ValueError class TestGeneralizedBoxIouLoss: # We refer to original test: https://github.com/facebookresearch/fvcore/blob/main/tests/test_giou_loss.py @@ -1399,7 +1397,8 @@ def test_giou_loss(self, dtype, device): # Test reduction value # reduction value other than ["none", "mean", "sum"] should raise a ValueError with pytest.raises(ValueError, match="Invalid"): - assert_reduction_mode(ops.generalized_box_iou_loss, box1s, box2s, reduction="xyz") + ops.generalized_box_iou_loss(box1s, box2s, reduction="xyz") + @pytest.mark.parametrize("device", cpu_and_gpu()) @pytest.mark.parametrize("dtype", [torch.float32, torch.half]) @@ -1421,7 +1420,7 @@ def test_ciou_loss(self, dtype, device): assert_iou_loss(ops.complete_box_iou_loss, box1s, box2s, 2.4500, device=device, reduction="sum") with pytest.raises(ValueError, match="Invalid"): - assert_reduction_mode(ops.complete_box_iou_loss, box1s, box2s, reduction="xyz") + ops.complete_box_iou_loss(box1s, box2s, reduction="xyz") @pytest.mark.parametrize("device", cpu_and_gpu()) @pytest.mark.parametrize("dtype", [torch.float32, torch.half]) @@ -1443,7 +1442,7 @@ def test_distance_iou_loss(self, dtype, device): assert_iou_loss(ops.distance_box_iou_loss, box1s, box2s, 2.4500, device=device, reduction="sum") with pytest.raises(ValueError, match="Invalid"): - assert_reduction_mode(ops.distance_box_iou_loss, box1s, box2s, reduction="xyz") + ops.distance_box_iou_loss(box1s, box2s, reduction="xyz") @pytest.mark.parametrize("device", cpu_and_gpu()) @pytest.mark.parametrize("dtype", [torch.float32, torch.half]) @@ -1576,7 +1575,7 @@ def test_reduction_mode(self, device, dtype, reduction="xyz"): torch.random.manual_seed(0) inputs, targets = self._generate_diverse_input_target_pair(device=device, dtype=dtype) with pytest.raises(ValueError, match="Invalid"): - ops.sigmoid_focal_loss(inputs, targets, 0.25, 2, reduction) == ValueError + ops.sigmoid_focal_loss(inputs, targets, 0.25, 2, reduction) From 1db7b393f53e329a1c0201c70234d1c0fa8b3ef4 Mon Sep 17 00:00:00 2001 From: adityagandhamal Date: Wed, 5 Oct 2022 00:57:35 +0530 Subject: [PATCH 7/8] Move code excerpt --- torchvision/ops/focal_loss.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/torchvision/ops/focal_loss.py b/torchvision/ops/focal_loss.py index 07ee4ace869..08c282555fc 100644 --- a/torchvision/ops/focal_loss.py +++ b/torchvision/ops/focal_loss.py @@ -33,12 +33,6 @@ def sigmoid_focal_loss( """ # Original implementation from https://github.com/facebookresearch/fvcore/blob/master/fvcore/nn/focal_loss.py - # Check reduction option - if reduction != "none" or reduction != "mean" or reduction != "sum": - raise ValueError( - f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'" - ) - if not torch.jit.is_scripting() and not torch.jit.is_tracing(): _log_api_usage_once(sigmoid_focal_loss) p = torch.sigmoid(inputs) @@ -50,9 +44,15 @@ def sigmoid_focal_loss( alpha_t = alpha * targets + (1 - alpha) * (1 - targets) loss = alpha_t * loss - if reduction == "mean": + # Check reduction option and return loss accordingly + if reduction == "none": + pass + elif reduction == "mean": loss = loss.mean() elif reduction == "sum": loss = loss.sum() - + else: + raise ValueError( + f"Invalid Value for arg 'reduction': '{reduction} \n Supported reduction modes: 'none', 'mean', 'sum'" + ) return loss From aca8813b48c4ed83e7dd0314e44d2bd6c65a9a02 Mon Sep 17 00:00:00 2001 From: adityagandhamal Date: Wed, 5 Oct 2022 12:46:53 +0530 Subject: [PATCH 8/8] Format tests --- test/test_ops.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/test/test_ops.py b/test/test_ops.py index 86f332bdb54..d76e57faecf 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1398,7 +1398,6 @@ def test_giou_loss(self, dtype, device): # reduction value other than ["none", "mean", "sum"] should raise a ValueError with pytest.raises(ValueError, match="Invalid"): ops.generalized_box_iou_loss(box1s, box2s, reduction="xyz") - @pytest.mark.parametrize("device", cpu_and_gpu()) @pytest.mark.parametrize("dtype", [torch.float32, torch.half]) @@ -1418,7 +1417,7 @@ def test_ciou_loss(self, dtype, device): assert_iou_loss(ops.complete_box_iou_loss, box1, box4, 1.2500, device=device) assert_iou_loss(ops.complete_box_iou_loss, box1s, box2s, 1.2250, device=device, reduction="mean") assert_iou_loss(ops.complete_box_iou_loss, box1s, box2s, 2.4500, device=device, reduction="sum") - + with pytest.raises(ValueError, match="Invalid"): ops.complete_box_iou_loss(box1s, box2s, reduction="xyz") @@ -1440,7 +1439,7 @@ def test_distance_iou_loss(self, dtype, device): assert_iou_loss(ops.distance_box_iou_loss, box1, box4, 1.2500, device=device) assert_iou_loss(ops.distance_box_iou_loss, box1s, box2s, 1.2250, device=device, reduction="mean") assert_iou_loss(ops.distance_box_iou_loss, box1s, box2s, 2.4500, device=device, reduction="sum") - + with pytest.raises(ValueError, match="Invalid"): ops.distance_box_iou_loss(box1s, box2s, reduction="xyz") @@ -1565,22 +1564,19 @@ def test_jit(self, alpha, gamma, reduction, device, dtype, seed): tol = 1e-3 if dtype is torch.half else 1e-5 torch.testing.assert_close(focal_loss, scripted_focal_loss, rtol=tol, atol=tol) - + # Raise ValueError for anonymous reduction mode @pytest.mark.parametrize("device", cpu_and_gpu()) @pytest.mark.parametrize("dtype", [torch.float32, torch.half]) def test_reduction_mode(self, device, dtype, reduction="xyz"): if device == "cpu" and dtype is torch.half: - pytest.skip("Currently torch.half is not fully supported on cpu") - torch.random.manual_seed(0) + pytest.skip("Currently torch.half is not fully supported on cpu") + torch.random.manual_seed(0) inputs, targets = self._generate_diverse_input_target_pair(device=device, dtype=dtype) with pytest.raises(ValueError, match="Invalid"): ops.sigmoid_focal_loss(inputs, targets, 0.25, 2, reduction) - - - class TestMasksToBoxes: def test_masks_box(self): def masks_box_check(masks, expected, atol=1e-4):