code: def run(
      model,
      val_dataloader,
      num_class,
      net_dim=416,
      nms_thresh=0.6,
      objectness_thresh=0.001,
      device="cpu",
  ):
      model.eval()
      nc = int(num_class)  # number of classes
      iouv = torch.linspace(0.5, 0.95, 10).to(
          device
      )  # iou vector for mAP@0.5:0.95
      niou = iouv.numel()
  
      p, r, f1, mp, mr, map50, map = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
      stats, ap, ap_class = [], [], []
  
      for batch_i, (im, targets) in tqdm(enumerate(val_dataloader)):
          im = im.to(device)
          targets = targets.to(device)
          nb = im.shape[0]  # batch
  
          # Inference
          out = model(im)  # inference
  
          # NMS
          targets[:, 2:] *= torch.Tensor(
              [net_dim, net_dim, net_dim, net_dim]
          ).to(
              device
          )  # to pixels
          out = get_predictions(
              pred=out.to(device),
              num_classes=nc,
              objectness_confidence=objectness_thresh,
              nms_confidence_level=nms_thresh,
              device=device,
          )
  
          # Metrics
          for si in range(nb):
              labels = targets[targets[:, 0] == si, 1:]
              pred = (
                  out[out[:, 0] == si, :]
                  if isinstance(out, torch.Tensor)
                  else torch.zeros((0, 0), device=device)
              )
              nl = len(labels)
              tcls = labels[:, 0].tolist() if nl else []  # target class
  
              if len(pred) == 0:
                  if nl:
                      stats.append(
                          (
                              torch.zeros(
                                  0,
                                  niou,
                                  dtype=torch.bool,
                                  device="cpu",
                              ),
                              torch.Tensor(device="cpu"),
                              torch.Tensor(device="cpu"),
                              tcls,
                          )
                      )
                  continue
  
              # Predictions
              if nc == 1:
                  pred[:, 7] = 0
  
              if pred.shape[0] > 300:
                  pred = pred[:300, :]  # sorted by confidence
  
              predn = pred.clone()
  
              # Evaluate
              if nl:
                  tbox = xywh2xyxy(labels[:, 1:5]).to(
                      device
                  )  # target boxes
                  labelsn = torch.cat((labels[:, 0:1], tbox), 1).to(
                      device
                  )  # native-space labels
                  correct = process_batch(predn, labelsn, iouv)
              else:
                  correct = torch.zeros(
                      pred.shape[0], niou, dtype=torch.bool
                  )
              stats.append(
                  (
                      correct.cpu(),
                      pred[:, 5].cpu(),
                      pred[:, 7].cpu(),
                      tcls,
                  )
              )  # (correct, conf, pcls, tcls)
  
      # Compute metrics
      stats = [np.concatenate(x, 0) for x in zip(*stats)]  # to numpy
      if len(stats) and stats[0].any():
          p, r, ap, f1, ap_class = ap_per_class(*stats)
          ap50, ap = ap[:, 0], ap.mean(1)  # AP@0.5, AP@0.5:0.95
          mp, mr, map50, map = (
              p.mean(),
              r.mean(),
              ap50.mean(),
              ap.mean(),
          )
  
      return mp, mr, map50, map
  
file_path: ImageAI/imageai/Detection/Custom/yolo/validate.py
imports: import os
  import numpy
  import torch
  from torchvision.ops import box_iou
  from ....yolov3.utils import get_predictions
  from .metric import ap_per_class
  from tqdm import tqdm
label_desc: Use image node_id 3 for calling a global function with example usage: run(model, val_dataloader, num_class, net_dim, nms_thresh, objectness_thresh, device) and returns: mp,  mr,  map50,  map