code: def forward(self, g, feat_dict):
      funcs = {}
      for srctype, etype, dsttype in g.canonical_etypes:
          g.nodes[dsttype].data["h"] = feat_dict[
              dsttype
          ]  # nodes' original feature
          g.nodes[srctype].data["h"] = feat_dict[srctype]
          g.nodes[srctype].data["t_h"] = self.W_T[etype](
              feat_dict[srctype]
          )  # src nodes' transformed feature
  
          # compute the attention numerator (exp)
          g.apply_edges(fn.u_mul_v("t_h", "h", "x"), etype=etype)
          g.edges[etype].data["x"] = torch.exp(
              self.W_A[etype](g.edges[etype].data["x"])
          )
  
          # first update to compute the attention denominator (\sum exp)
          funcs[etype] = (fn.copy_e("x", "m"), fn.sum("m", "att"))
      g.multi_update_all(funcs, "sum")
  
      funcs = {}
      for srctype, etype, dsttype in g.canonical_etypes:
          g.apply_edges(
              fn.e_div_v("x", "att", "att"), etype=etype
          )  # compute attention weights (numerator/denominator)
          funcs[etype] = (
              fn.u_mul_e("h", "att", "m"),
              fn.sum("m", "h"),
          )  # \sum(h0*att) -> h1
      # second update to obtain h1
      g.multi_update_all(funcs, "sum")
  
      # apply activation, layernorm, and dropout
      feat_dict = {}
      for ntype in g.ntypes:
          feat_dict[ntype] = self.dropout(
              self.layernorm(F.relu_(g.nodes[ntype].data["h"]))
          )  # apply activation, layernorm, and dropout
  
      return feat_dict
  
imports: import dgl
  import dgl.function
  import torch
  import torch.nn
  import torch.nn.functional
  from dgl.nn.pytorch import GATConv
label_desc: Use image node_id 2 for calling the RelationalAGG obj's underlying member method code with example usage: obj.forward(g, feat_dict) and returns: feat_dict