class_docstr: A wrapped :class:`torch.nn.Module` class for the convinient instantiation of 
  pre-implemented graph encoders.
  
  Args:
      feat_dim (int): The dimension of input node features.
      hidden_dim (int): The dimension of node-level (local) embeddings. 
      n_layer (int, optional): The number of GNN layers in the encoder. (default: :obj:`5`)
      pool (string, optional): The global pooling methods, :obj:`sum` or :obj:`mean`.
          (default: :obj:`sum`)
      gnn (string, optional): The type of GNN layer, :obj:`gcn`, :obj:`gin` or 
          :obj:`resgcn`. (default: :obj:`gin`)
      bn (bool, optional): Whether to include batch normalization. (default: :obj:`True`)
      act (string, optional): The activation function, :obj:`relu` or :obj:`prelu`.
          (default: :obj:`relu`)
      bias (bool, optional): Whether to include bias term in Linear. (default: :obj:`True`)
      xavier (bool, optional): Whether to apply xavier initialization. (default: :obj:`True`)
      node_level (bool, optional): If :obj:`True`, the encoder will output node level
          embedding (local representations). (default: :obj:`False`)
      graph_level (bool, optional): If :obj:`True`, the encoder will output graph level
          embeddings (global representations). (default: :obj:`True`)
      edge_weight (bool, optional): Only applied to GCN. Whether to use edge weight to
          compute the aggregation. (default: :obj:`False`)
          
  Note
  ----
  For GCN and GIN encoders, the dimension of the output node-level (local) embedding will be 
  :obj:`hidden_dim`, whereas the node-level embedding will be :obj:`hidden_dim` * :obj:`n_layers`. 
  For ResGCN, the output embeddings for boths node and graphs will have dimensions :obj:`hidden_dim`.
          
  Examples
  --------
  >>> feat_dim = dataset[0].x.shape[1]
  >>> encoder = Encoder(feat_dim, 128, n_layer=3, gnn="gin")
  >>> encoder(some_batched_data).shape # graph-level embedding of shape [batch_size, 128*3]
  torch.Size([32, 384]) 
  
  >>> encoder = Encoder(feat_dim, 128, n_layer=5, node_level=True, graph_level=False)
  >>> encoder(some_batched_data).shape # node-level embedding of shape [n_nodes, 128]
  torch.Size([707, 128]) 
  
  >>> encoder = Encoder(feat_dim, 128, n_layer=5, node_level=True, graph_level=False)
  >>> encoder(some_batched_data) # a tuple of graph-level and node-level embeddings
  (tensor([...]), tensor([...])) 
code: def __init__(
      self,
      feat_dim,
      hidden_dim,
      n_layers=5,
      pool="sum",
      gnn="gin",
      node_level=False,
      graph_level=True,
      **kwargs,
  ):
      super(Encoder, self).__init__()
  
      if gnn == "gin":
          self.encoder = GIN(
              feat_dim, hidden_dim, n_layers, pool, **kwargs
          )
      elif gnn == "gcn":
          self.encoder = GCN(
              feat_dim, hidden_dim, n_layers, pool, **kwargs
          )
      elif gnn == "resgcn":
          self.encoder = ResGCN(
              feat_dim,
              hidden_dim,
              num_conv_layers=n_layers,
              global_pool=pool,
          )
  
      self.node_level = node_level
      self.graph_level = graph_level
  
imports: from functools import partial
  import torch
  import torch.nn.functional
  from torch.nn import Parameter
  from torch.nn import Sequential, Linear, BatchNorm1d
  from torch_scatter import scatter_add
  from torch_geometric.nn import GINConv, GCNConv, global_add_pool, global_mean_pool
  from torch_geometric.nn.conv import MessagePassing
  from torch_geometric.utils import remove_self_loops, add_self_loops
  from torch_geometric.nn.inits import glorot, zeros
label_desc: Use image node_id 1 to create a new Encoder object from inherited base classes: torch.nn with example: obj = Encoder(feat_dim, hidden_dim, n_layers, pool, gnn, node_level, graph_level)