class_docstr: Multi-layered `Gated Graph Sequence Neural Networks
  <https://arxiv.org/pdf/1511.05493.pdf>`__.
  Support both undirected (i.e., regular) and bidirectional
  (i.e., `bi_sep` and `bi_fuse`) versions.
  Attributes
  ----------
  num_layers: int
      Number of GGNN layers.
  input_size: int
      Input feature size.
  hidden_size: int
      Should be equal to output_size.
  output_size: int
      Output feature size.
  direction_option: str
      The direction option of GGNN ('undirected', 'bi_sep' or 'bi_fuse').
      (Default: 'bi_fuse')
  n_etypes: int
      Number of edge types. n_etypes can be set to any integer if the
      direction_option is 'undirected'.
      If the direction_option is 'bi_sep' or 'bi_fuse', n_etypes will be set to 1.
  bias: bool
      If True, adds a learnable bias to the output. (Default: True)
docstr: Use GGNN compute node embeddings.
  Parameters
  ----------
  graph: GraphData.
      The initial node features are stored in the node feature field
      named `node_feat`.
  Returns
  -------
  input_graph: GraphData.
      The computed node embedding tensors are stored in the node feature field
      named `node_emb`.
docstr_tok: ["Use","GGNN","compute","node","embeddings",".","Parameters","--","--","--","--","--","graph",":","GraphData",".","The","initial","node","features","are","stored","in","the","node","feature","field","named","`","node_feat","`",".","Returns","--","--","--","-","input_graph",":","GraphData",".","The","computed","node","embedding","tensors","are","stored","in","the","node","feature","field","named","`","node_emb","`","."]
code: def forward(self, graph: GraphData):
      r"""
      Use GGNN compute node embeddings.
      Parameters
      ----------
      graph: GraphData.
          The initial node features are stored in the node feature field
          named `node_feat`.
      Returns
      -------
      input_graph: GraphData.
          The computed node embedding tensors are stored in the node feature field
          named `node_emb`.
      """
      if self.n_etypes == 1:
          graph.edge_features["etype"] = torch.tensor(
              [0] * graph.get_edge_num(),
              dtype=torch.long,
              device=graph.device,
          )
  
      node_feats = graph.node_features["node_feat"]
      etypes = graph.edge_features["etype"]
      if self.use_edge_weight:
          edge_weight = graph.edge_features["edge_weight"]
          if (
              self.direction_option == "bi_fuse"
              or self.direction_option == "bi_sep"
          ):
              reverse_edge_weight = graph.edge_features[
                  "reverse_edge_weight"
              ]
              edge_weight = (edge_weight, reverse_edge_weight)
      else:
          edge_weight = None
  
      dgl_graph = graph.to_dgl()
  
      if self.direction_option == "undirected":
          node_embs = self.models(
              dgl_graph, node_feats, etypes, edge_weight
          )
      else:
          assert node_feats.shape[1] == self.input_size
  
          zero_pad = node_feats.new_zeros(
              (
                  node_feats.shape[0],
                  self.output_size - node_feats.shape[1],
              )
          )
          node_feats = torch.cat([node_feats, zero_pad], -1)
  
          feat_in = node_feats
          feat_out = node_feats
  
          for _ in range(self.num_layers):
              feat_in = self.feat_drop(feat_in)
              feat_out = self.feat_drop(feat_out)
              h = self.models(
                  dgl_graph, (feat_in, feat_out), etypes, edge_weight
              )
              feat_in = h[0]
              feat_out = h[1]
  
          if self.direction_option == "bi_sep":
              node_embs = torch.cat([feat_in, feat_out], dim=-1)
          elif self.direction_option == "bi_fuse":
              node_embs = feat_in
          else:
              raise RuntimeError(
                  "Unknown `bidirection` value: {}".format(
                      self.direction_option
                  )
              )
  
      graph.node_features["node_emb"] = node_embs
  
      return graph
  
imports: import dgl
  import dgl.function
  import torch
  import torch.nn
  from torch.nn import init
  from ...data.data import GraphData
  from .base import GNNBase, GNNLayerBase
label_desc: Use image node_id 2 for calling the GGNN obj's underlying member method code with example usage: obj.forward(graph) and returns: graph