class_docstr: Encoder based on dgl.nn.GINConv &  dgl.nn.SumPooling
  Parameters
  -----------
  in_dim: int
      Input feature size.
  hid_dim: int
      Hidden feature size.
  n_layer:
      Number of GIN layers.
  
  Functions
  -----------
  forward(graph, feat):
      graph: DGLGraph
      feat: Tensor
          [N * D], node features
code: def __init__(self, in_dim, hid_dim, n_layer):
      super(GINEncoder, self).__init__()
  
      self.n_layer = n_layer
  
      self.convs = ModuleList()
      self.bns = ModuleList()
  
      for i in range(n_layer):
          if i == 0:
              n_in = in_dim
          else:
              n_in = hid_dim
          n_out = hid_dim
          block = Sequential(
              Linear(n_in, n_out), ReLU(), Linear(hid_dim, hid_dim)
          )
  
          conv = GINConv(apply_func=block, aggregator_type="sum")
          bn = BatchNorm1d(hid_dim)
  
          self.convs.append(conv)
          self.bns.append(bn)
  
      # sum pooling
      self.pool = SumPooling()
  
imports: import torch
  import torch.nn
  import torch.nn.functional
  from dgl.nn import GINConv, NNConv, Set2Set
  from dgl.nn.pytorch.glob import SumPooling
  from torch.nn import BatchNorm1d, GRU, Linear, ModuleList, ReLU, Sequential
  from utils import global_global_loss_, local_global_loss_
label_desc: Use image node_id 1 to create a new GINEncoder object from inherited base classes: nn with example: obj = GINEncoder(in_dim, hid_dim, n_layer)