code: def main(args):
      # acm data
      if args["dataset"] == "ACMRaw":
          from utils import load_data
  
          (
              g,
              features,
              labels,
              n_classes,
              train_nid,
              val_nid,
              test_nid,
              train_mask,
              val_mask,
              test_mask,
          ) = load_data("ACMRaw")
          metapath_list = [["pa", "ap"], ["pf", "fp"]]
      else:
          raise NotImplementedError(
              "Unsupported dataset {}".format(args["dataset"])
          )
  
      # Is it need to set different neighbors numbers for different meta-path based graph?
      num_neighbors = args["num_neighbors"]
      han_sampler = HANSampler(g, metapath_list, num_neighbors)
      # Create PyTorch DataLoader for constructing blocks
      dataloader = DataLoader(
          dataset=train_nid,
          batch_size=args["batch_size"],
          collate_fn=han_sampler.sample_blocks,
          shuffle=True,
          drop_last=False,
          num_workers=4,
      )
  
      model = HAN(
          num_metapath=len(metapath_list),
          in_size=features.shape[1],
          hidden_size=args["hidden_units"],
          out_size=n_classes,
          num_heads=args["num_heads"],
          dropout=args["dropout"],
      ).to(args["device"])
  
      total_params = sum(p.numel() for p in model.parameters())
      print("total_params: {:d}".format(total_params))
      total_trainable_params = sum(
          p.numel() for p in model.parameters() if p.requires_grad
      )
      print(
          "total trainable params: {:d}".format(total_trainable_params)
      )
  
      stopper = EarlyStopping(patience=args["patience"])
      loss_fn = torch.nn.CrossEntropyLoss()
      optimizer = torch.optim.Adam(
          model.parameters(),
          lr=args["lr"],
          weight_decay=args["weight_decay"],
      )
  
      for epoch in range(args["num_epochs"]):
          model.train()
          for step, (seeds, blocks) in enumerate(dataloader):
              h_list = load_subtensors(blocks, features)
              blocks = [block.to(args["device"]) for block in blocks]
              hs = [h.to(args["device"]) for h in h_list]
  
              logits = model(blocks, hs)
              loss = loss_fn(
                  logits,
                  labels[numpy.asarray(seeds)].to(args["device"]),
              )
  
              optimizer.zero_grad()
              loss.backward()
              optimizer.step()
  
              # print info in each batch
              train_acc, train_micro_f1, train_macro_f1 = score(
                  logits, labels[numpy.asarray(seeds)]
              )
              print(
                  "Epoch {:d} | loss: {:.4f} | train_acc: {:.4f} | train_micro_f1: {:.4f} | train_macro_f1: {:.4f}".format(
                      epoch + 1,
                      loss,
                      train_acc,
                      train_micro_f1,
                      train_macro_f1,
                  )
              )
          val_loss, val_acc, val_micro_f1, val_macro_f1 = evaluate(
              model,
              g,
              metapath_list,
              num_neighbors,
              features,
              labels,
              val_nid,
              loss_fn,
              args["batch_size"],
          )
          early_stop = stopper.step(
              val_loss.data.item(), val_acc, model
          )
  
          print(
              "Epoch {:d} | Val loss {:.4f} | Val Accuracy {:.4f} | Val Micro f1 {:.4f} | Val Macro f1 {:.4f}".format(
                  epoch + 1,
                  val_loss.item(),
                  val_acc,
                  val_micro_f1,
                  val_macro_f1,
              )
          )
  
          if early_stop:
              break
  
      stopper.load_checkpoint(model)
      test_loss, test_acc, test_micro_f1, test_macro_f1 = evaluate(
          model,
          g,
          metapath_list,
          num_neighbors,
          features,
          labels,
          test_nid,
          loss_fn,
          args["batch_size"],
      )
      print(
          "Test loss {:.4f} | Test Accuracy {:.4f} | Test Micro f1 {:.4f} | Test Macro f1 {:.4f}".format(
              test_loss.item(), test_acc, test_micro_f1, test_macro_f1
          )
      )
  
imports: import argparse
  import dgl
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  from dgl.nn.pytorch import GATConv
  from dgl.sampling import RandomWalkNeighborSampler
  from model_hetero import SemanticAttention
  from sklearn.metrics import f1_score
  from torch.utils.data import DataLoader
  from utils import EarlyStopping, set_random_seed
label_desc: Use image node_id 4 for calling a global function with example usage: main(args) without return types