text: # encoding: utf-8
  
  import argparse
  import os
  import sys
  from os import mkdir
  
  import torch
  from torch.backends import cudnn
  
  sys.path.append('.')
  from config import cfg
  from data import make_data_loader
  from engine.inference import inference
  from modeling import build_model
  from utils.logger import setup_logger
  from tensorboardX import SummaryWriter
  
  writer = SummaryWriter('./work_space')
  
  def normalize(x, axis=-1):
      """Normalizing to unit length along the specified dimension.
      Args:
        x: pytorch Variable
      Returns:
        x: pytorch Variable, same shape as input
      """
      x = 1. * x / (torch.norm(x, 2, axis, keepdim=True).expand_as(x) + 1e-12)
      return x
  
  def euclidean_dist(x, y):
      """
      Args:
        x: pytorch Variable, with shape [m, d]
        y: pytorch Variable, with shape [n, d]
      Returns:
        dist: pytorch Variable, with shape [m, n]
      """
      m, n = x.size(0), y.size(0)
      xx = torch.pow(x, 2).sum(1, keepdim=True).expand(m, n)
      yy = torch.pow(y, 2).sum(1, keepdim=True).expand(n, m).t()
      dist = xx + yy
      dist.addmm_(1, -2, x, y.t())
      dist = dist.clamp(min=1e-12).sqrt()  # for numerical stability
      return dist
  
  def hard_example_mining(dist_mat, labels, return_inds=False):
      assert len(dist_mat.size()) == 2
      assert dist_mat.size(0) == dist_mat.size(1)
      N = dist_mat.size(0)
  
      # shape [N, N]
      is_pos = labels.expand(N, N).eq(labels.expand(N, N).t())
      is_neg = labels.expand(N, N).ne(labels.expand(N, N).t())
  
      dist_ap, relative_p_inds = torch.max(dist_mat[is_pos].contiguous().view(N, -1), 1, keepdim=True)
      
      dist_an, relative_n_inds = torch.min(
          dist_mat[is_neg].contiguous().view(N, -1), 1, keepdim=True)
      # shape [N]
      dist_ap = dist_ap.squeeze(1)
      dist_an = dist_an.squeeze(1)
      
      return dist_ap, dist_an
  
  def inference_threshold(cfg,model,data_loader,num_query):
      device = cfg.MODEL.DEVICE
      model.to(device)
      model.eval()
      for batch_idx, (img, target) in enumerate(data_loader):
          with torch.no_grad():
              img = img.cuda()
              target = target.cuda()
              feat = model(img)
              feat = normalize(feat, axis=-1)
              dist_mat = euclidean_dist(feat, feat)
              dist_ap, dist_an = hard_example_mining(dist_mat, target)
              writer.add_histogram('dist_ap',dist_ap,batch_idx)
              writer.add_histogram('dist_an',dist_an,batch_idx)
  
          
  def main():
      parser = argparse.ArgumentParser(description="ReID Inference")
      parser.add_argument(
          "--config_file", default="", help="path to config file", type=str
      )
      parser.add_argument("opts", help="Modify config options using the command-line", default=None,
                          nargs=argparse.REMAINDER)
  
      args = parser.parse_args()
  
      num_gpus = int(os.environ["WORLD_SIZE"]) if "WORLD_SIZE" in os.environ else 1
  
      if args.config_file != "":
          cfg.merge_from_file(args.config_file)
      cfg.merge_from_list(args.opts)
      cfg.freeze()
  
      output_dir = cfg.OUTPUT_DIR
      if output_dir and not os.path.exists(output_dir):
          mkdir(output_dir)
  
      logger = setup_logger("reid_baseline", output_dir, 0)
      logger.info("Using {} GPUS".format(num_gpus))
      logger.info(args)
  
      if args.config_file != "":
          logger.info("Loaded configuration file {}".format(args.config_file))
          with open(args.config_file, 'r') as cf:
              config_str = "\n" + cf.read()
              logger.info(config_str)
      logger.info("Running with config:\n{}".format(cfg))
  
      if cfg.MODEL.DEVICE == "cuda":
          os.environ['CUDA_VISIBLE_DEVICES'] = cfg.MODEL.DEVICE_ID
      cudnn.benchmark = True
  
      train_loader, val_loader, num_query, num_classes = make_data_loader(cfg)
      model = build_model(cfg, num_classes)
      model.load_param(cfg.TEST.WEIGHT)
  
      inference_threshold(cfg, model, train_loader, num_query)
      writer.close()
  
  if __name__ == '__main__':
      main()
  
  