code: def eval_metrics_query_and_gallery_dataset(
      model, query_dataloader, gallery_dataloader, device, k_vals, opt
  ):
      """
      Compute evaluation metrics on test-dataset, e.g. NMI, F1 and Recall @ k.
  
      Args:
          model:               PyTorch network, network to compute evaluation metrics for.
          query_dataloader:    PyTorch Dataloader, dataloader for query dataset, for which nearest neighbours in the gallery dataset are retrieved.
          gallery_dataloader:  PyTorch Dataloader, dataloader for gallery dataset, provides target samples which are to be retrieved in correspondance to the query dataset.
          device:              torch.device, Device to run inference on.
          k_vals:              list of int, Recall values to compute
          opt:                 argparse.Namespace, contains all training-specific parameters.
      Returns:
          F1 score (float), NMI score (float), recall_at_ks (list of float), query data embedding (np.ndarray), gallery data embedding (np.ndarray)
      """
      torch.cuda.empty_cache()
  
      _ = model.eval()
      n_classes = len(query_dataloader.dataset.avail_classes)
  
      with torch.no_grad():
          ### For all query test images, extract features
          query_target_labels, query_feature_coll = [], []
          query_image_paths = [
              x[0] for x in query_dataloader.dataset.image_list
          ]
          query_iter = tqdm(
              query_dataloader, desc="Extraction Query Features"
          )
          for idx, inp in enumerate(query_iter):
              input_img, target = inp[-1], inp[0]
              query_target_labels.extend(target.numpy().tolist())
              out = model(input_img.to(device), feature=True)
              query_feature_coll.extend(
                  out.cpu().detach().numpy().tolist()
              )
  
          ### For all gallery test images, extract features
          gallery_target_labels, gallery_feature_coll = [], []
          gallery_image_paths = [
              x[0] for x in gallery_dataloader.dataset.image_list
          ]
          gallery_iter = tqdm(
              gallery_dataloader, desc="Extraction Gallery Features"
          )
          for idx, inp in enumerate(gallery_iter):
              input_img, target = inp[-1], inp[0]
              gallery_target_labels.extend(target.numpy().tolist())
              out = model(input_img.to(device), feature=True)
              gallery_feature_coll.extend(
                  out.cpu().detach().numpy().tolist()
              )
  
          query_target_labels, query_feature_coll = np.hstack(
              query_target_labels
          ).reshape(-1, 1), np.vstack(query_feature_coll).astype(
              "float32"
          )
          gallery_target_labels, gallery_feature_coll = np.hstack(
              gallery_target_labels
          ).reshape(-1, 1), np.vstack(gallery_feature_coll).astype(
              "float32"
          )
  
          torch.cuda.empty_cache()
  
          ### Set CPU Cluster index
          stackset = np.concatenate(
              [query_feature_coll, gallery_feature_coll], axis=0
          )
          stacklabels = np.concatenate(
              [query_target_labels, gallery_target_labels], axis=0
          )
          cpu_cluster_index = faiss.IndexFlatL2(stackset.shape[-1])
          kmeans = faiss.Clustering(stackset.shape[-1], n_classes)
          kmeans.niter = 20
          kmeans.min_points_per_centroid = 1
          kmeans.max_points_per_centroid = 1000000000
  
          ### Train Kmeans
          kmeans.train(stackset, cpu_cluster_index)
          computed_centroids = faiss.vector_float_to_array(
              kmeans.centroids
          ).reshape(n_classes, stackset.shape[-1])
  
          ### Assign feature points to clusters
          faiss_search_index = faiss.IndexFlatL2(
              computed_centroids.shape[-1]
          )
          faiss_search_index.add(computed_centroids)
          _, model_generated_cluster_labels = faiss_search_index.search(
              stackset, 1
          )
  
          ### Compute NMI
          NMI = metrics.cluster.normalized_mutual_info_score(
              model_generated_cluster_labels.reshape(-1),
              stacklabels.reshape(-1),
          )
  
          ### Recover max(k_vals) nearest neighbours to use for recall computation
          faiss_search_index = faiss.IndexFlatL2(
              gallery_feature_coll.shape[-1]
          )
          faiss_search_index.add(gallery_feature_coll)
          _, k_closest_points = faiss_search_index.search(
              query_feature_coll, int(np.max(k_vals))
          )
          k_closest_classes = gallery_target_labels.reshape(-1)[
              k_closest_points
          ]
  
          ### Compute Recall
          recall_all_k = []
          for k in k_vals:
              recall_at_k = np.sum(
                  [
                      1
                      for target, recalled_predictions in zip(
                          query_target_labels, k_closest_classes
                      )
                      if target in recalled_predictions[:k]
                  ]
              ) / len(query_target_labels)
              recall_all_k.append(recall_at_k)
          recall_str = ", ".join(
              "@{0}: {1:.4f}".format(k, rec)
              for k, rec in zip(k_vals, recall_all_k)
          )
  
          ### Compute F1 score
          F1 = f1_score(
              model_generated_cluster_labels,
              stacklabels,
              stackset,
              computed_centroids,
          )
  
      return (
          F1,
          NMI,
          recall_all_k,
          query_feature_coll,
          gallery_feature_coll,
      )
  
imports: import warnings
  import csv
  import datetime
  import os
  import pickle
  import faiss
  import matplotlib.pyplot
  import numpy
  import torch
  from PIL import Image
  from sklearn import metrics
  from torch import nn
  from tqdm import tqdm
  import pdb
label_desc: Use image node_id 6 for calling a global function with example usage: eval_metrics_query_and_gallery_dataset(model, query_dataloader, gallery_dataloader, device, k_vals, opt) and returns: F1,  NMI,  recall_all_k,  query_feature_coll,  gallery_feature_coll