From 1ef2eef617c0a573a1f0fcb970e397766c14d737 Mon Sep 17 00:00:00 2001 From: Kai Wana <89363872+iaoqian@users.noreply.github.com> Date: Tue, 16 May 2023 11:33:15 +0800 Subject: [PATCH 1/9] Update feature_pyramid_network.py Argument Error with max_pool2d in class LastLevelMaxPool --- torchvision/ops/feature_pyramid_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/ops/feature_pyramid_network.py b/torchvision/ops/feature_pyramid_network.py index f4b190844ff..dbfc9330b39 100644 --- a/torchvision/ops/feature_pyramid_network.py +++ b/torchvision/ops/feature_pyramid_network.py @@ -216,7 +216,7 @@ def forward( names: List[str], ) -> Tuple[List[Tensor], List[str]]: names.append("pool") - x.append(F.max_pool2d(x[-1], 1, 2, 0)) + x.append(F.max_pool2d(x[-1], kernel_size=2, stride=2, padding=0)) return x, names From c8fed6d24b1a4bd157397ebc0dc4cd533406b4e3 Mon Sep 17 00:00:00 2001 From: Kai <21052222@hdu.edu.cn> Date: Tue, 16 May 2023 13:26:07 +0800 Subject: [PATCH 2/9] bug-fix and test --- test/test_ops.py | 22 ++++++++++++++++++++++ torchvision/ops/feature_pyramid_network.py | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/test/test_ops.py b/test/test_ops.py index 463ebb333ff..048c00e081e 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1488,6 +1488,28 @@ def test_distance_iou_loss(self, dtype, device): def test_empty_distance_iou_inputs(self, dtype, device): assert_empty_loss(ops.distance_box_iou_loss, dtype, device) +class TestLastLevelMaxPool2d: + def _generate_fpn_feature_maps(self, **kwargs): + feature_maps = [torch.rand(16, 3, 240, 320), + torch.rand(16, 3, 120, 160), + torch.rand(16, 3, 60, 80), + torch.rand(16, 3, 30, 40)] + names = ['0', '1', '2', '3'] + return feature_maps, names + + def test_lastlevel_maxpool2d(self): + + feature_maps, names = self._generate_fpn_feature_maps() + extra_blocks = ops.feature_pyramid_network.LastLevelMaxPool() + + # skip what FPN really dit, simply copy results from feature maps here. + results = feature_maps + + results, names = extra_blocks(results, feature_maps, names) + expected_pooled_featuremap = F.max_pool2d(feature_maps[-1], 2, 2, 0) + + tol = 1e-3 if feature_maps[-1].dtype is torch.half else 1e-5 + torch.testing.assert_close(expected_pooled_featuremap, results[-1], atol=tol, rtol=tol) class TestFocalLoss: def _generate_diverse_input_target_pair(self, shape=(5, 2), **kwargs): diff --git a/torchvision/ops/feature_pyramid_network.py b/torchvision/ops/feature_pyramid_network.py index f4b190844ff..dbfc9330b39 100644 --- a/torchvision/ops/feature_pyramid_network.py +++ b/torchvision/ops/feature_pyramid_network.py @@ -216,7 +216,7 @@ def forward( names: List[str], ) -> Tuple[List[Tensor], List[str]]: names.append("pool") - x.append(F.max_pool2d(x[-1], 1, 2, 0)) + x.append(F.max_pool2d(x[-1], kernel_size=2, stride=2, padding=0)) return x, names From 8ecb64b6c973228bd0ecaa60de04fb599a17aca5 Mon Sep 17 00:00:00 2001 From: Kai Wana <89363872+iaoqian@users.noreply.github.com> Date: Tue, 16 May 2023 13:55:52 +0800 Subject: [PATCH 3/9] Update test_ops.py --- test/test_ops.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_ops.py b/test/test_ops.py index 048c00e081e..65240620778 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1504,9 +1504,9 @@ def test_lastlevel_maxpool2d(self): # skip what FPN really dit, simply copy results from feature maps here. results = feature_maps - - results, names = extra_blocks(results, feature_maps, names) + expected_pooled_featuremap = F.max_pool2d(feature_maps[-1], 2, 2, 0) + results, names = extra_blocks(results, feature_maps, names) tol = 1e-3 if feature_maps[-1].dtype is torch.half else 1e-5 torch.testing.assert_close(expected_pooled_featuremap, results[-1], atol=tol, rtol=tol) From 83d2ce428a9133f06d6a9a640ad38f773fd02292 Mon Sep 17 00:00:00 2001 From: Kai Wana <89363872+iaoqian@users.noreply.github.com> Date: Tue, 16 May 2023 14:13:42 +0800 Subject: [PATCH 4/9] Update test_ops.py --- test/test_ops.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_ops.py b/test/test_ops.py index 65240620778..ed3ba387b9a 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1489,22 +1489,22 @@ def test_empty_distance_iou_inputs(self, dtype, device): assert_empty_loss(ops.distance_box_iou_loss, dtype, device) class TestLastLevelMaxPool2d: - def _generate_fpn_feature_maps(self, **kwargs): + def _generate_fpn_feature_maps(self, **kwargs) -> Tuple[List[Tensor], List[str]]: feature_maps = [torch.rand(16, 3, 240, 320), torch.rand(16, 3, 120, 160), torch.rand(16, 3, 60, 80), torch.rand(16, 3, 30, 40)] names = ['0', '1', '2', '3'] + return feature_maps, names - def test_lastlevel_maxpool2d(self): - + def test_lastlevel_maxpool2d(self) -> None: feature_maps, names = self._generate_fpn_feature_maps() extra_blocks = ops.feature_pyramid_network.LastLevelMaxPool() # skip what FPN really dit, simply copy results from feature maps here. results = feature_maps - + expected_pooled_featuremap = F.max_pool2d(feature_maps[-1], 2, 2, 0) results, names = extra_blocks(results, feature_maps, names) From 0742636d7954b9fd89e8b328deb2315565eb7f84 Mon Sep 17 00:00:00 2001 From: Kai Wana <89363872+iaoqian@users.noreply.github.com> Date: Tue, 16 May 2023 19:06:58 +0800 Subject: [PATCH 5/9] Update test_ops.py --- test/test_ops.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/test_ops.py b/test/test_ops.py index ed3ba387b9a..60de8a4c1de 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1488,12 +1488,15 @@ def test_distance_iou_loss(self, dtype, device): def test_empty_distance_iou_inputs(self, dtype, device): assert_empty_loss(ops.distance_box_iou_loss, dtype, device) + class TestLastLevelMaxPool2d: def _generate_fpn_feature_maps(self, **kwargs) -> Tuple[List[Tensor], List[str]]: - feature_maps = [torch.rand(16, 3, 240, 320), - torch.rand(16, 3, 120, 160), - torch.rand(16, 3, 60, 80), - torch.rand(16, 3, 30, 40)] + feature_maps = [ + torch.rand(16, 3, 240, 320), + torch.rand(16, 3, 120, 160), + torch.rand(16, 3, 60, 80), + torch.rand(16, 3, 30, 40) + ] names = ['0', '1', '2', '3'] return feature_maps, names @@ -1511,6 +1514,7 @@ def test_lastlevel_maxpool2d(self) -> None: tol = 1e-3 if feature_maps[-1].dtype is torch.half else 1e-5 torch.testing.assert_close(expected_pooled_featuremap, results[-1], atol=tol, rtol=tol) + class TestFocalLoss: def _generate_diverse_input_target_pair(self, shape=(5, 2), **kwargs): def logit(p): From 250a42a8898f07c6f13f1a3beae8c4cefe28c12a Mon Sep 17 00:00:00 2001 From: Kai Wana <89363872+iaoqian@users.noreply.github.com> Date: Tue, 16 May 2023 19:20:12 +0800 Subject: [PATCH 6/9] Update test_ops.py --- test/test_ops.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test_ops.py b/test/test_ops.py index 60de8a4c1de..711ff45325a 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1488,17 +1488,17 @@ def test_distance_iou_loss(self, dtype, device): def test_empty_distance_iou_inputs(self, dtype, device): assert_empty_loss(ops.distance_box_iou_loss, dtype, device) - + class TestLastLevelMaxPool2d: def _generate_fpn_feature_maps(self, **kwargs) -> Tuple[List[Tensor], List[str]]: feature_maps = [ torch.rand(16, 3, 240, 320), torch.rand(16, 3, 120, 160), torch.rand(16, 3, 60, 80), - torch.rand(16, 3, 30, 40) + torch.rand(16, 3, 30, 40), ] - names = ['0', '1', '2', '3'] - + names = ["0", "1", "2", "3"] + return feature_maps, names def test_lastlevel_maxpool2d(self) -> None: @@ -1514,7 +1514,7 @@ def test_lastlevel_maxpool2d(self) -> None: tol = 1e-3 if feature_maps[-1].dtype is torch.half else 1e-5 torch.testing.assert_close(expected_pooled_featuremap, results[-1], atol=tol, rtol=tol) - + class TestFocalLoss: def _generate_diverse_input_target_pair(self, shape=(5, 2), **kwargs): def logit(p): From 708a63c40b8185867a560084c16701313f5ecd9f Mon Sep 17 00:00:00 2001 From: Kai Wana <89363872+iaoqian@users.noreply.github.com> Date: Thu, 18 May 2023 00:18:21 +0800 Subject: [PATCH 7/9] remove test_lastlevel_maxpool2d --- test/test_ops.py | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/test/test_ops.py b/test/test_ops.py index 711ff45325a..463ebb333ff 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1489,32 +1489,6 @@ def test_empty_distance_iou_inputs(self, dtype, device): assert_empty_loss(ops.distance_box_iou_loss, dtype, device) -class TestLastLevelMaxPool2d: - def _generate_fpn_feature_maps(self, **kwargs) -> Tuple[List[Tensor], List[str]]: - feature_maps = [ - torch.rand(16, 3, 240, 320), - torch.rand(16, 3, 120, 160), - torch.rand(16, 3, 60, 80), - torch.rand(16, 3, 30, 40), - ] - names = ["0", "1", "2", "3"] - - return feature_maps, names - - def test_lastlevel_maxpool2d(self) -> None: - feature_maps, names = self._generate_fpn_feature_maps() - extra_blocks = ops.feature_pyramid_network.LastLevelMaxPool() - - # skip what FPN really dit, simply copy results from feature maps here. - results = feature_maps - - expected_pooled_featuremap = F.max_pool2d(feature_maps[-1], 2, 2, 0) - results, names = extra_blocks(results, feature_maps, names) - - tol = 1e-3 if feature_maps[-1].dtype is torch.half else 1e-5 - torch.testing.assert_close(expected_pooled_featuremap, results[-1], atol=tol, rtol=tol) - - class TestFocalLoss: def _generate_diverse_input_target_pair(self, shape=(5, 2), **kwargs): def logit(p): From a53f5645e548fe45191549da04e91f28e572197a Mon Sep 17 00:00:00 2001 From: Kai Wana <89363872+iaoqian@users.noreply.github.com> Date: Thu, 18 May 2023 00:28:25 +0800 Subject: [PATCH 8/9] add comment for LastLevelMaxPool --- torchvision/ops/feature_pyramid_network.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/torchvision/ops/feature_pyramid_network.py b/torchvision/ops/feature_pyramid_network.py index dbfc9330b39..52f792dd950 100644 --- a/torchvision/ops/feature_pyramid_network.py +++ b/torchvision/ops/feature_pyramid_network.py @@ -206,7 +206,7 @@ def forward(self, x: Dict[str, Tensor]) -> Dict[str, Tensor]: class LastLevelMaxPool(ExtraFPNBlock): """ - Applies a max_pool2d on top of the last feature map + Applies a max_pool2d (not actual max_pool2d) on top of the last feature map """ def forward( @@ -216,7 +216,8 @@ def forward( names: List[str], ) -> Tuple[List[Tensor], List[str]]: names.append("pool") - x.append(F.max_pool2d(x[-1], kernel_size=2, stride=2, padding=0)) + # Use max pooling to simulate stride 2 subsampling + x.append(F.max_pool2d(x[-1], kernel_size=1, stride=2, padding=0)) return x, names From a49b786e03e49d9cdabf76b6197bd1941fe03794 Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Thu, 18 May 2023 10:47:42 +0100 Subject: [PATCH 9/9] Update torchvision/ops/feature_pyramid_network.py --- torchvision/ops/feature_pyramid_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/ops/feature_pyramid_network.py b/torchvision/ops/feature_pyramid_network.py index 52f792dd950..2e7aef0e2fa 100644 --- a/torchvision/ops/feature_pyramid_network.py +++ b/torchvision/ops/feature_pyramid_network.py @@ -206,7 +206,7 @@ def forward(self, x: Dict[str, Tensor]) -> Dict[str, Tensor]: class LastLevelMaxPool(ExtraFPNBlock): """ - Applies a max_pool2d (not actual max_pool2d) on top of the last feature map + Applies a max_pool2d (not actual max_pool2d, we just subsample) on top of the last feature map """ def forward(