code: import sys,os
  sys.path.append(os.getcwd())
  # from Process.process import *
  from Process.process import *
  import torch as th
  from torch_scatter import scatter_mean
  import torch.nn.functional as F
  import numpy as np
  from tools.earlystopping import EarlyStopping
  from torch_geometric.data import DataLoader
  from tqdm import tqdm
  from Process.rand5fold import *
  from tools.evaluate import *
  from torch_geometric.nn import GCNConv
  import copy
  
  
  class TDRumorGCN(th.nn.Module):
      def __init__(self, in_feats, hid_feats, out_feats):
          super(TDRumorGCN, self).__init__()
          self.conv1 = GCNConv(in_feats, hid_feats)
          # self.conv2 = GCNConv(hid_feats+in_feats, out_feats)
          self.conv2 = GCNConv(hid_feats, out_feats)
  
      def forward(self, data):
          x, edge_index = data.x, data.edge_index
  
          # print("==========================")
          # print(x.shape, edge_index.shape)
          # print("==========================")
          """
          x1 = copy.copy(x.float())
          x = self.conv1(x, edge_index)
          x2 = copy.copy(x)
          # TODO: root feature concat
          rootindex = data.rootindex
          root_extend = th.zeros(len(data.batch), x1.size(1)).to(device)
          batch_size = max(data.batch) + 1
          for num_batch in range(batch_size):
              index = (th.eq(data.batch, num_batch))
              root_extend[index] = x1[rootindex[num_batch]]
          x = th.cat((x, root_extend), 1)
  
          x = F.relu(x)
          x = F.dropout(x, training=self.training)
          x = self.conv2(x, edge_index)
          x = F.relu(x)
          root_extend = th.zeros(len(data.batch), x2.size(1)).to(device)
          for num_batch in range(batch_size):
              index = (th.eq(data.batch, num_batch))
              root_extend[index] = x2[rootindex[num_batch]]
          x = th.cat((x, root_extend), 1)
          x = scatter_mean(x, data.batch, dim=0)
          """
  
          x, edge_index = data.x, data.BU_edge_index
  
          # print("TEST")
          # print(x.shape, edge_index.shape)
  
          x = self.conv1(x, edge_index)
          # print("after conv1:", x.shape)
  
          x = F.relu(x)
          x = F.dropout(x, training=self.training)
          x = self.conv2(x, edge_index)
          # print("after conv2:", x.shape)
  
          # exit()
  
          x = F.relu(x)
          x = scatter_mean(x, data.batch, dim=0)
  
          return x
  
  
  class BURumorGCN(th.nn.Module):
      def __init__(self, in_feats, hid_feats, out_feats):
          super(BURumorGCN, self).__init__()
          self.conv1 = GCNConv(in_feats, hid_feats)
          # self.conv2 = GCNConv(hid_feats+in_feats, out_feats)
          self.conv2 = GCNConv(hid_feats, out_feats)
  
      def forward(self, data):
  
          # print("---------------------------------------")
          # print(data.x.shape, data.BU_edge_index.shape)
          # print("---------------------------------------")
  
  
          """
          x, edge_index = data.x, data.BU_edge_index
          x1 = copy.copy(x.float())
          x = self.conv1(x, edge_index)
          x2 = copy.copy(x)
  
          rootindex = data.rootindex
          root_extend = th.zeros(len(data.batch), x1.size(1)).to(device)
          batch_size = max(data.batch) + 1
          for num_batch in range(batch_size):
              index = (th.eq(data.batch, num_batch))
              root_extend[index] = x1[rootindex[num_batch]]
          x = th.cat((x, root_extend), 1)
  
          x = F.relu(x)
          x = F.dropout(x, training=self.training)
          x = self.conv2(x, edge_index)
          x = F.relu(x)
          root_extend = th.zeros(len(data.batch), x2.size(1)).to(device)
          for num_batch in range(batch_size):
              index = (th.eq(data.batch, num_batch))
              root_extend[index] = x2[rootindex[num_batch]]
          x = th.cat((x, root_extend), 1)
  
          x = scatter_mean(x, data.batch, dim=0)
          """
  
          x, edge_index = data.x, data.BU_edge_index
  
          x1 = copy.copy(x.float())
          rootindex = data.rootindex
          root_extend = th.zeros(len(data.batch), x1.size(1)).to(device)
          batch_size = max(data.batch) + 1
          for num_batch in range(batch_size):
              index = (th.eq(data.batch, num_batch))
              root_extend[index] = x1[rootindex[num_batch]]
          # x = th.cat((x, root_extend), 1)
  
  
          x = self.conv1(x, edge_index)
          x = F.relu(x)
          x = F.dropout(x, training=self.training)
          x = self.conv2(x, edge_index)
          x = F.relu(x)
          # x = scatter_mean(x, data.batch, dim=0)
          # print(x.shape, root_extend.shape)
  
          # HERE
          # x = th.cat((x, root_extend), 1)
          x = scatter_mean(x, data.batch, dim=0)  # GCN - mean
  
  
          root_extend = scatter_mean(root_extend, data.batch, dim=0)
          # print(x.shape, root_extend.shape)
  
          return x, root_extend
  
  
  class Net(th.nn.Module):
      def __init__(self, in_feats, hid_feats, out_feats):  # 5000, 64, 64
          super(Net, self).__init__()
          self.TDRumorGCN = TDRumorGCN(in_feats, hid_feats, out_feats)
          self.BURumorGCN = BURumorGCN(in_feats, hid_feats, out_feats)
  
  
          print("Out / hidden:", out_feats, hid_feats)
  
          # self.multihead_attn = th.nn.MultiheadAttention(hid_feats, 6)
  
  
          # TODO: Attention layer
          # self.fc1 = th.nn.Linear((out_feats+hid_feats)*2 * 5, 64)
  
          self.W_s1 = th.nn.Linear(out_feats * 2, 128)
          self.W_s2 = th.nn.Linear(128, 128)
  
  
          # self.multihead_attn = th.nn.MultiheadAttention(65, 5)
  
          # self.fc1 = th.nn.Linear((out_feats + hid_feats)*2 * 5, 64)
          self.fc1 = th.nn.Linear((out_feats) *2 * 5 + in_feats, 64)
          # self.fc1 = th.nn.Linear((out_feats) *2 * 10 + in_feats, 64)
  
  
          # self.relu = th.nn.ReLU()
          self.relu = th.nn.LeakyReLU()
          self.fc2 = th.nn.Linear(64, 4)
  
  
  
      def attention_net(self, snapshot_output):
          # B * D
          """
          https://github.com/prakashpandey9/Text-Classification-Pytorch/blob/master/models/selfAttention.py
          """
          attn_weight_matrix = self.W_s2(th.tanh(self.W_s1(snapshot_output)))
          print("here1", attn_weight_matrix.shape)
  
          # attn_weight_matrix = attn_weight_matrix.unsqueeze(1) # 128 1 64 --> 128 1 64
          print("here2", attn_weight_matrix.shape)
  
          # ttn_weight_matrix = attn_weight_matrix.permute(0, 2, 1)
          # ttn_weight_matrix = attn_weight_matrix.permute(1, 0, 2)
          print("here3", attn_weight_matrix.shape)
  
          attn_weight_matrix = F.softmax(attn_weight_matrix, dim=0)  # TODO
  
          attn_weight_matrix = attn_weight_matrix.unsqueeze(1) # 128 64*2 --> 128 64 1
          print("there4", attn_weight_matrix.shape)
  
          return attn_weight_matrix
  
  
      # def forward(self, data):
      def forward(self, s0, s1, s2, s3, s4):
      # def forward(self, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9):
  
          # TODO: data to temporal adjacency network, fix
  
          TD_x0 = self.TDRumorGCN(s0)
          BU_x0, _ = self.BURumorGCN(s0)
          TD_x1 = self.TDRumorGCN(s1)
          BU_x1, _ = self.BURumorGCN(s1)
          TD_x2 = self.TDRumorGCN(s2)
          BU_x2, _ = self.BURumorGCN(s2)
          TD_x3 = self.TDRumorGCN(s3)
          BU_x3, _ = self.BURumorGCN(s3)
          TD_x4 = self.TDRumorGCN(s4)
          BU_x4, root_extend = self.BURumorGCN(s4)
  
          # TD_x5 = self.TDRumorGCN(s5)
          # BU_x5, _ = self.BURumorGCN(s5)
          # TD_x6 = self.TDRumorGCN(s6)
          # BU_x6, _ = self.BURumorGCN(s6)
          # TD_x7 = self.TDRumorGCN(s7)
          # BU_x7, _ = self.BURumorGCN(s7)
          # TD_x8 = self.TDRumorGCN(s8)
          # BU_x8, _ = self.BURumorGCN(s8)
          # TD_x9 = self.TDRumorGCN(s9)
          # BU_x9, _ = self.BURumorGCN(s9)
  
  
          # x = th.cat((BU_x, TD_x), 1)
          # x = th.cat((BU_x0, TD_x0, BU_x1, TD_x1, BU_x2, TD_x2, BU_x3, TD_x3, BU_x4, TD_x4), 1)
  
          """
          # TD_x0 = TD_x0.permute(1, 0)
          print(TD_x0.shape)
          attn_weight_matrix = self.attention_net(TD_x0)
          print("attn", attn_weight_matrix.shape)
          print("TD", TD_x0.shape)
  
  
          TD_x0_coeff = th.matmul(attn_weight_matrix, TD_x0.unsqueeze(2))  # (B x 1 x 64) * (B x 64 x 1)
          # TD_x0 = th.bmm(attn_weight_matrix, TD_x0)  # TODO: https://gaussian37.github.io/dl-pytorch-pytorch-tensor-basic/
          # TD_x0 = th.bmm(TD_x0, attn_weight_matrix)  # TODO: https://gaussian37.github.io/dl-pytorch-pytorch-tensor-basic/
          print("TD_x0_coeff", TD_x0_coeff.shape)  # B x 1 x 1
  
          # HERE TODO: JIHO
  
  
          TD_x0 = th.bmm(TD_x0_coeff, TD_x0.unsqueeze(1))
          print("TD HEREHERE1", TD_x0.shape)
          TD_x0 = TD_x0.view(-1, 64)
          print("TD HEREHERE2", TD_x0.shape)
          """
  
          x0 = th.cat((BU_x0, TD_x0), 1)
          x1 = th.cat((BU_x1, TD_x1), 1)
          x2 = th.cat((BU_x2, TD_x2), 1)
          x3 = th.cat((BU_x3, TD_x3), 1)
          x4 = th.cat((BU_x4, TD_x4), 1)
  
          attn_weight_matrix = self.attention_net(x0)
          x0_coeff = th.matmul(attn_weight_matrix, x0.unsqueeze(2))  # (B x 1 x 64) * (B x 64 x 1)
          x0 = th.bmm(x0_coeff, x0.unsqueeze(1)).view(-1, 128)
  
          attn_weight_matrix = self.attention_net(x1)
          x1_coeff = th.matmul(attn_weight_matrix, x1.unsqueeze(2))  # (B x 1 x 64) * (B x 64 x 1)
          x1 = th.bmm(x1_coeff, x1.unsqueeze(1)).view(-1, 128)
          attn_weight_matrix = self.attention_net(x2)
          x2_coeff = th.matmul(attn_weight_matrix, x2.unsqueeze(2))  # (B x 1 x 64) * (B x 64 x 1)
          x2 = th.bmm(x2_coeff, x2.unsqueeze(1)).view(-1, 128)
          attn_weight_matrix = self.attention_net(x3)
          x3_coeff = th.matmul(attn_weight_matrix, x3.unsqueeze(2))  # (B x 1 x 64) * (B x 64 x 1)
          x3 = th.bmm(x3_coeff, x3.unsqueeze(1)).view(-1, 128)
          attn_weight_matrix = self.attention_net(x4)
          x4_coeff = th.matmul(attn_weight_matrix, x4.unsqueeze(2))  # (B x 1 x 64) * (B x 64 x 1)
          x4 = th.bmm(x4_coeff, x4.unsqueeze(1)).view(-1, 128)
  
  
  
          # x = th.cat((BU_x0, TD_x0, BU_x1, TD_x1, BU_x2, TD_x2, BU_x3, TD_x3, BU_x4, TD_x4, root_extend), 1)  # ORG
          x = th.cat((x0, x1, x2, x3, x4, root_extend), 1)
  
          # https://github.com/prakashpandey9/Text-Classification-Pytorch/blob/master/models/selfAttention.py
  
  
          # attn_output, attn_output_weights = self.multihead_attn(x, x, x)
          # print(attn_output, attn_output_weights)
          # print(attn_output.shape, attn_output_weights.shape)
          # exit()
  
  
          # x = th.cat((BU_x0, TD_x0, BU_x1, TD_x1, BU_x2, TD_x2, BU_x3, TD_x3, BU_x4, TD_x4,
          #                 BU_x5, TD_x5, BU_x6, TD_x6, BU_x7, TD_x7, BU_x8, TD_x8, BU_x9, TD_x9, root_extend), 1)
  
          # TODO: attention
          # x = self.multihead_attn(x, x, x)
  
  
          # print(x.shape)
          x = self.fc1(x)
          x = self.relu(x)
          x = self.fc2(x)
          x = F.log_softmax(x, dim=1)
          return x
  
  
  def train_GCN(treeDic, x_test, x_train, TDdroprate, BUdroprate, lr, weight_decay, patience, n_epochs, batchsize, dataname, iter):
      model = Net(5000, 64, 64).to(device)
      BU_params = list(map(id, model.BURumorGCN.conv1.parameters()))
      BU_params += list(map(id, model.BURumorGCN.conv2.parameters()))
      base_params = filter(lambda p: id(p) not in BU_params, model.parameters())
      optimizer = th.optim.Adam([
          {'params': base_params},
          {'params': model.BURumorGCN.conv1.parameters(), 'lr': lr/5},
          {'params': model.BURumorGCN.conv2.parameters(), 'lr': lr/5}
      ], lr=lr, weight_decay=weight_decay)
      model.train()
      train_losses = []
      val_losses = []
      train_accs = []
      val_accs = []
      early_stopping = EarlyStopping(patience=patience, verbose=True)
      for epoch in range(n_epochs):
          # traindata_list, testdata_list = loadBiData(dataname, treeDic, x_train, x_test, TDdroprate, BUdroprate)
          traindata_list, testdata_list = loadSnapshotData(dataname, treeDic, x_train, x_test, TDdroprate, BUdroprate)
          train_loader = DataLoader(traindata_list, batch_size=batchsize, shuffle=True, num_workers=5)
          test_loader = DataLoader(testdata_list, batch_size=batchsize, shuffle=True, num_workers=5)
          print("epoch")
  
          # ---------
          # TRAIN
          # ---------
          avg_loss = []
          avg_acc = []
          batch_idx = 0
          # tqdm_train_loader = tqdm(train_loader)  # JIHO
          tqdm_train_loader = train_loader
          for Batch_data in tqdm_train_loader:
  
              # print(Batch_data.shape)
              # Batch_data.to(device)
  
              # print(Batch_data)
              # print(len(Batch_data))
              # print("HERE")
  
              s0 = Batch_data[0].to(device)
              s1 = Batch_data[1].to(device)
              s2 = Batch_data[2].to(device)
              s3 = Batch_data[3].to(device)
              s4 = Batch_data[4].to(device)
  
              # s5 = Batch_data[5].to(device)
              # s6 = Batch_data[6].to(device)
              # s7 = Batch_data[7].to(device)
              # s8 = Batch_data[8].to(device)
              # s9 = Batch_data[9].to(device)
  
  
              # out_labels = model(Batch_data)
              out_labels = model(s0, s1, s2, s3, s4)
              # out_labels = model(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9)
  
              finalloss = F.nll_loss(out_labels, Batch_data[0].y)
              loss = finalloss
              optimizer.zero_grad()
              loss.backward()
              avg_loss.append(loss.item())
              optimizer.step()
              _, pred = out_labels.max(dim=-1)
              # correct = pred.eq(Batch_data.y).sum().item()
              correct = pred.eq(Batch_data[0].y).sum().item()
              train_acc = correct / len(Batch_data[0].y)
              avg_acc.append(train_acc)
              print("Iter {:03d} | Epoch {:05d} | Batch{:02d} | Train_Loss {:.4f}| Train_Accuracy {:.4f}".format(
                  iter, epoch, batch_idx, loss.item(), train_acc))
              batch_idx = batch_idx + 1
  
          train_losses.append(np.mean(avg_loss))
          train_accs.append(np.mean(avg_acc))
  
          # ---------
          # TEST
          # ---------
          temp_val_losses = []
          temp_val_accs = []
          temp_val_Acc_all, temp_val_Acc1, temp_val_Prec1, temp_val_Recll1, temp_val_F1, \
              temp_val_Acc2, temp_val_Prec2, temp_val_Recll2, temp_val_F2, \
              temp_val_Acc3, temp_val_Prec3, temp_val_Recll3, temp_val_F3, \
              temp_val_Acc4, temp_val_Prec4, temp_val_Recll4, temp_val_F4 = [], [
              ], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []
          model.eval()
          # tqdm_test_loader = tqdm(test_loader)  # JIHO
          tqdm_test_loader = test_loader
          for Batch_data in tqdm_test_loader:
              # Batch_data.to(device)
              # val_out = model(Batch_data)
  
              s0 = Batch_data[0].to(device)
              s1 = Batch_data[1].to(device)
              s2 = Batch_data[2].to(device)
              s3 = Batch_data[3].to(device)
              s4 = Batch_data[4].to(device)
  
              # s5 = Batch_data[5].to(device)
              # s6 = Batch_data[6].to(device)
              # s7 = Batch_data[7].to(device)
              # s8 = Batch_data[8].to(device)
              # s9 = Batch_data[9].to(device)
  
              # out_labels = model(Batch_data)
              val_out = model(s0, s1, s2, s3, s4)
              # val_out = model(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9)
  
              val_loss = F.nll_loss(val_out, Batch_data[0].y)
              temp_val_losses.append(val_loss.item())
              _, val_pred = val_out.max(dim=1)
              correct = val_pred.eq(Batch_data[0].y).sum().item()
              val_acc = correct / len(Batch_data[0].y)
              Acc_all, Acc1, Prec1, Recll1, F1, Acc2, Prec2, Recll2, F2, Acc3, Prec3, Recll3, F3, Acc4, Prec4, Recll4, F4 = evaluation4class(
                  val_pred, Batch_data[0].y)
              temp_val_Acc_all.append(Acc_all), temp_val_Acc1.append(Acc1), temp_val_Prec1.append(Prec1), temp_val_Recll1.append(Recll1), temp_val_F1.append(F1), \
                  temp_val_Acc2.append(Acc2), temp_val_Prec2.append(Prec2), temp_val_Recll2.append(Recll2), temp_val_F2.append(F2), \
                  temp_val_Acc3.append(Acc3), temp_val_Prec3.append(Prec3), temp_val_Recll3.append(Recll3), temp_val_F3.append(F3), \
                  temp_val_Acc4.append(Acc4), temp_val_Prec4.append(
                      Prec4), temp_val_Recll4.append(Recll4), temp_val_F4.append(F4)
              temp_val_accs.append(val_acc)
          val_losses.append(np.mean(temp_val_losses))
          val_accs.append(np.mean(temp_val_accs))
          print("Epoch {:05d} | Val_Loss {:.4f}| Val_Accuracy {:.4f}".format(epoch, np.mean(temp_val_losses),
                                                                             np.mean(temp_val_accs)))
  
          res = ['acc:{:.4f}'.format(np.mean(temp_val_Acc_all)),
                 'C1:{:.4f},{:.4f},{:.4f},{:.4f}'.format(np.mean(temp_val_Acc1), np.mean(
                     temp_val_Prec1), np.mean(temp_val_Recll1), np.mean(temp_val_F1)),
                 'C2:{:.4f},{:.4f},{:.4f},{:.4f}'.format(np.mean(temp_val_Acc2), np.mean(
                     temp_val_Prec2), np.mean(temp_val_Recll2), np.mean(temp_val_F2)),
                 'C3:{:.4f},{:.4f},{:.4f},{:.4f}'.format(np.mean(temp_val_Acc3), np.mean(
                     temp_val_Prec3), np.mean(temp_val_Recll3), np.mean(temp_val_F3)),
                 'C4:{:.4f},{:.4f},{:.4f},{:.4f}'.format(np.mean(temp_val_Acc4), np.mean(temp_val_Prec4), np.mean(temp_val_Recll4), np.mean(temp_val_F4))]
          print('results:', res)
          early_stopping(np.mean(temp_val_losses), np.mean(temp_val_accs), np.mean(temp_val_F1), np.mean(
              temp_val_F2), np.mean(temp_val_F3), np.mean(temp_val_F4), model, 'BiGCN', dataname)
          accs = np.mean(temp_val_accs)
          F1 = np.mean(temp_val_F1)
          F2 = np.mean(temp_val_F2)
          F3 = np.mean(temp_val_F3)
          F4 = np.mean(temp_val_F4)
          if early_stopping.early_stop:
              print("Early stopping")
              accs = early_stopping.accs
              F1 = early_stopping.F1
              F2 = early_stopping.F2
              F3 = early_stopping.F3
              F4 = early_stopping.F4
              break
      return train_losses, val_losses, train_accs, val_accs, accs, F1, F2, F3, F4
  
  
  # ====================
  #         MAIN
  # ====================
  
  lr = 0.0005
  weight_decay = 1e-4
  patience = 10
  # n_epochs=200  # JIHO
  n_epochs = 100
  batchsize = 128
  TDdroprate = 0.2
  BUdroprate = 0.2
  datasetname = sys.argv[1]  # "Twitter15"、"Twitter16"
  iterations = int(sys.argv[2])
  model = "GCN"
  device = th.device('cuda:2' if th.cuda.is_available() else 'cpu')
  # device = th.device('cuda:3' if th.cuda.is_available() else 'cpu')
  test_accs = []
  NR_F1 = []
  FR_F1 = []
  TR_F1 = []
  UR_F1 = []
  for iter in range(iterations):
      fold0_x_test, fold0_x_train, fold1_x_test, fold1_x_train, fold2_x_test, \
          fold2_x_train, fold3_x_test, fold3_x_train, fold4_x_test, fold4_x_train = load5foldData(
              datasetname)
  
      treeDic = loadTree(datasetname)
  
      # print(len(treeDic))
      # print(treeDic.keys())
      # print(treeDic['634013216431935488'])
      # print("----------------" * 4)
      # for key in treeDic['634013216431935488']:
      #     print(key, treeDic['634013216431935488'][key])
      # exit()
  
      # five fold cross validation
      train_losses, val_losses, train_accs, val_accs0, accs0, F1_0, F2_0, F3_0, F4_0 = train_GCN(
          treeDic, fold0_x_test, fold0_x_train, TDdroprate, BUdroprate, lr, weight_decay, patience, n_epochs, batchsize, datasetname, iter)
      train_losses, val_losses, train_accs, val_accs1, accs1, F1_1, F2_1, F3_1, F4_1 = train_GCN(
          treeDic, fold1_x_test, fold1_x_train, TDdroprate, BUdroprate, lr, weight_decay, patience, n_epochs, batchsize, datasetname, iter)
      train_losses, val_losses, train_accs, val_accs2, accs2, F1_2, F2_2, F3_2, F4_2 = train_GCN(
          treeDic, fold2_x_test, fold2_x_train, TDdroprate, BUdroprate, lr, weight_decay, patience, n_epochs, batchsize, datasetname, iter)
      train_losses, val_losses, train_accs, val_accs3, accs3, F1_3, F2_3, F3_3, F4_3 = train_GCN(
          treeDic, fold3_x_test, fold3_x_train, TDdroprate, BUdroprate, lr, weight_decay, patience, n_epochs, batchsize, datasetname, iter)
      train_losses, val_losses, train_accs, val_accs4, accs4, F1_4, F2_4, F3_4, F4_4 = train_GCN(
          treeDic, fold4_x_test, fold4_x_train, TDdroprate, BUdroprate, lr, weight_decay, patience, n_epochs, batchsize, datasetname, iter)
      test_accs.append((accs0+accs1+accs2+accs3+accs4)/5)
      NR_F1.append((F1_0+F1_1+F1_2+F1_3+F1_4)/5)
      FR_F1.append((F2_0 + F2_1 + F2_2 + F2_3 + F2_4) / 5)
      TR_F1.append((F3_0 + F3_1 + F3_2 + F3_3 + F3_4) / 5)
      UR_F1.append((F4_0 + F4_1 + F4_2 + F4_3 + F4_4) / 5)
  print("Total_Test_Accuracy: {:.4f}|NR F1: {:.4f}|FR F1: {:.4f}|TR F1: {:.4f}|UR F1: {:.4f}".format(
      sum(test_accs) / iterations, sum(NR_F1) / iterations, sum(FR_F1) / iterations, sum(TR_F1) / iterations, sum(UR_F1) / iterations))
  
apis: torch.nn.functional.log_softmax torch.nn.Linear torch.nn.functional.dropout torch.nn.functional.softmax torch.nn.functional.nll_loss torch.eq torch.nn.functional.relu torch.cuda.is_available torch.cat numpy.mean torch.nn.LeakyReLU