class_docstr: Implementation of `Grid Head <https://arxiv.org/abs/1811.12030>`_
  
  Args:
      grid_points (int): The number of grid points. Defaults to 9.
      num_convs (int): The number of convolution layers. Defaults to 8.
      roi_feat_size (int): RoI feature size. Default to 14.
      in_channels (int): The channel number of inputs features.
          Defaults to 256.
      conv_kernel_size (int): The kernel size of convolution layers.
          Defaults to 3.
      point_feat_channels (int): The number of channels of each point
          features. Defaults to 64.
      class_agnostic (bool): Whether use class agnostic classification.
          If so, the output channels of logits will be 1. Defaults to False.
      loss_grid (:obj:`ConfigDict` or dict): Config of grid loss.
      conv_cfg (:obj:`ConfigDict` or dict, optional) dictionary to
          construct and config conv layer.
      norm_cfg (:obj:`ConfigDict` or dict): dictionary to construct and
          config norm layer.
      init_cfg (:obj:`ConfigDict` or dict or list[:obj:`ConfigDict` or             dict]): Initialization config dict.
code: def __init__(
      self,
      grid_points: int = 9,
      num_convs: int = 8,
      roi_feat_size: int = 14,
      in_channels: int = 256,
      conv_kernel_size: int = 3,
      point_feat_channels: int = 64,
      deconv_kernel_size: int = 4,
      class_agnostic: bool = False,
      loss_grid: ConfigType = dict(
          type="CrossEntropyLoss", use_sigmoid=True, loss_weight=15
      ),
      conv_cfg: OptConfigType = None,
      norm_cfg: ConfigType = dict(type="GN", num_groups=36),
      init_cfg: MultiConfig = [
          dict(type="Kaiming", layer=["Conv2d", "Linear"]),
          dict(
              type="Normal",
              layer="ConvTranspose2d",
              std=0.001,
              override=dict(
                  type="Normal",
                  name="deconv2",
                  std=0.001,
                  bias=-np.log(0.99 / 0.01),
              ),
          ),
      ],
  ) -> None:
      super().__init__(init_cfg=init_cfg)
      self.grid_points = grid_points
      self.num_convs = num_convs
      self.roi_feat_size = roi_feat_size
      self.in_channels = in_channels
      self.conv_kernel_size = conv_kernel_size
      self.point_feat_channels = point_feat_channels
      self.conv_out_channels = (
          self.point_feat_channels * self.grid_points
      )
      self.class_agnostic = class_agnostic
      self.conv_cfg = conv_cfg
      self.norm_cfg = norm_cfg
      if isinstance(norm_cfg, dict) and norm_cfg["type"] == "GN":
          assert self.conv_out_channels % norm_cfg["num_groups"] == 0
  
      assert self.grid_points >= 4
      self.grid_size = int(np.sqrt(self.grid_points))
      if self.grid_size * self.grid_size != self.grid_points:
          raise ValueError("grid_points must be a square number")
  
      # the predicted heatmap is half of whole_map_size
      if not isinstance(self.roi_feat_size, int):
          raise ValueError(
              "Only square RoIs are supporeted in Grid R-CNN"
          )
      self.whole_map_size = self.roi_feat_size * 4
  
      # compute point-wise sub-regions
      self.sub_regions = self.calc_sub_regions()
  
      self.convs = []
      for i in range(self.num_convs):
          in_channels = (
              self.in_channels if i == 0 else self.conv_out_channels
          )
          stride = 2 if i == 0 else 1
          padding = (self.conv_kernel_size - 1) // 2
          self.convs.append(
              ConvModule(
                  in_channels,
                  self.conv_out_channels,
                  self.conv_kernel_size,
                  stride=stride,
                  padding=padding,
                  conv_cfg=self.conv_cfg,
                  norm_cfg=self.norm_cfg,
                  bias=True,
              )
          )
      self.convs = nn.Sequential(*self.convs)
  
      self.deconv1 = nn.ConvTranspose2d(
          self.conv_out_channels,
          self.conv_out_channels,
          kernel_size=deconv_kernel_size,
          stride=2,
          padding=(deconv_kernel_size - 2) // 2,
          groups=grid_points,
      )
      self.norm1 = nn.GroupNorm(grid_points, self.conv_out_channels)
      self.deconv2 = nn.ConvTranspose2d(
          self.conv_out_channels,
          grid_points,
          kernel_size=deconv_kernel_size,
          stride=2,
          padding=(deconv_kernel_size - 2) // 2,
          groups=grid_points,
      )
  
      # find the 4-neighbor of each grid point
      self.neighbor_points = []
      grid_size = self.grid_size
      for i in range(grid_size):  # i-th column
          for j in range(grid_size):  # j-th row
              neighbors = []
              if i > 0:  # left: (i - 1, j)
                  neighbors.append((i - 1) * grid_size + j)
              if j > 0:  # up: (i, j - 1)
                  neighbors.append(i * grid_size + j - 1)
              if j < grid_size - 1:  # down: (i, j + 1)
                  neighbors.append(i * grid_size + j + 1)
              if i < grid_size - 1:  # right: (i + 1, j)
                  neighbors.append((i + 1) * grid_size + j)
              self.neighbor_points.append(tuple(neighbors))
      # total edges in the grid
      self.num_edges = sum([len(p) for p in self.neighbor_points])
  
      self.forder_trans = (
          nn.ModuleList()
      )  # first-order feature transition
      self.sorder_trans = (
          nn.ModuleList()
      )  # second-order feature transition
      for neighbors in self.neighbor_points:
          fo_trans = nn.ModuleList()
          so_trans = nn.ModuleList()
          for _ in range(len(neighbors)):
              # each transition module consists of a 5x5 depth-wise conv and
              # 1x1 conv.
              fo_trans.append(
                  nn.Sequential(
                      nn.Conv2d(
                          self.point_feat_channels,
                          self.point_feat_channels,
                          5,
                          stride=1,
                          padding=2,
                          groups=self.point_feat_channels,
                      ),
                      nn.Conv2d(
                          self.point_feat_channels,
                          self.point_feat_channels,
                          1,
                      ),
                  )
              )
              so_trans.append(
                  nn.Sequential(
                      nn.Conv2d(
                          self.point_feat_channels,
                          self.point_feat_channels,
                          5,
                          1,
                          2,
                          groups=self.point_feat_channels,
                      ),
                      nn.Conv2d(
                          self.point_feat_channels,
                          self.point_feat_channels,
                          1,
                      ),
                  )
              )
          self.forder_trans.append(fo_trans)
          self.sorder_trans.append(so_trans)
  
      self.loss_grid = MODELS.build(loss_grid)
  
imports: from typing import Dict, List, Tuple
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  from mmcv.cnn import ConvModule
  from mmengine.config import ConfigDict
  from mmengine.model import BaseModule
  from mmengine.structures import InstanceData
  from torch import Tensor
  from mmdet.models.task_modules.samplers import SamplingResult
  from mmdet.registry import MODELS
  from mmdet.utils import ConfigType, InstanceList, MultiConfig, OptConfigType
label_desc: Use image node_id 1 to create a new GridHead object from inherited base classes: BaseModule with example: obj = GridHead(grid_points, num_convs, roi_feat_size, in_channels, conv_kernel_size, point_feat_channels, deconv_kernel_size, class_agnostic, loss_grid, conv_cfg, norm_cfg, init_cfg)