docstr: Inference with the GAT model on full neighbors (i.e. without neighbor sampling).
  g : the entire graph.
  x : the input of entire node set.
  The inference code is written in a fashion that it could handle any number of nodes and
  layers.
docstr_tok: ["Inference","with","the","GAT","model","on","full","neighbors","(","i.e",".","without","neighbor","sampling",")",".","g",":","the","entire","graph",".","x",":","the","input","of","entire","node","set",".","The","inference","code","is","written","in","a","fashion","that","it","could","handle","any","number","of","nodes","and","layers","."]
code: def inference(self, g, x, num_heads, device):
      """
      Inference with the GAT model on full neighbors (i.e. without neighbor sampling).
      g : the entire graph.
      x : the input of entire node set.
      The inference code is written in a fashion that it could handle any number of nodes and
      layers.
      """
      # During inference with sampling, multi-layer blocks are very inefficient because
      # lots of computations in the first few layers are repeated.
      # Therefore, we compute the representation of all nodes layer by layer.  The nodes
      # on each layer are of course splitted in batches.
      # TODO: can we standardize this?
      for l, layer in enumerate(self.layers):
          if l < self.n_layers - 1:
              y = th.zeros(
                  g.num_nodes(),
                  self.n_hidden * num_heads
                  if l != len(self.layers) - 1
                  else self.n_classes,
              )
          else:
              y = th.zeros(
                  g.num_nodes(),
                  self.n_hidden
                  if l != len(self.layers) - 1
                  else self.n_classes,
              )
  
          sampler = dgl.dataloading.MultiLayerFullNeighborSampler(1)
          dataloader = dgl.dataloading.DataLoader(
              g,
              th.arange(g.num_nodes()),
              sampler,
              batch_size=args.batch_size,
              shuffle=True,
              drop_last=False,
              num_workers=args.num_workers,
          )
  
          for input_nodes, output_nodes, blocks in tqdm.tqdm(
              dataloader
          ):
              block = blocks[0].int().to(device)
  
              h = x[input_nodes].to(device)
              h_dst = h[: block.num_dst_nodes()]
              if l < self.n_layers - 1:
                  h = layer(block, (h, h_dst)).flatten(1)
              else:
                  h = layer(block, (h, h_dst))
                  h = h.mean(1)
                  h = h.log_softmax(dim=-1)
  
              y[output_nodes] = h.cpu()
  
          x = y
      return y.to(device)
  
file_path: dgl/examples/pytorch/ogb/ogbn-products/gat/main.py
imports: import argparse
  import time
  import dgl
  import dgl.nn.pytorch
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  import torch.optim
  import tqdm
  from ogb.nodeproppred import DglNodePropPredDataset
label_desc: Use image node_id 3 for calling the GAT obj's underlying member method code with example usage: obj.inference(g, x, num_heads, device) and returns: y