class_docstr: AutoHeterGNN
class_docstr_tok: ["AutoHeterGNN"]
docstr: Forward for auto heter gnn
          
docstr_tok: ["Forward","for","auto","heter","gnn"]
code: def forward(self, graph_holders, init_feature, degree_norm=None):
      """Forward for auto heter gnn"""
      # pad a zeros to prevent empty graph happen
      zeros_tensor1 = paddle.zeros([1, init_feature.shape[-1]])
      zeros_tensor2 = paddle.zeros([1, 1], dtype="int64")
      init_feature = paddle.concat([zeros_tensor1, init_feature])
      feature = init_feature
      self.hcl_buffer.append(feature)
  
      if degree_norm is not None:
          degree_norm = degree_norm.reshape([self.etype_len, -1]).T
          degree_norm = paddle.sum(degree_norm, -1)
          degree_norm = model_util.get_degree_norm(degree_norm)
          degree_norm = paddle.concat(
              [paddle.ones([1, 1], dtype="float32"), degree_norm],
              axis=0,
          )
  
      for i in range(self.num_layers):
          graph_holder = graph_holders[self.num_layers - i - 1]
          num_nodes = graph_holder[0] + 1
          next_num_nodes = graph_holder[1] + 1
          edges_src = graph_holder[2] + 1
          edges_dst = graph_holder[3] + 1
          split_edges = graph_holder[4]
  
          # if self.return_weight:
          #     edges_weight = graph_holder[5]
  
          nxt_fs = []
          feature = self.shared_sub_pre_layer[i](feature, degree_norm)
          self.hcl_buffer.append(feature)
  
          for j in range(self.etype_len):
              start = (
                  paddle.zeros([1], dtype="int64")
                  if j == 0
                  else split_edges[j - 1]
              )
              new_edges_src = paddle.concat(
                  [zeros_tensor2, edges_src[start : split_edges[j]]]
              )
              new_edges_dst = paddle.concat(
                  [zeros_tensor2, edges_dst[start : split_edges[j]]]
              )
              graph = pgl.Graph(
                  num_nodes=num_nodes,
                  edges=paddle.concat(
                      [new_edges_src, new_edges_dst], axis=1
                  ),
              )
  
              # generate feature of single relation
              nxt_f = self.rgnn_dict[(i, j)](
                  graph, feature, next_num_nodes, degree_norm
              )
              nxt_fs.append(nxt_f)
          # feature intergation
          feature = self.rgnn_dict[(i, self.etype_len)](nxt_fs)
  
          # heter graph residual
          feature = init_feature[
              :next_num_nodes
          ] * self.alpha_residual + feature * (1 - self.alpha_residual)
          if degree_norm is not None:
              degree_norm = degree_norm[:next_num_nodes]
      # remove first zeros to prevent empty graph happen
      return feature[1:]
  
file_path: PGL/apps/PGLBox/src/models/auto_heter_gnn.py
imports: import paddle
  import paddle.nn
  import paddle.nn.functional
  from collections import OrderedDict
  import paddle.static
  import pgl
  from .None import model_util
  from .None import layers
label_desc: Use image node_id 2 for calling the AutoHeterGNN obj's underlying member method code with example usage: obj.forward(graph_holders, init_feature, degree_norm) and returns: feature