We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
ResNet FPN backbone
## 🐛 Bug

In https://github.com/pytorch/vision/blob/master/torchvision/models/detection/backbone_utils.py#L99, it says

> freeze layers only if pretrained backbone is used.

Therefore, if pretrained backbone is NOT used, any layers should be frozen.

But when I run:
```
from torchvision.models.detection.backbone_utils import resnet_fpn_backbone
resnet_fpn_backbone('resnet50', pretrained=False, norm_layer=None, trainable_layers=5)
```
I can see that parameters `bn1.weight, bn1.bias, fc.weight, fc.bias` are frozen on the [line 101](https://github.com/pytorch/vision/blob/master/torchvision/models/detection/backbone_utils.py#L101).

## To Reproduce

Steps to reproduce the behavior:

Run 
```
from torchvision.models.detection.backbone_utils import resnet_fpn_backbone
resnet_fpn_backbone('resnet50', pretrained=False, norm_layer=None, trainable_layers=5)
```

and see that on the [line 101](https://github.com/pytorch/vision/blob/master/torchvision/models/detection/backbone_utils.py#L101) parameters `bn1.weight, bn1.bias, fc.weight, fc.bias` are frozen despite that `trainable_layers=5` which should correspond to no frozen layers as written on the [line 83](https://github.com/pytorch/vision/blob/master/torchvision/models/detection/backbone_utils.py#L83).


## Expected behavior

No layers are frozen.

## Environment

PyTorch version: 1.7.0
Is debug build: True
CUDA used to build PyTorch: None
ROCM used to build PyTorch: N/A

OS: macOS 10.15.7 (x86_64)
GCC version: Could not collect
Clang version: 12.0.0 (clang-1200.0.32.29)
CMake version: version 3.18.2

Python version: 3.8 (64-bit runtime)
Is CUDA available: False
CUDA runtime version: No CUDA
GPU models and configuration: No CUDA
Nvidia driver version: No CUDA
cuDNN version: No CUDA
HIP runtime version: N/A
MIOpen runtime version: N/A

Versions of relevant libraries:
[pip3] numpy==1.19.2
[pip3] pytorch-lightning==1.1.1
[pip3] pytorch-lightning-bolts==0.2.5rc1
[pip3] torch==1.7.0
[pip3] torchvision==0.8.1
[conda] blas                      1.0                         mkl
[conda] mkl                       2019.5                      281    conda-forge
[conda] mkl-service               2.3.0            py38h0b31af3_0    conda-forge
[conda] mkl_fft                   1.2.0            py38hc64f4ea_0
[conda] mkl_random                1.1.1            py38h959d312_0
[conda] numpy                     1.19.2           py38h456fd55_0
[conda] numpy-base                1.19.2           py38hcfb5961_0
[conda] pytorch                   1.7.0                   py3.8_0    pytorch
[conda] pytorch-lightning         1.1.1              pyhd8ed1ab_0    conda-forge
[conda] pytorch-lightning-bolts   0.2.5rc1                 pypi_0    pypi
[conda] torchvision               0.8.1                  py38_cpu    pytorch



--- 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/backbone_utils.py`
Content:
```
1 import warnings
2 from torch import nn
3 from torchvision.ops.feature_pyramid_network import FeaturePyramidNetwork, LastLevelMaxPool
4 
5 from torchvision.ops import misc as misc_nn_ops
6 from .._utils import IntermediateLayerGetter
7 from .. import mobilenet
8 from .. import resnet
9 
10 
11 class BackboneWithFPN(nn.Module):
12     """
13     Adds a FPN on top of a model.
14     Internally, it uses torchvision.models._utils.IntermediateLayerGetter to
15     extract a submodel that returns the feature maps specified in return_layers.
16     The same limitations of IntermediatLayerGetter apply here.
17     Args:
18         backbone (nn.Module)
19         return_layers (Dict[name, new_name]): a dict containing the names
20             of the modules for which the activations will be returned as
21             the key of the dict, and the value of the dict is the name
22             of the returned activation (which the user can specify).
23         in_channels_list (List[int]): number of channels for each feature map
24             that is returned, in the order they are present in the OrderedDict
25         out_channels (int): number of channels in the FPN.
26     Attributes:
27         out_channels (int): the number of channels in the FPN
28     """
29     def __init__(self, backbone, return_layers, in_channels_list, out_channels, extra_blocks=None):
30         super(BackboneWithFPN, self).__init__()
31 
32         if extra_blocks is None:
33             extra_blocks = LastLevelMaxPool()
34 
35         self.body = IntermediateLayerGetter(backbone, return_layers=return_layers)
36         self.fpn = FeaturePyramidNetwork(
37             in_channels_list=in_channels_list,
38             out_channels=out_channels,
39             extra_blocks=extra_blocks,
40         )
41         self.out_channels = out_channels
42 
43     def forward(self, x):
44         x = self.body(x)
45         x = self.fpn(x)
46         return x
47 
48 
49 def resnet_fpn_backbone(
50     backbone_name,
51     pretrained,
52     norm_layer=misc_nn_ops.FrozenBatchNorm2d,
53     trainable_layers=3,
54     returned_layers=None,
55     extra_blocks=None
56 ):
57     """
58     Constructs a specified ResNet backbone with FPN on top. Freezes the specified number of layers in the backbone.
59 
60     Examples::
61 
62         >>> from torchvision.models.detection.backbone_utils import resnet_fpn_backbone
63         >>> backbone = resnet_fpn_backbone('resnet50', pretrained=True, trainable_layers=3)
64         >>> # get some dummy image
65         >>> x = torch.rand(1,3,64,64)
66         >>> # compute the output
67         >>> output = backbone(x)
68         >>> print([(k, v.shape) for k, v in output.items()])
69         >>> # returns
70         >>>   [('0', torch.Size([1, 256, 16, 16])),
71         >>>    ('1', torch.Size([1, 256, 8, 8])),
72         >>>    ('2', torch.Size([1, 256, 4, 4])),
73         >>>    ('3', torch.Size([1, 256, 2, 2])),
74         >>>    ('pool', torch.Size([1, 256, 1, 1]))]
75 
76     Args:
77         backbone_name (string): resnet architecture. Possible values are 'ResNet', 'resnet18', 'resnet34', 'resnet50',
78              'resnet101', 'resnet152', 'resnext50_32x4d', 'resnext101_32x8d', 'wide_resnet50_2', 'wide_resnet101_2'
79         pretrained (bool): If True, returns a model with backbone pre-trained on Imagenet
80         norm_layer (torchvision.ops): it is recommended to use the default value. For details visit:
81             (https://github.com/facebookresearch/maskrcnn-benchmark/issues/267)
82         trainable_layers (int): number of trainable (not frozen) resnet layers starting from final block.
83             Valid values are between 0 and 5, with 5 meaning all backbone layers are trainable.
84         returned_layers (list of int): The layers of the network to return. Each entry must be in ``[1, 4]``.
85             By default all layers are returned.
86         extra_blocks (ExtraFPNBlock or None): if provided, extra operations will
87             be performed. It is expected to take the fpn features, the original
88             features and the names of the original features as input, and returns
89             a new list of feature maps and their corresponding names. By
90             default a ``LastLevelMaxPool`` is used.
91     """
92     backbone = resnet.__dict__[backbone_name](
93         pretrained=pretrained,
94         norm_layer=norm_layer)
95 
96     # select layers that wont be frozen
97     assert 0 <= trainable_layers <= 5
98     layers_to_train = ['layer4', 'layer3', 'layer2', 'layer1', 'conv1'][:trainable_layers]
99     # freeze layers only if pretrained backbone is used
100     for name, parameter in backbone.named_parameters():
101         if all([not name.startswith(layer) for layer in layers_to_train]):
102             parameter.requires_grad_(False)
103 
104     if extra_blocks is None:
105         extra_blocks = LastLevelMaxPool()
106 
107     if returned_layers is None:
108         returned_layers = [1, 2, 3, 4]
109     assert min(returned_layers) > 0 and max(returned_layers) < 5
110     return_layers = {f'layer{k}': str(v) for v, k in enumerate(returned_layers)}
111 
112     in_channels_stage2 = backbone.inplanes // 8
113     in_channels_list = [in_channels_stage2 * 2 ** (i - 1) for i in returned_layers]
114     out_channels = 256
115     return BackboneWithFPN(backbone, return_layers, in_channels_list, out_channels, extra_blocks=extra_blocks)
116 
117 
118 def _validate_trainable_layers(pretrained, trainable_backbone_layers, max_value, default_value):
119     # dont freeze any layers if pretrained model or backbone is not used
120     if not pretrained:
121         if trainable_backbone_layers is not None:
122             warnings.warn(
123                 "Changing trainable_backbone_layers has not effect if "
124                 "neither pretrained nor pretrained_backbone have been set to True, "
125                 "falling back to trainable_backbone_layers={} so that all layers are trainable".format(max_value))
126         trainable_backbone_layers = max_value
127 
128     # by default freeze first blocks
129     if trainable_backbone_layers is None:
130         trainable_backbone_layers = default_value
131     assert 0 <= trainable_backbone_layers <= max_value
132     return trainable_backbone_layers
133 
134 
135 def mobilenet_backbone(
136     backbone_name,
137     pretrained,
138     fpn,
139     norm_layer=misc_nn_ops.FrozenBatchNorm2d,
140     trainable_layers=2,
141     returned_layers=None,
142     extra_blocks=None
143 ):
144     backbone = mobilenet.__dict__[backbone_name](pretrained=pretrained, norm_layer=norm_layer).features
145 
146     # Gather the indices of blocks which are strided. These are the locations of C1, ..., Cn-1 blocks.
147     # The first and last blocks are always included because they are the C0 (conv1) and Cn.
148     stage_indices = [0] + [i for i, b in enumerate(backbone) if getattr(b, "_is_cn", False)] + [len(backbone) - 1]
149     num_stages = len(stage_indices)
150 
151     # find the index of the layer from which we wont freeze
152     assert 0 <= trainable_layers <= num_stages
153     freeze_before = num_stages if trainable_layers == 0 else stage_indices[num_stages - trainable_layers]
154 
155     # freeze layers only if pretrained backbone is used
156     for b in backbone[:freeze_before]:
157         for parameter in b.parameters():
158             parameter.requires_grad_(False)
159 
160     out_channels = 256
161     if fpn:
162         if extra_blocks is None:
163             extra_blocks = LastLevelMaxPool()
164 
165         if returned_layers is None:
166             returned_layers = [num_stages - 2, num_stages - 1]
167         assert min(returned_layers) >= 0 and max(returned_layers) < num_stages
168         return_layers = {f'{stage_indices[k]}': str(v) for v, k in enumerate(returned_layers)}
169 
170         in_channels_list = [backbone[stage_indices[i]].out_channels for i in returned_layers]
171         return BackboneWithFPN(backbone, return_layers, in_channels_list, out_channels, extra_blocks=extra_blocks)
172     else:
173         m = nn.Sequential(
174             backbone,
175             # depthwise linear combination of channels to reduce their size
176             nn.Conv2d(backbone[-1].out_channels, out_channels, 1),
177         )
178         m.out_channels = out_channels
179         return m
180
```
--- 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/backbone_utils.py b/torchvision/models/detection/backbone_utils.py
--- a/torchvision/models/detection/backbone_utils.py
+++ b/torchvision/models/detection/backbone_utils.py
@@ -96,7 +96,8 @@
     # select layers that wont be frozen
     assert 0 <= trainable_layers <= 5
     layers_to_train = ['layer4', 'layer3', 'layer2', 'layer1', 'conv1'][:trainable_layers]
-    # freeze layers only if pretrained backbone is used
+    if trainable_layers == 5:
+        layers_to_train.append('bn1')
     for name, parameter in backbone.named_parameters():
         if all([not name.startswith(layer) for layer in layers_to_train]):
             parameter.requires_grad_(False)
@@ -152,7 +153,6 @@
     assert 0 <= trainable_layers <= num_stages
     freeze_before = num_stages if trainable_layers == 0 else stage_indices[num_stages - trainable_layers]
 
-    # freeze layers only if pretrained backbone is used
     for b in backbone[:freeze_before]:
         for parameter in b.parameters():
             parameter.requires_grad_(False)

{"golden_diff": "diff --git a/torchvision/models/detection/backbone_utils.py b/torchvision/models/detection/backbone_utils.py\n--- a/torchvision/models/detection/backbone_utils.py\n+++ b/torchvision/models/detection/backbone_utils.py\n@@ -96,7 +96,8 @@\n     # select layers that wont be frozen\n     assert 0 <= trainable_layers <= 5\n     layers_to_train = ['layer4', 'layer3', 'layer2', 'layer1', 'conv1'][:trainable_layers]\n-    # freeze layers only if pretrained backbone is used\n+    if trainable_layers == 5:\n+        layers_to_train.append('bn1')\n     for name, parameter in backbone.named_parameters():\n         if all([not name.startswith(layer) for layer in layers_to_train]):\n             parameter.requires_grad_(False)\n@@ -152,7 +153,6 @@\n     assert 0 <= trainable_layers <= num_stages\n     freeze_before = num_stages if trainable_layers == 0 else stage_indices[num_stages - trainable_layers]\n \n-    # freeze layers only if pretrained backbone is used\n     for b in backbone[:freeze_before]:\n         for parameter in b.parameters():\n             parameter.requires_grad_(False)\n", "issue": "ResNet FPN backbone\n## \ud83d\udc1b Bug\r\n\r\nIn https://github.com/pytorch/vision/blob/master/torchvision/models/detection/backbone_utils.py#L99, it says\r\n\r\n> freeze layers only if pretrained backbone is used.\r\n\r\nTherefore, if pretrained backbone is NOT used, any layers should be frozen.\r\n\r\nBut when I run:\r\n```\r\nfrom torchvision.models.detection.backbone_utils import resnet_fpn_backbone\r\nresnet_fpn_backbone('resnet50', pretrained=False, norm_layer=None, trainable_layers=5)\r\n```\r\nI can see that parameters `bn1.weight, bn1.bias, fc.weight, fc.bias` are frozen on the [line 101](https://github.com/pytorch/vision/blob/master/torchvision/models/detection/backbone_utils.py#L101).\r\n\r\n## To Reproduce\r\n\r\nSteps to reproduce the behavior:\r\n\r\nRun \r\n```\r\nfrom torchvision.models.detection.backbone_utils import resnet_fpn_backbone\r\nresnet_fpn_backbone('resnet50', pretrained=False, norm_layer=None, trainable_layers=5)\r\n```\r\n\r\nand see that on the [line 101](https://github.com/pytorch/vision/blob/master/torchvision/models/detection/backbone_utils.py#L101) parameters `bn1.weight, bn1.bias, fc.weight, fc.bias` are frozen despite that `trainable_layers=5` which should correspond to no frozen layers as written on the [line 83](https://github.com/pytorch/vision/blob/master/torchvision/models/detection/backbone_utils.py#L83).\r\n\r\n\r\n## Expected behavior\r\n\r\nNo layers are frozen.\r\n\r\n## Environment\r\n\r\nPyTorch version: 1.7.0\r\nIs debug build: True\r\nCUDA used to build PyTorch: None\r\nROCM used to build PyTorch: N/A\r\n\r\nOS: macOS 10.15.7 (x86_64)\r\nGCC version: Could not collect\r\nClang version: 12.0.0 (clang-1200.0.32.29)\r\nCMake version: version 3.18.2\r\n\r\nPython version: 3.8 (64-bit runtime)\r\nIs CUDA available: False\r\nCUDA runtime version: No CUDA\r\nGPU models and configuration: No CUDA\r\nNvidia driver version: No CUDA\r\ncuDNN version: No CUDA\r\nHIP runtime version: N/A\r\nMIOpen runtime version: N/A\r\n\r\nVersions of relevant libraries:\r\n[pip3] numpy==1.19.2\r\n[pip3] pytorch-lightning==1.1.1\r\n[pip3] pytorch-lightning-bolts==0.2.5rc1\r\n[pip3] torch==1.7.0\r\n[pip3] torchvision==0.8.1\r\n[conda] blas                      1.0                         mkl\r\n[conda] mkl                       2019.5                      281    conda-forge\r\n[conda] mkl-service               2.3.0            py38h0b31af3_0    conda-forge\r\n[conda] mkl_fft                   1.2.0            py38hc64f4ea_0\r\n[conda] mkl_random                1.1.1            py38h959d312_0\r\n[conda] numpy                     1.19.2           py38h456fd55_0\r\n[conda] numpy-base                1.19.2           py38hcfb5961_0\r\n[conda] pytorch                   1.7.0                   py3.8_0    pytorch\r\n[conda] pytorch-lightning         1.1.1              pyhd8ed1ab_0    conda-forge\r\n[conda] pytorch-lightning-bolts   0.2.5rc1                 pypi_0    pypi\r\n[conda] torchvision               0.8.1                  py38_cpu    pytorch\r\n\r\n\n", "before_files": [{"content": "import warnings\nfrom torch import nn\nfrom torchvision.ops.feature_pyramid_network import FeaturePyramidNetwork, LastLevelMaxPool\n\nfrom torchvision.ops import misc as misc_nn_ops\nfrom .._utils import IntermediateLayerGetter\nfrom .. import mobilenet\nfrom .. import resnet\n\n\nclass BackboneWithFPN(nn.Module):\n    \"\"\"\n    Adds a FPN on top of a model.\n    Internally, it uses torchvision.models._utils.IntermediateLayerGetter to\n    extract a submodel that returns the feature maps specified in return_layers.\n    The same limitations of IntermediatLayerGetter apply here.\n    Args:\n        backbone (nn.Module)\n        return_layers (Dict[name, new_name]): a dict containing the names\n            of the modules for which the activations will be returned as\n            the key of the dict, and the value of the dict is the name\n            of the returned activation (which the user can specify).\n        in_channels_list (List[int]): number of channels for each feature map\n            that is returned, in the order they are present in the OrderedDict\n        out_channels (int): number of channels in the FPN.\n    Attributes:\n        out_channels (int): the number of channels in the FPN\n    \"\"\"\n    def __init__(self, backbone, return_layers, in_channels_list, out_channels, extra_blocks=None):\n        super(BackboneWithFPN, self).__init__()\n\n        if extra_blocks is None:\n            extra_blocks = LastLevelMaxPool()\n\n        self.body = IntermediateLayerGetter(backbone, return_layers=return_layers)\n        self.fpn = FeaturePyramidNetwork(\n            in_channels_list=in_channels_list,\n            out_channels=out_channels,\n            extra_blocks=extra_blocks,\n        )\n        self.out_channels = out_channels\n\n    def forward(self, x):\n        x = self.body(x)\n        x = self.fpn(x)\n        return x\n\n\ndef resnet_fpn_backbone(\n    backbone_name,\n    pretrained,\n    norm_layer=misc_nn_ops.FrozenBatchNorm2d,\n    trainable_layers=3,\n    returned_layers=None,\n    extra_blocks=None\n):\n    \"\"\"\n    Constructs a specified ResNet backbone with FPN on top. Freezes the specified number of layers in the backbone.\n\n    Examples::\n\n        >>> from torchvision.models.detection.backbone_utils import resnet_fpn_backbone\n        >>> backbone = resnet_fpn_backbone('resnet50', pretrained=True, trainable_layers=3)\n        >>> # get some dummy image\n        >>> x = torch.rand(1,3,64,64)\n        >>> # compute the output\n        >>> output = backbone(x)\n        >>> print([(k, v.shape) for k, v in output.items()])\n        >>> # returns\n        >>>   [('0', torch.Size([1, 256, 16, 16])),\n        >>>    ('1', torch.Size([1, 256, 8, 8])),\n        >>>    ('2', torch.Size([1, 256, 4, 4])),\n        >>>    ('3', torch.Size([1, 256, 2, 2])),\n        >>>    ('pool', torch.Size([1, 256, 1, 1]))]\n\n    Args:\n        backbone_name (string): resnet architecture. Possible values are 'ResNet', 'resnet18', 'resnet34', 'resnet50',\n             'resnet101', 'resnet152', 'resnext50_32x4d', 'resnext101_32x8d', 'wide_resnet50_2', 'wide_resnet101_2'\n        pretrained (bool): If True, returns a model with backbone pre-trained on Imagenet\n        norm_layer (torchvision.ops): it is recommended to use the default value. For details visit:\n            (https://github.com/facebookresearch/maskrcnn-benchmark/issues/267)\n        trainable_layers (int): number of trainable (not frozen) resnet layers starting from final block.\n            Valid values are between 0 and 5, with 5 meaning all backbone layers are trainable.\n        returned_layers (list of int): The layers of the network to return. Each entry must be in ``[1, 4]``.\n            By default all layers are returned.\n        extra_blocks (ExtraFPNBlock or None): if provided, extra operations will\n            be performed. It is expected to take the fpn features, the original\n            features and the names of the original features as input, and returns\n            a new list of feature maps and their corresponding names. By\n            default a ``LastLevelMaxPool`` is used.\n    \"\"\"\n    backbone = resnet.__dict__[backbone_name](\n        pretrained=pretrained,\n        norm_layer=norm_layer)\n\n    # select layers that wont be frozen\n    assert 0 <= trainable_layers <= 5\n    layers_to_train = ['layer4', 'layer3', 'layer2', 'layer1', 'conv1'][:trainable_layers]\n    # freeze layers only if pretrained backbone is used\n    for name, parameter in backbone.named_parameters():\n        if all([not name.startswith(layer) for layer in layers_to_train]):\n            parameter.requires_grad_(False)\n\n    if extra_blocks is None:\n        extra_blocks = LastLevelMaxPool()\n\n    if returned_layers is None:\n        returned_layers = [1, 2, 3, 4]\n    assert min(returned_layers) > 0 and max(returned_layers) < 5\n    return_layers = {f'layer{k}': str(v) for v, k in enumerate(returned_layers)}\n\n    in_channels_stage2 = backbone.inplanes // 8\n    in_channels_list = [in_channels_stage2 * 2 ** (i - 1) for i in returned_layers]\n    out_channels = 256\n    return BackboneWithFPN(backbone, return_layers, in_channels_list, out_channels, extra_blocks=extra_blocks)\n\n\ndef _validate_trainable_layers(pretrained, trainable_backbone_layers, max_value, default_value):\n    # dont freeze any layers if pretrained model or backbone is not used\n    if not pretrained:\n        if trainable_backbone_layers is not None:\n            warnings.warn(\n                \"Changing trainable_backbone_layers has not effect if \"\n                \"neither pretrained nor pretrained_backbone have been set to True, \"\n                \"falling back to trainable_backbone_layers={} so that all layers are trainable\".format(max_value))\n        trainable_backbone_layers = max_value\n\n    # by default freeze first blocks\n    if trainable_backbone_layers is None:\n        trainable_backbone_layers = default_value\n    assert 0 <= trainable_backbone_layers <= max_value\n    return trainable_backbone_layers\n\n\ndef mobilenet_backbone(\n    backbone_name,\n    pretrained,\n    fpn,\n    norm_layer=misc_nn_ops.FrozenBatchNorm2d,\n    trainable_layers=2,\n    returned_layers=None,\n    extra_blocks=None\n):\n    backbone = mobilenet.__dict__[backbone_name](pretrained=pretrained, norm_layer=norm_layer).features\n\n    # Gather the indices of blocks which are strided. These are the locations of C1, ..., Cn-1 blocks.\n    # The first and last blocks are always included because they are the C0 (conv1) and Cn.\n    stage_indices = [0] + [i for i, b in enumerate(backbone) if getattr(b, \"_is_cn\", False)] + [len(backbone) - 1]\n    num_stages = len(stage_indices)\n\n    # find the index of the layer from which we wont freeze\n    assert 0 <= trainable_layers <= num_stages\n    freeze_before = num_stages if trainable_layers == 0 else stage_indices[num_stages - trainable_layers]\n\n    # freeze layers only if pretrained backbone is used\n    for b in backbone[:freeze_before]:\n        for parameter in b.parameters():\n            parameter.requires_grad_(False)\n\n    out_channels = 256\n    if fpn:\n        if extra_blocks is None:\n            extra_blocks = LastLevelMaxPool()\n\n        if returned_layers is None:\n            returned_layers = [num_stages - 2, num_stages - 1]\n        assert min(returned_layers) >= 0 and max(returned_layers) < num_stages\n        return_layers = {f'{stage_indices[k]}': str(v) for v, k in enumerate(returned_layers)}\n\n        in_channels_list = [backbone[stage_indices[i]].out_channels for i in returned_layers]\n        return BackboneWithFPN(backbone, return_layers, in_channels_list, out_channels, extra_blocks=extra_blocks)\n    else:\n        m = nn.Sequential(\n            backbone,\n            # depthwise linear combination of channels to reduce their size\n            nn.Conv2d(backbone[-1].out_channels, out_channels, 1),\n        )\n        m.out_channels = out_channels\n        return m\n", "path": "torchvision/models/detection/backbone_utils.py"}], "after_files": [{"content": "import warnings\nfrom torch import nn\nfrom torchvision.ops.feature_pyramid_network import FeaturePyramidNetwork, LastLevelMaxPool\n\nfrom torchvision.ops import misc as misc_nn_ops\nfrom .._utils import IntermediateLayerGetter\nfrom .. import mobilenet\nfrom .. import resnet\n\n\nclass BackboneWithFPN(nn.Module):\n    \"\"\"\n    Adds a FPN on top of a model.\n    Internally, it uses torchvision.models._utils.IntermediateLayerGetter to\n    extract a submodel that returns the feature maps specified in return_layers.\n    The same limitations of IntermediatLayerGetter apply here.\n    Args:\n        backbone (nn.Module)\n        return_layers (Dict[name, new_name]): a dict containing the names\n            of the modules for which the activations will be returned as\n            the key of the dict, and the value of the dict is the name\n            of the returned activation (which the user can specify).\n        in_channels_list (List[int]): number of channels for each feature map\n            that is returned, in the order they are present in the OrderedDict\n        out_channels (int): number of channels in the FPN.\n    Attributes:\n        out_channels (int): the number of channels in the FPN\n    \"\"\"\n    def __init__(self, backbone, return_layers, in_channels_list, out_channels, extra_blocks=None):\n        super(BackboneWithFPN, self).__init__()\n\n        if extra_blocks is None:\n            extra_blocks = LastLevelMaxPool()\n\n        self.body = IntermediateLayerGetter(backbone, return_layers=return_layers)\n        self.fpn = FeaturePyramidNetwork(\n            in_channels_list=in_channels_list,\n            out_channels=out_channels,\n            extra_blocks=extra_blocks,\n        )\n        self.out_channels = out_channels\n\n    def forward(self, x):\n        x = self.body(x)\n        x = self.fpn(x)\n        return x\n\n\ndef resnet_fpn_backbone(\n    backbone_name,\n    pretrained,\n    norm_layer=misc_nn_ops.FrozenBatchNorm2d,\n    trainable_layers=3,\n    returned_layers=None,\n    extra_blocks=None\n):\n    \"\"\"\n    Constructs a specified ResNet backbone with FPN on top. Freezes the specified number of layers in the backbone.\n\n    Examples::\n\n        >>> from torchvision.models.detection.backbone_utils import resnet_fpn_backbone\n        >>> backbone = resnet_fpn_backbone('resnet50', pretrained=True, trainable_layers=3)\n        >>> # get some dummy image\n        >>> x = torch.rand(1,3,64,64)\n        >>> # compute the output\n        >>> output = backbone(x)\n        >>> print([(k, v.shape) for k, v in output.items()])\n        >>> # returns\n        >>>   [('0', torch.Size([1, 256, 16, 16])),\n        >>>    ('1', torch.Size([1, 256, 8, 8])),\n        >>>    ('2', torch.Size([1, 256, 4, 4])),\n        >>>    ('3', torch.Size([1, 256, 2, 2])),\n        >>>    ('pool', torch.Size([1, 256, 1, 1]))]\n\n    Args:\n        backbone_name (string): resnet architecture. Possible values are 'ResNet', 'resnet18', 'resnet34', 'resnet50',\n             'resnet101', 'resnet152', 'resnext50_32x4d', 'resnext101_32x8d', 'wide_resnet50_2', 'wide_resnet101_2'\n        pretrained (bool): If True, returns a model with backbone pre-trained on Imagenet\n        norm_layer (torchvision.ops): it is recommended to use the default value. For details visit:\n            (https://github.com/facebookresearch/maskrcnn-benchmark/issues/267)\n        trainable_layers (int): number of trainable (not frozen) resnet layers starting from final block.\n            Valid values are between 0 and 5, with 5 meaning all backbone layers are trainable.\n        returned_layers (list of int): The layers of the network to return. Each entry must be in ``[1, 4]``.\n            By default all layers are returned.\n        extra_blocks (ExtraFPNBlock or None): if provided, extra operations will\n            be performed. It is expected to take the fpn features, the original\n            features and the names of the original features as input, and returns\n            a new list of feature maps and their corresponding names. By\n            default a ``LastLevelMaxPool`` is used.\n    \"\"\"\n    backbone = resnet.__dict__[backbone_name](\n        pretrained=pretrained,\n        norm_layer=norm_layer)\n\n    # select layers that wont be frozen\n    assert 0 <= trainable_layers <= 5\n    layers_to_train = ['layer4', 'layer3', 'layer2', 'layer1', 'conv1'][:trainable_layers]\n    if trainable_layers == 5:\n        layers_to_train.append('bn1')\n    for name, parameter in backbone.named_parameters():\n        if all([not name.startswith(layer) for layer in layers_to_train]):\n            parameter.requires_grad_(False)\n\n    if extra_blocks is None:\n        extra_blocks = LastLevelMaxPool()\n\n    if returned_layers is None:\n        returned_layers = [1, 2, 3, 4]\n    assert min(returned_layers) > 0 and max(returned_layers) < 5\n    return_layers = {f'layer{k}': str(v) for v, k in enumerate(returned_layers)}\n\n    in_channels_stage2 = backbone.inplanes // 8\n    in_channels_list = [in_channels_stage2 * 2 ** (i - 1) for i in returned_layers]\n    out_channels = 256\n    return BackboneWithFPN(backbone, return_layers, in_channels_list, out_channels, extra_blocks=extra_blocks)\n\n\ndef _validate_trainable_layers(pretrained, trainable_backbone_layers, max_value, default_value):\n    # dont freeze any layers if pretrained model or backbone is not used\n    if not pretrained:\n        if trainable_backbone_layers is not None:\n            warnings.warn(\n                \"Changing trainable_backbone_layers has not effect if \"\n                \"neither pretrained nor pretrained_backbone have been set to True, \"\n                \"falling back to trainable_backbone_layers={} so that all layers are trainable\".format(max_value))\n        trainable_backbone_layers = max_value\n\n    # by default freeze first blocks\n    if trainable_backbone_layers is None:\n        trainable_backbone_layers = default_value\n    assert 0 <= trainable_backbone_layers <= max_value\n    return trainable_backbone_layers\n\n\ndef mobilenet_backbone(\n    backbone_name,\n    pretrained,\n    fpn,\n    norm_layer=misc_nn_ops.FrozenBatchNorm2d,\n    trainable_layers=2,\n    returned_layers=None,\n    extra_blocks=None\n):\n    backbone = mobilenet.__dict__[backbone_name](pretrained=pretrained, norm_layer=norm_layer).features\n\n    # Gather the indices of blocks which are strided. These are the locations of C1, ..., Cn-1 blocks.\n    # The first and last blocks are always included because they are the C0 (conv1) and Cn.\n    stage_indices = [0] + [i for i, b in enumerate(backbone) if getattr(b, \"_is_cn\", False)] + [len(backbone) - 1]\n    num_stages = len(stage_indices)\n\n    # find the index of the layer from which we wont freeze\n    assert 0 <= trainable_layers <= num_stages\n    freeze_before = num_stages if trainable_layers == 0 else stage_indices[num_stages - trainable_layers]\n\n    for b in backbone[:freeze_before]:\n        for parameter in b.parameters():\n            parameter.requires_grad_(False)\n\n    out_channels = 256\n    if fpn:\n        if extra_blocks is None:\n            extra_blocks = LastLevelMaxPool()\n\n        if returned_layers is None:\n            returned_layers = [num_stages - 2, num_stages - 1]\n        assert min(returned_layers) >= 0 and max(returned_layers) < num_stages\n        return_layers = {f'{stage_indices[k]}': str(v) for v, k in enumerate(returned_layers)}\n\n        in_channels_list = [backbone[stage_indices[i]].out_channels for i in returned_layers]\n        return BackboneWithFPN(backbone, return_layers, in_channels_list, out_channels, extra_blocks=extra_blocks)\n    else:\n        m = nn.Sequential(\n            backbone,\n            # depthwise linear combination of channels to reduce their size\n            nn.Conv2d(backbone[-1].out_channels, out_channels, 1),\n        )\n        m.out_channels = out_channels\n        return m\n", "path": "torchvision/models/detection/backbone_utils.py"}]}