class_docstr: Grouped reversible residual connections for GNNs, as introduced in
  `Training Graph Neural Networks with 1000 Layers <https://arxiv.org/abs/2106.07476>`__
  
  It uniformly partitions an input node feature :math:`X` into :math:`C` groups
  :math:`X_1, X_2, \cdots, X_C` across the channel dimension. Besides, it makes
  :math:`C` copies of the input GNN module :math:`f_{w1}, \cdots, f_{wC}`. In the
  forward pass, each GNN module only takes the corresponding group of node features.
  
  The output node representations :math:`X^{'}` are computed as follows.
  
  .. math::
  
      X_0^{'} = \sum_{i=2}^{C}X_i
  
      X_i^{'} = f_{wi}(X_{i-1}^{'}, g, U) + X_i, i\in\{1,\cdots,C\}
  
      X^{'} = X_1^{'} \, \Vert \, \ldots \, \Vert \, X_C^{'}
  
  where :math:`g` is the input graph, :math:`U` is arbitrary additional input arguments like
  edge features, and :math:`\, \Vert \,` is concatenation.
  
  Parameters
  ----------
  gnn_module : nn.Module
      GNN module for message passing. :attr:`GroupRevRes` will clone the module for
      :attr:`groups`-1 number of times, yielding :attr:`groups` copies in total.
      The input and output node representation size need to be the same. Its forward
      function needs to take a DGLGraph and the associated input node features in order,
      optionally followed by additional arguments like edge features.
  groups : int, optional
      The number of groups.
  
  Examples
  --------
  
  >>> import dgl
  >>> import torch
  >>> import torch.nn as nn
  >>> from dgl.nn import GraphConv, GroupRevRes
  
  >>> class GNNLayer(nn.Module):
  ...     def __init__(self, feats, dropout=0.2):
  ...         super(GNNLayer, self).__init__()
  ...         # Use BatchNorm and dropout to prevent gradient vanishing
  ...         # In particular if you use a large number of GNN layers
  ...         self.norm = nn.BatchNorm1d(feats)
  ...         self.conv = GraphConv(feats, feats)
  ...         self.dropout = nn.Dropout(dropout)
  ...
  ...     def forward(self, g, x):
  ...         x = self.norm(x)
  ...         x = self.dropout(x)
  ...         return self.conv(g, x)
  
  >>> num_nodes = 5
  >>> num_edges = 20
  >>> feats = 32
  >>> groups = 2
  >>> g = dgl.rand_graph(num_nodes, num_edges)
  >>> x = torch.randn(num_nodes, feats)
  >>> conv = GNNLayer(feats // groups)
  >>> model = GroupRevRes(conv, groups)
  >>> out = model(g, x)
code: def _forward(self, g, x, *args):
      xs = torch.chunk(x, self.groups, dim=-1)
  
      if len(args) == 0:
          args_chunks = [()] * self.groups
      else:
          chunked_args = list(
              map(
                  lambda arg: torch.chunk(arg, self.groups, dim=-1),
                  args,
              )
          )
          args_chunks = list(zip(*chunked_args))
      y_in = sum(xs[1:])
  
      ys = []
      for i in range(self.groups):
          y_in = xs[i] + self.gnn_modules[i](g, y_in, *args_chunks[i])
          ys.append(y_in)
  
      out = torch.cat(ys, dim=-1)
  
      return out
  
file_path: dgl/python/dgl/nn/pytorch/conv/grouprevres.py
imports: from copy import deepcopy
  import numpy
  import torch
  import torch.nn
label_desc: Use image node_id 2 for calling the GroupRevRes obj's underlying member method code with example usage: obj._forward(g, x) and returns: out