We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Raise error if target boxes are degenerate in Faster R-CNN
We have had a number of reports with users saying that their training loss is nan after a few iterations.

Most of the time, this is due to degenerate boxes (i.e., boxes with negative sizes or zero area). We should improve the user experience in those situations.

I think that raising an error in `GeneralizedRCNN` if the target boxes are degenerate would be a good compromise.

Related issues: https://github.com/pytorch/vision/issues/2235 https://github.com/pytorch/vision/issues/1994 https://github.com/pytorch/vision/issues/1176 https://github.com/pytorch/vision/issues/1128 #1120 and #997

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `torchvision/models/detection/generalized_rcnn.py`
Content:
```
1 # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
2 """
3 Implements the Generalized R-CNN framework
4 """
5 
6 from collections import OrderedDict
7 import torch
8 from torch import nn
9 import warnings
10 from torch.jit.annotations import Tuple, List, Dict, Optional
11 from torch import Tensor
12 
13 
14 class GeneralizedRCNN(nn.Module):
15     """
16     Main class for Generalized R-CNN.
17 
18     Arguments:
19         backbone (nn.Module):
20         rpn (nn.Module):
21         roi_heads (nn.Module): takes the features + the proposals from the RPN and computes
22             detections / masks from it.
23         transform (nn.Module): performs the data transformation from the inputs to feed into
24             the model
25     """
26 
27     def __init__(self, backbone, rpn, roi_heads, transform):
28         super(GeneralizedRCNN, self).__init__()
29         self.transform = transform
30         self.backbone = backbone
31         self.rpn = rpn
32         self.roi_heads = roi_heads
33         # used only on torchscript mode
34         self._has_warned = False
35 
36     @torch.jit.unused
37     def eager_outputs(self, losses, detections):
38         # type: (Dict[str, Tensor], List[Dict[str, Tensor]]) -> Tuple[Dict[str, Tensor], List[Dict[str, Tensor]]]
39         if self.training:
40             return losses
41 
42         return detections
43 
44     def forward(self, images, targets=None):
45         # type: (List[Tensor], Optional[List[Dict[str, Tensor]]]) -> Tuple[Dict[str, Tensor], List[Dict[str, Tensor]]]
46         """
47         Arguments:
48             images (list[Tensor]): images to be processed
49             targets (list[Dict[Tensor]]): ground-truth boxes present in the image (optional)
50 
51         Returns:
52             result (list[BoxList] or dict[Tensor]): the output from the model.
53                 During training, it returns a dict[Tensor] which contains the losses.
54                 During testing, it returns list[BoxList] contains additional fields
55                 like `scores`, `labels` and `mask` (for Mask R-CNN models).
56 
57         """
58         if self.training and targets is None:
59             raise ValueError("In training mode, targets should be passed")
60         if self.training:
61             assert targets is not None
62             for target in targets:
63                 boxes = target["boxes"]
64                 if isinstance(boxes, torch.Tensor):
65                     if len(boxes.shape) != 2 or boxes.shape[-1] != 4:
66                         raise ValueError("Expected target boxes to be a tensor"
67                                          "of shape [N, 4], got {:}.".format(
68                                              boxes.shape))
69                 else:
70                     raise ValueError("Expected target boxes to be of type "
71                                      "Tensor, got {:}.".format(type(boxes)))
72 
73         original_image_sizes = torch.jit.annotate(List[Tuple[int, int]], [])
74         for img in images:
75             val = img.shape[-2:]
76             assert len(val) == 2
77             original_image_sizes.append((val[0], val[1]))
78 
79         images, targets = self.transform(images, targets)
80         features = self.backbone(images.tensors)
81         if isinstance(features, torch.Tensor):
82             features = OrderedDict([('0', features)])
83         proposals, proposal_losses = self.rpn(images, features, targets)
84         detections, detector_losses = self.roi_heads(features, proposals, images.image_sizes, targets)
85         detections = self.transform.postprocess(detections, images.image_sizes, original_image_sizes)
86 
87         losses = {}
88         losses.update(detector_losses)
89         losses.update(proposal_losses)
90 
91         if torch.jit.is_scripting():
92             if not self._has_warned:
93                 warnings.warn("RCNN always returns a (Losses, Detections) tuple in scripting")
94                 self._has_warned = True
95             return (losses, detections)
96         else:
97             return self.eager_outputs(losses, detections)
98
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/torchvision/models/detection/generalized_rcnn.py b/torchvision/models/detection/generalized_rcnn.py
--- a/torchvision/models/detection/generalized_rcnn.py
+++ b/torchvision/models/detection/generalized_rcnn.py
@@ -77,6 +77,21 @@
             original_image_sizes.append((val[0], val[1]))
 
         images, targets = self.transform(images, targets)
+
+        # Check for degenerate boxes
+        # TODO: Move this to a function
+        if targets is not None:
+            for target_idx, target in enumerate(targets):
+                boxes = target["boxes"]
+                degenerate_boxes = boxes[:, 2:] <= boxes[:, :2]
+                if degenerate_boxes.any():
+                    # print the first degenrate box
+                    bb_idx = degenerate_boxes.any(dim=1).nonzero().view(-1)[0]
+                    degen_bb: List[float] = boxes[bb_idx].tolist()
+                    raise ValueError("All bounding boxes should have positive height and width."
+                                     " Found invaid box {} for target at index {}."
+                                     .format(degen_bb, target_idx))
+
         features = self.backbone(images.tensors)
         if isinstance(features, torch.Tensor):
             features = OrderedDict([('0', features)])

{"golden_diff": "diff --git a/torchvision/models/detection/generalized_rcnn.py b/torchvision/models/detection/generalized_rcnn.py\n--- a/torchvision/models/detection/generalized_rcnn.py\n+++ b/torchvision/models/detection/generalized_rcnn.py\n@@ -77,6 +77,21 @@\n             original_image_sizes.append((val[0], val[1]))\n \n         images, targets = self.transform(images, targets)\n+\n+        # Check for degenerate boxes\n+        # TODO: Move this to a function\n+        if targets is not None:\n+            for target_idx, target in enumerate(targets):\n+                boxes = target[\"boxes\"]\n+                degenerate_boxes = boxes[:, 2:] <= boxes[:, :2]\n+                if degenerate_boxes.any():\n+                    # print the first degenrate box\n+                    bb_idx = degenerate_boxes.any(dim=1).nonzero().view(-1)[0]\n+                    degen_bb: List[float] = boxes[bb_idx].tolist()\n+                    raise ValueError(\"All bounding boxes should have positive height and width.\"\n+                                     \" Found invaid box {} for target at index {}.\"\n+                                     .format(degen_bb, target_idx))\n+\n         features = self.backbone(images.tensors)\n         if isinstance(features, torch.Tensor):\n             features = OrderedDict([('0', features)])\n", "issue": "Raise error if target boxes are degenerate in Faster R-CNN\nWe have had a number of reports with users saying that their training loss is nan after a few iterations.\r\n\r\nMost of the time, this is due to degenerate boxes (i.e., boxes with negative sizes or zero area). We should improve the user experience in those situations.\r\n\r\nI think that raising an error in `GeneralizedRCNN` if the target boxes are degenerate would be a good compromise.\r\n\r\nRelated issues: https://github.com/pytorch/vision/issues/2235 https://github.com/pytorch/vision/issues/1994 https://github.com/pytorch/vision/issues/1176 https://github.com/pytorch/vision/issues/1128 #1120 and #997\n", "before_files": [{"content": "# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.\n\"\"\"\nImplements the Generalized R-CNN framework\n\"\"\"\n\nfrom collections import OrderedDict\nimport torch\nfrom torch import nn\nimport warnings\nfrom torch.jit.annotations import Tuple, List, Dict, Optional\nfrom torch import Tensor\n\n\nclass GeneralizedRCNN(nn.Module):\n    \"\"\"\n    Main class for Generalized R-CNN.\n\n    Arguments:\n        backbone (nn.Module):\n        rpn (nn.Module):\n        roi_heads (nn.Module): takes the features + the proposals from the RPN and computes\n            detections / masks from it.\n        transform (nn.Module): performs the data transformation from the inputs to feed into\n            the model\n    \"\"\"\n\n    def __init__(self, backbone, rpn, roi_heads, transform):\n        super(GeneralizedRCNN, self).__init__()\n        self.transform = transform\n        self.backbone = backbone\n        self.rpn = rpn\n        self.roi_heads = roi_heads\n        # used only on torchscript mode\n        self._has_warned = False\n\n    @torch.jit.unused\n    def eager_outputs(self, losses, detections):\n        # type: (Dict[str, Tensor], List[Dict[str, Tensor]]) -> Tuple[Dict[str, Tensor], List[Dict[str, Tensor]]]\n        if self.training:\n            return losses\n\n        return detections\n\n    def forward(self, images, targets=None):\n        # type: (List[Tensor], Optional[List[Dict[str, Tensor]]]) -> Tuple[Dict[str, Tensor], List[Dict[str, Tensor]]]\n        \"\"\"\n        Arguments:\n            images (list[Tensor]): images to be processed\n            targets (list[Dict[Tensor]]): ground-truth boxes present in the image (optional)\n\n        Returns:\n            result (list[BoxList] or dict[Tensor]): the output from the model.\n                During training, it returns a dict[Tensor] which contains the losses.\n                During testing, it returns list[BoxList] contains additional fields\n                like `scores`, `labels` and `mask` (for Mask R-CNN models).\n\n        \"\"\"\n        if self.training and targets is None:\n            raise ValueError(\"In training mode, targets should be passed\")\n        if self.training:\n            assert targets is not None\n            for target in targets:\n                boxes = target[\"boxes\"]\n                if isinstance(boxes, torch.Tensor):\n                    if len(boxes.shape) != 2 or boxes.shape[-1] != 4:\n                        raise ValueError(\"Expected target boxes to be a tensor\"\n                                         \"of shape [N, 4], got {:}.\".format(\n                                             boxes.shape))\n                else:\n                    raise ValueError(\"Expected target boxes to be of type \"\n                                     \"Tensor, got {:}.\".format(type(boxes)))\n\n        original_image_sizes = torch.jit.annotate(List[Tuple[int, int]], [])\n        for img in images:\n            val = img.shape[-2:]\n            assert len(val) == 2\n            original_image_sizes.append((val[0], val[1]))\n\n        images, targets = self.transform(images, targets)\n        features = self.backbone(images.tensors)\n        if isinstance(features, torch.Tensor):\n            features = OrderedDict([('0', features)])\n        proposals, proposal_losses = self.rpn(images, features, targets)\n        detections, detector_losses = self.roi_heads(features, proposals, images.image_sizes, targets)\n        detections = self.transform.postprocess(detections, images.image_sizes, original_image_sizes)\n\n        losses = {}\n        losses.update(detector_losses)\n        losses.update(proposal_losses)\n\n        if torch.jit.is_scripting():\n            if not self._has_warned:\n                warnings.warn(\"RCNN always returns a (Losses, Detections) tuple in scripting\")\n                self._has_warned = True\n            return (losses, detections)\n        else:\n            return self.eager_outputs(losses, detections)\n", "path": "torchvision/models/detection/generalized_rcnn.py"}], "after_files": [{"content": "# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.\n\"\"\"\nImplements the Generalized R-CNN framework\n\"\"\"\n\nfrom collections import OrderedDict\nimport torch\nfrom torch import nn\nimport warnings\nfrom torch.jit.annotations import Tuple, List, Dict, Optional\nfrom torch import Tensor\n\n\nclass GeneralizedRCNN(nn.Module):\n    \"\"\"\n    Main class for Generalized R-CNN.\n\n    Arguments:\n        backbone (nn.Module):\n        rpn (nn.Module):\n        roi_heads (nn.Module): takes the features + the proposals from the RPN and computes\n            detections / masks from it.\n        transform (nn.Module): performs the data transformation from the inputs to feed into\n            the model\n    \"\"\"\n\n    def __init__(self, backbone, rpn, roi_heads, transform):\n        super(GeneralizedRCNN, self).__init__()\n        self.transform = transform\n        self.backbone = backbone\n        self.rpn = rpn\n        self.roi_heads = roi_heads\n        # used only on torchscript mode\n        self._has_warned = False\n\n    @torch.jit.unused\n    def eager_outputs(self, losses, detections):\n        # type: (Dict[str, Tensor], List[Dict[str, Tensor]]) -> Tuple[Dict[str, Tensor], List[Dict[str, Tensor]]]\n        if self.training:\n            return losses\n\n        return detections\n\n    def forward(self, images, targets=None):\n        # type: (List[Tensor], Optional[List[Dict[str, Tensor]]]) -> Tuple[Dict[str, Tensor], List[Dict[str, Tensor]]]\n        \"\"\"\n        Arguments:\n            images (list[Tensor]): images to be processed\n            targets (list[Dict[Tensor]]): ground-truth boxes present in the image (optional)\n\n        Returns:\n            result (list[BoxList] or dict[Tensor]): the output from the model.\n                During training, it returns a dict[Tensor] which contains the losses.\n                During testing, it returns list[BoxList] contains additional fields\n                like `scores`, `labels` and `mask` (for Mask R-CNN models).\n\n        \"\"\"\n        if self.training and targets is None:\n            raise ValueError(\"In training mode, targets should be passed\")\n        if self.training:\n            assert targets is not None\n            for target in targets:\n                boxes = target[\"boxes\"]\n                if isinstance(boxes, torch.Tensor):\n                    if len(boxes.shape) != 2 or boxes.shape[-1] != 4:\n                        raise ValueError(\"Expected target boxes to be a tensor\"\n                                         \"of shape [N, 4], got {:}.\".format(\n                                             boxes.shape))\n                else:\n                    raise ValueError(\"Expected target boxes to be of type \"\n                                     \"Tensor, got {:}.\".format(type(boxes)))\n\n        original_image_sizes = torch.jit.annotate(List[Tuple[int, int]], [])\n        for img in images:\n            val = img.shape[-2:]\n            assert len(val) == 2\n            original_image_sizes.append((val[0], val[1]))\n\n        images, targets = self.transform(images, targets)\n\n        # Check for degenerate boxes\n        # TODO: Move this to a function\n        if targets is not None:\n            for target_idx, target in enumerate(targets):\n                boxes = target[\"boxes\"]\n                degenerate_boxes = boxes[:, 2:] <= boxes[:, :2]\n                if degenerate_boxes.any():\n                    # print the first degenrate box\n                    bb_idx = degenerate_boxes.any(dim=1).nonzero().view(-1)[0]\n                    degen_bb: List[float] = boxes[bb_idx].tolist()\n                    raise ValueError(\"All bounding boxes should have positive height and width.\"\n                                     \" Found invaid box {} for target at index {}.\"\n                                     .format(degen_bb, target_idx))\n\n        features = self.backbone(images.tensors)\n        if isinstance(features, torch.Tensor):\n            features = OrderedDict([('0', features)])\n        proposals, proposal_losses = self.rpn(images, features, targets)\n        detections, detector_losses = self.roi_heads(features, proposals, images.image_sizes, targets)\n        detections = self.transform.postprocess(detections, images.image_sizes, original_image_sizes)\n\n        losses = {}\n        losses.update(detector_losses)\n        losses.update(proposal_losses)\n\n        if torch.jit.is_scripting():\n            if not self._has_warned:\n                warnings.warn(\"RCNN always returns a (Losses, Detections) tuple in scripting\")\n                self._has_warned = True\n            return (losses, detections)\n        else:\n            return self.eager_outputs(losses, detections)\n", "path": "torchvision/models/detection/generalized_rcnn.py"}]}