code: def train_model(self, metric="auc"):
      best_metric = 0
      for epoch in range(self.max_epoch):
          # Train
          self.train()
          print("=== Epoch %d train ===" % epoch)
          avg_loss = AverageMeter()
          avg_acc = AverageMeter()
          avg_pos_acc = AverageMeter()
          t = tqdm(self.train_loader)
          for iter, data in enumerate(t):
              if torch.cuda.is_available():
                  for i in range(len(data)):
                      try:
                          data[i] = data[i].cuda()
                      except:
                          pass
              label = data[0]
              bag_name = data[1]
              scope = data[2]
              args = data[3:]
              logits = self.model(
                  label, scope, *args, bag_size=self.bag_size
              )
              loss = self.criterion(logits, label)
              score, pred = logits.max(-1)  # (B)
              acc = float((pred == label).long().sum()) / label.size(0)
              pos_total = (label != 0).long().sum()
              pos_correct = (
                  (pred == label).long() * (label != 0).long()
              ).sum()
              if pos_total > 0:
                  pos_acc = float(pos_correct) / float(pos_total)
              else:
                  pos_acc = 0
  
              # Log
              avg_loss.update(loss.item(), 1)
              avg_acc.update(acc, 1)
              avg_pos_acc.update(pos_acc, 1)
              t.set_postfix(
                  loss=avg_loss.avg,
                  acc=avg_acc.avg,
                  pos_acc=avg_pos_acc.avg,
              )
  
              # Optimize
              loss.backward()
              self.optimizer.step()
              self.optimizer.zero_grad()
  
          # Val
          print("=== Epoch %d val ===" % epoch)
          result = self.eval_model(self.val_loader)
          print("AUC: %.4f" % result["auc"])
          print("Micro F1: %.4f" % (result["max_micro_f1"]))
          if result[metric] > best_metric:
              print("Best ckpt and saved.")
              torch.save(
                  {"state_dict": self.model.module.state_dict()},
                  self.ckpt,
              )
              best_metric = result[metric]
      print("Best %s on val set: %f" % (metric, best_metric))
  
file_path: OpenNRE/opennre/framework/bag_re.py
imports: import torch
  from torch import nn, optim
  import json
  from .data_loader import SentenceRELoader, BagRELoader
  from .utils import AverageMeter
  from tqdm import tqdm
  import os
label_desc: Use image node_id 2 for calling the BagRE obj's underlying member method code with example usage: obj.train_model(metric) without return types