From a1114b0b67e4d92afe552732dba3549c8c6287b1 Mon Sep 17 00:00:00 2001 From: Yosua Michael Maranatha Date: Fri, 8 Apr 2022 17:00:14 +0100 Subject: [PATCH 1/3] Add test for giou_loss --- test/test_ops.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/test/test_ops.py b/test/test_ops.py index 071f079e97c..db9881a45ee 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1569,5 +1569,59 @@ def test_jit(self, alpha, gamma, reduction, device, dtype, seed) -> None: torch.testing.assert_close(focal_loss, scripted_focal_loss, rtol=tol, atol=tol) +class TestGeneralizedBoxIouLoss: + # We refer to original test: https://github.com/facebookresearch/fvcore/blob/main/tests/test_giou_loss.py + @pytest.mark.parametrize("device", cpu_and_gpu()) + @pytest.mark.parametrize("dtype", [torch.float32, torch.half]) + def test_giou_loss(self, dtype, device) -> None: + box1 = torch.tensor([-1, -1, 1, 1], dtype=dtype, device=device) + box2 = torch.tensor([0, 0, 1, 1], dtype=dtype, device=device) + box3 = torch.tensor([0, 1, 1, 2], dtype=dtype, device=device) + box4 = torch.tensor([1, 1, 2, 2], dtype=dtype, device=device) + box1s = torch.stack([box2, box2], dim=0) + box2s = torch.stack([box3, box4], dim=0) + + def assert_giou_loss(box1, box2, expected_loss, reduction="none"): + tol = 1e-3 if dtype is torch.half else 1e-5 + computed_loss = ops.generalized_box_iou_loss(box1, box2, reduction=reduction) + expected_loss = torch.tensor(expected_loss, device=device) + torch.testing.assert_close(computed_loss, expected_loss, rtol=tol, atol=tol) + + # Identical boxes should have loss of 0 + assert_giou_loss(box1, box1, 0.0) + + # quarter size box inside other box = IoU of 0.25 + assert_giou_loss(box1, box2, 0.75) + + # Two side by side boxes, area=union + # IoU=0 and GIoU=0 (loss 1.0) + assert_giou_loss(box2, box3, 1.0) + + # Two diagonally adjacent boxes, area=2*union + # IoU=0 and GIoU=-0.5 (loss 1.5) + assert_giou_loss(box2, box4, 1.5) + + # Test batched loss and reductions + assert_giou_loss(box1s, box2s, 2.5, reduction="sum") + assert_giou_loss(box1s, box2s, 1.25, reduction="mean") + + @pytest.mark.parametrize("device", cpu_and_gpu()) + @pytest.mark.parametrize("dtype", [torch.float32, torch.half]) + def test_empty_inputs(self, dtype, device) -> None: + box1 = torch.randn([0, 4], dtype=dtype).requires_grad_() + box2 = torch.randn([0, 4], dtype=dtype).requires_grad_() + + loss = ops.generalized_box_iou_loss(box1, box2, reduction="mean") + loss.backward() + + tol = 1e-3 if dtype is torch.half else 1e-5 + torch.testing.assert_close(loss, torch.tensor(0.0), rtol=tol, atol=tol) + assert box1.grad is not None, "box1.grad should not be None after backward is called" + assert box2.grad is not None, "box2.grad should not be None after backward is called" + + loss = ops.generalized_box_iou_loss(box1, box2, reduction="none") + torch.testing.assert_close(loss.numel(), 0, rtol=tol, atol=tol) + + if __name__ == "__main__": pytest.main([__file__]) From 4bfb30738f94841b8202012b0c1548b473632c4b Mon Sep 17 00:00:00 2001 From: YosuaMichael Date: Tue, 12 Apr 2022 17:38:47 +0100 Subject: [PATCH 2/3] Use standard assert for integer comparison Co-authored-by: Philip Meier --- test/test_ops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_ops.py b/test/test_ops.py index db9881a45ee..0d09a506fab 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1620,7 +1620,7 @@ def test_empty_inputs(self, dtype, device) -> None: assert box2.grad is not None, "box2.grad should not be None after backward is called" loss = ops.generalized_box_iou_loss(box1, box2, reduction="none") - torch.testing.assert_close(loss.numel(), 0, rtol=tol, atol=tol) + assert loss.numel()== 0 if __name__ == "__main__": From bf04f3a34e6a3b2fd9020ef56257ac5ef1dba74e Mon Sep 17 00:00:00 2001 From: Yosua Michael Maranatha Date: Wed, 13 Apr 2022 13:24:54 +0100 Subject: [PATCH 3/3] Fix ufmt format and add log after assert --- test/test_ops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_ops.py b/test/test_ops.py index 0d09a506fab..c61922204a3 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1620,7 +1620,7 @@ def test_empty_inputs(self, dtype, device) -> None: assert box2.grad is not None, "box2.grad should not be None after backward is called" loss = ops.generalized_box_iou_loss(box1, box2, reduction="none") - assert loss.numel()== 0 + assert loss.numel() == 0, "giou_loss for two empty box should be empty" if __name__ == "__main__":