class_docstr: Feature Pyramid Network.
  
  This is an implementation of - Feature Pyramid Networks for Object
  Detection (https://arxiv.org/abs/1612.03144)
  
  Args:
      in_channels (List[int]): Number of input channels per scale.
      out_channels (int): Number of output channels (used at each scale)
      num_outs (int): Number of output scales.
      start_level (int): Index of the start input backbone level used to
          build the feature pyramid. Default: 0.
      end_level (int): Index of the end input backbone level (exclusive) to
          build the feature pyramid. Default: -1, which means the last level.
      add_extra_convs (bool | str): If bool, it decides whether to add conv
          layers on top of the original feature maps. Default to False.
          If True, its actual mode is specified by `extra_convs_on_inputs`.
          If str, it specifies the source feature map of the extra convs.
          Only the following options are allowed
  
          - 'on_input': Last feat map of neck inputs (i.e. backbone feature).
          - 'on_lateral':  Last feature map after lateral convs.
          - 'on_output': The last output feature map after fpn convs.
      extra_convs_on_inputs (bool, deprecated): Whether to apply extra convs
          on the original feature from the backbone. If True,
          it is equivalent to `add_extra_convs='on_input'`. If False, it is
          equivalent to set `add_extra_convs='on_output'`. Default to True.
      relu_before_extra_convs (bool): Whether to apply relu before the extra
          conv. Default: False.
      no_norm_on_lateral (bool): Whether to apply norm on lateral.
          Default: False.
      conv_cfg (dict): Config dict for convolution layer. Default: None.
      norm_cfg (dict): Config dict for normalization layer. Default: None.
      act_cfg (str): Config dict for activation layer in ConvModule.
          Default: None.
      upsample_cfg (dict): Config dict for interpolate layer.
          Default: `dict(mode='nearest')`
  
  Example:
      >>> import torch
      >>> in_channels = [2, 3, 5, 7]
      >>> scales = [340, 170, 84, 43]
      >>> inputs = [torch.rand(1, c, s, s)
      ...           for c, s in zip(in_channels, scales)]
      >>> self = FPN(in_channels, 11, len(in_channels)).eval()
      >>> outputs = self.forward(inputs)
      >>> for i in range(len(outputs)):
      ...     print(f'outputs[{i}].shape = {outputs[i].shape}')
      outputs[0].shape = torch.Size([1, 11, 340, 340])
      outputs[1].shape = torch.Size([1, 11, 170, 170])
      outputs[2].shape = torch.Size([1, 11, 84, 84])
      outputs[3].shape = torch.Size([1, 11, 43, 43])
code: def forward(self, inputs):
      assert len(inputs) == len(self.in_channels)
  
      # build laterals
      laterals = [
          lateral_conv(inputs[i + self.start_level])
          for i, lateral_conv in enumerate(self.lateral_convs)
      ]
  
      # build top-down path
      used_backbone_levels = len(laterals)
      for i in range(used_backbone_levels - 1, 0, -1):
          # In some cases, fixing `scale factor` (e.g. 2) is preferred, but
          #  it cannot co-exist with `size` in `F.interpolate`.
          if "scale_factor" in self.upsample_cfg:
              laterals[i - 1] += F.interpolate(
                  laterals[i], **self.upsample_cfg
              )
          else:
              prev_shape = laterals[i - 1].shape[2:]
              laterals[i - 1] += F.interpolate(
                  laterals[i], size=prev_shape, **self.upsample_cfg
              )
  
      # build outputs
      # part 1: from original levels
      outs = [
          self.fpn_convs[i](laterals[i])
          for i in range(used_backbone_levels)
      ]
      # part 2: add extra levels
      if self.num_outs > len(outs):
          # use max pool to get more levels on top of outputs
          # (e.g., Faster R-CNN, Mask R-CNN)
          if not self.add_extra_convs:
              for i in range(self.num_outs - used_backbone_levels):
                  outs.append(F.max_pool2d(outs[-1], 1, stride=2))
          # add conv layers on top of original feature maps (RetinaNet)
          else:
              if self.add_extra_convs == "on_input":
                  extra_source = inputs[self.backbone_end_level - 1]
              elif self.add_extra_convs == "on_lateral":
                  extra_source = laterals[-1]
              elif self.add_extra_convs == "on_output":
                  extra_source = outs[-1]
              else:
                  raise NotImplementedError
              outs.append(
                  self.fpn_convs[used_backbone_levels](extra_source)
              )
              for i in range(used_backbone_levels + 1, self.num_outs):
                  if self.relu_before_extra_convs:
                      outs.append(self.fpn_convs[i](F.relu(outs[-1])))
                  else:
                      outs.append(self.fpn_convs[i](outs[-1]))
      return tuple(outs)
  
file_path: lavis/lavis/common/annotator/uniformer/mmseg/models/necks/fpn.py
imports: import torch.nn
  import torch.nn.functional
  from annotator.uniformer.mmcv.cnn import ConvModule, xavier_init
  from ..builder import NECKS
label_desc: Use image node_id 3 for calling the FPN obj's underlying member method code with example usage: obj.forward(inputs) and returns: tuple