def on_epoch_begin(self): self.batch_nb = 0 self.current_epoch += 1 self.t0 = time.time() self.running_loss.reset() self.tng_prefetcher = data_prefetcher(self.tng_dataloader)
def inference_with_distmat( cfg, test_dataloader, num_query, distmat, ): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") pids, camids = [], [] test_prefetcher = data_prefetcher(test_dataloader, cfg) batch = test_prefetcher.next() while batch[0] is not None: img, pid, camid = batch pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() # query q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) #distmat = re_ranking(qf, gf, k1=14, k2=4, lambda_value=0.4) cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") logger.info(f"Score: {(mAP + cmc[0]) / 2.:.1%}")
def get_distmat(self): m = self.model.eval() feats = [] pids = [] camids = [] val_prefetcher = data_prefetcher(self.val_dataloader) batch = val_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): feat = m(img.cuda()) feats.append(feat) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) feats = torch.cat(feats, dim=0) if self.cfg.TEST.NORM: feats = F.normalize(feats) qf = feats[:self.num_query] gf = feats[self.num_query:] self.q_pids = np.asarray(pids[:self.num_query]) self.g_pids = np.asarray(pids[self.num_query:]) self.q_camids = np.asarray(camids[:self.num_query]) self.g_camids = np.asarray(camids[self.num_query:]) # Cosine distance distmat = torch.mm(qf, gf.t()) self.distmat = distmat.cpu().numpy() self.indices = np.argsort(-self.distmat, axis=1) self.matches = ( self.g_pids[self.indices] == self.q_pids[:, np.newaxis]).astype( np.int32)
def test(self): # convert to eval mode self.model.eval() feats, pids, camids = [], [], [] val_prefetcher = data_prefetcher(self.val_dataloader, self.cfg) batch = val_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): feat = self.model(img) if isinstance(feat, tuple): feats.append(feat[0]) else: feats.append(feat) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = val_prefetcher.next() #### feats = torch.cat(feats, dim=0) if self.cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) # query qf = feats[:self.num_query] q_pids = np.asarray(pids[:self.num_query]) q_camids = np.asarray(camids[:self.num_query]) # gallery gf = feats[self.num_query:] g_pids = np.asarray(pids[self.num_query:]) g_camids = np.asarray(camids[self.num_query:]) # TODO: 添加rerank的测评结果 # m, n = qf.shape[0], gf.shape[0] distmat = -torch.mm(qf, gf.t()).cpu().numpy() # distmat = torch.pow(qf, 2).sum(dim=1, keepdim=True).expand(m, n) + \ # torch.pow(gf, 2).sum(dim=1, keepdim=True).expand(n, m).t() # distmat.addmm_(1, -2, qf, gf.t()) # distmat = distmat.numpy() cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) self.logger.info(f"Test Results - Epoch: {self.current_epoch}") self.logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: self.logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") self.writer.add_scalar('rank1', cmc[0], self.global_step) self.writer.add_scalar('mAP', mAP, self.global_step) metric_dict = {'rank1': cmc[0], 'mAP': mAP} # convert to train mode self.model.train() return metric_dict
def on_epoch_begin(self): self.batch_nb = 0 self.current_epoch += 1 self.t0 = time.time() self.running_loss.reset() if 'InsDis' in list(self.cfg.SOLVER.LOSSTYPE): self.tng_prefetcher = instance_prefetcher(self.tng_dataloader) else: self.tng_prefetcher = data_prefetcher(self.tng_dataloader)
def inference_no_rerank(cfg, model, test_dataloader, num_query): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") model.eval() feats, pids, camids = [], [], [] test_prefetcher = data_prefetcher(test_dataloader, cfg) batch = test_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): feat = model(img) #feat = model(torch.flip(img, [3])) if isinstance(feat, tuple): feats.append(feat[0]) #local_feats.append(feat[1]) else: feats.append(feat) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() feats = torch.cat(feats, dim=0) if cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) # query qf = feats[:num_query] q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery gf = feats[num_query:] g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) distmat = -torch.mm(qf, gf.t()).cpu().numpy() cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") logger.info(f"Score: {(mAP + cmc[0]) / 2.:.1%}") index = np.argsort(distmat, axis=1) # from small to large new_gallery_index = np.unique(index[:, :top_k].reshape(-1)) print('new_gallery_index', len(new_gallery_index)) return new_gallery_index
def test(self): # convert to eval mode self.model.eval() metric_dict = list() for val_dataset_name, val_dataloader, num_query in zip(self.cfg.DATASETS.TEST_NAMES, self.val_dataloader_collection, self.num_query_len_collection): feats,pids,camids = [],[],[] val_prefetcher = data_prefetcher(val_dataloader) batch = val_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): _, feat = self.model(img) feats.append(feat) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = val_prefetcher.next() feats = torch.cat(feats, dim=0) if self.cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) # query qf = feats[:num_query] q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery gf = feats[num_query:] g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) # m, n = qf.shape[0], gf.shape[0] distmat = torch.mm(qf, gf.t()).cpu().numpy() # distmat = torch.pow(qf, 2).sum(dim=1, keepdim=True).expand(m, n) + \ # torch.pow(gf, 2).sum(dim=1, keepdim=True).expand(n, m).t() # distmat.addmm_(1, -2, qf, gf.t()) # distmat = distmat.numpy() cmc, mAP = evaluate(-distmat, q_pids, g_pids, q_camids, g_camids) self.logger.info(f"Test Results on {val_dataset_name} - Epoch: {self.current_epoch}") self.logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: self.logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") self.writer.add_scalar('rank1', cmc[0], self.global_step) self.writer.add_scalar('mAP', mAP, self.global_step) metric_dict.append({'rank1': cmc[0], 'mAP': mAP}) # convert to train mode self.model.train() return metric_dict[0]
def inference(cfg, model, test_dataloader, num_query): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") model.eval() feats, pids, camids = [], [], [] test_prefetcher = data_prefetcher(test_dataloader) batch = test_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): feat = model(img) feats.append(feat) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() feats = torch.cat(feats, dim=0) if cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) # query qf = feats[:num_query] q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery gf = feats[num_query:] g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) # cosine distance distmat = torch.mm(qf, gf.t()).cpu().numpy() # euclidean distance # distmat = torch.pow(qf, 2).sum(dim=1, keepdim=True).expand(m, n) + \ # torch.pow(gf, 2).sum(dim=1, keepdim=True).expand(n, m).t() # distmat.addmm_(1, -2, qf, gf.t()) # distmat = distmat.numpy() cmc, mAP = evaluate(-distmat, q_pids, g_pids, q_camids, g_camids) logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}")
def inference_flipped_deprecated( cfg, model, test_dataloader, num_query, theta=0.95, use_local_feature=False # 是否使用local特征 ): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") model.eval() g_feats, l_feats, gf_feats, lf_feats, pids, camids = [], [], [], [], [], [] val_prefetcher = data_prefetcher(test_dataloader, cfg) batch = val_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): g_feat, bn_gf, lf, l_feat = model(img) gf_feat, bn_gff, lff, lf_feat = model(torch.flip(img, [3])) g_feats.append(g_feat.data.cpu()) l_feats.append(l_feat.data.cpu()) gf_feats.append(gf_feat.data.cpu()) lf_feats.append(lf_feat.data.cpu()) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = val_prefetcher.next() g_feats = torch.cat(g_feats, dim=0) l_feats = torch.cat(l_feats, dim=0) gf_feats = torch.cat(gf_feats, dim=0) lf_feats = torch.cat(lf_feats, dim=0) if cfg.TEST.NORM: g_feats = F.normalize(g_feats, p=2, dim=1) gf_feats = F.normalize(gf_feats, p=2, dim=1) # query qf = g_feats[:num_query] lqf = l_feats[:num_query] qff = gf_feats[:num_query] lqff = lf_feats[:num_query] q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery gf = g_feats[num_query:] lgf = l_feats[num_query:] gff = gf_feats[num_query:] lgff = lf_feats[num_query:] g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) # calculate the global distance scores, indices, dist_mats = [], [], [] #use_local_feature = True if use_local_feature: logger.info("--------computing local features ...--------") lqf = lqf.permute(0, 2, 1) lgf = lgf.permute(0, 2, 1) local_distmat = low_memory_local_dist(lqf.numpy(), lgf.numpy(), aligned=True) local_qq_distmat = low_memory_local_dist(lqf.numpy(), lqf.numpy(), aligned=True) local_gg_distmat = low_memory_local_dist(lgf.numpy(), lgf.numpy(), aligned=True) local_dist = np.concatenate([ np.concatenate([local_qq_distmat, local_distmat], axis=1), np.concatenate([local_distmat.T, local_gg_distmat], axis=1) ], axis=0) logger.info("--------computing flipped local features ...--------") lqff = lqff.permute(0, 2, 1) lgff = lgff.permute(0, 2, 1) local_distmat = low_memory_local_dist(lqff.numpy(), lgff.numpy(), aligned=True) local_qq_distmat = low_memory_local_dist(lqff.numpy(), lqff.numpy(), aligned=True) local_gg_distmat = low_memory_local_dist(lgff.numpy(), lgff.numpy(), aligned=True) local_dist_flip = np.concatenate([ np.concatenate([local_qq_distmat, local_distmat], axis=1), np.concatenate([local_distmat.T, local_gg_distmat], axis=1) ], axis=0) else: local_dist = None local_dist_flip = None logger.info("use reranking") #for theta in thetas: if True: distmat = re_ranking(qf, gf, k1=6, k2=2, lambda_value=0.3, local_distmat=local_dist, theta_value=theta, only_local=False) distmat_flip = re_ranking(qff, gff, k1=6, k2=2, lambda_value=0.3, local_distmat=local_dist_flip, theta_value=theta, only_local=False) # 合并距离 distmat = (distmat + distmat_flip) / 2 score = distmat index = np.argsort(score, axis=1) # from small to large scores.append(score) indices.append(index) dist_mats.append(distmat) return scores, indices, dist_mats
def inference_aligned_flipped(cfg, model, test_dataloader, num_query, use_local_feature, use_rerank, use_cross_feature): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing aligned with flipping") model.eval() pids, camids = [], [] gfs, bn_gfs, lfs, bn_lfs = [], [], [], [] gfs_flipped, bn_gfs_flipped, lfs_flipped, bn_lfs_flipped = [], [], [], [] test_prefetcher = data_prefetcher(test_dataloader, cfg) batch = test_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): ret = model(img) ret_flip = model(torch.flip(img, [3])) if len(ret) == 4: gf, bn_gf, lf, bn_lf = ret gff, bn_gff, lff, bn_lff = ret_flip elif len(ret) == 2: gf, bn_gf = ret gff, bn_gff = ret_flip lf, bn_lf = None, None lff, bn_lff = None, None elif ret is not tuple: gf = bn_gf = ret gff = bn_gff = ret_flip lf, bn_lf = None, None lff, bn_lff = None, None else: #print('ret', ret.size()) raise Exception("Unknown model returns, length = ", len(ret)) # 4 features gfs.append(gf.cpu()) bn_gfs.append(bn_gf.cpu()) if use_local_feature: lfs.append(lf.cpu()) bn_lfs.append(bn_lf.cpu()) # 4 features flipped gfs_flipped.append(gff.cpu()) bn_gfs_flipped.append(bn_gff.cpu()) if use_local_feature: lfs_flipped.append(lff.cpu()) bn_lfs_flipped.append(bn_lff.cpu()) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() distmat1 = distmat2 = None logger.info( f"use_cross_feature = {use_cross_feature}, use_local_feature = {use_local_feature}, use_rerank = {use_rerank}" ) if use_cross_feature: logger.info("Computing distmat with bn_gf (+ lf)") distmat2 = compute_distmat(cfg, num_query, bn_gfs, bn_gfs_flipped, lfs, lfs_flipped, theta=0.45, use_local_feature=use_local_feature, use_rerank=use_rerank) distmat = distmat2 #distmat = (distmat1 + distmat2) / 2 else: logger.info("Computing distmat with gf (+ bn_lf)") distmat1 = compute_distmat(cfg, num_query, gfs, gfs_flipped, bn_lfs, bn_lfs_flipped, theta=0.95, use_local_feature=use_local_feature, use_rerank=use_rerank) distmat = distmat1 score = distmat index = np.argsort(score, axis=1) # from small to large #index = mem_saving_argsort(score) # better for large matrix ? return distmat, index, distmat1, distmat2
def inference( cfg, model, test_dataloader_collection, num_query_collection, is_vis=False, test_collection=None, use_mask=True, num_parts=10, mask_image=False ): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") model.eval() adj = torch.from_numpy(coarse_adj_npy).float() idx = -1 for test_dataset_name, test_dataloader, num_query in zip(cfg.DATASETS.TEST_NAMES, test_dataloader_collection, num_query_collection): idx += 1 feats, pids, camids = [], [], [] if use_mask: test_prefetcher = data_prefetcher_mask(test_dataloader) else: test_prefetcher = data_prefetcher(test_dataloader) batch = test_prefetcher.next() while batch[0] is not None: if use_mask: img, mask, pid, camid = batch adj_batch = adj.repeat(img.size(0), 1, 1) with torch.no_grad(): output = model(img, img, mask, adj_batch) # feat = output[1] # feat = output[3] feat = torch.cat([output[1], output[3]], dim=1) feats.append(feat) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() feats = torch.cat(feats, dim=0) if cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) # query qf = feats[:num_query] q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery gf = feats[num_query:] g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) # cosine distance distmat = torch.mm(qf, gf.t()).cpu().numpy() # euclidean distance # distmat = torch.pow(qf, 2).sum(dim=1, keepdim=True).expand(m, n) + \ # torch.pow(gf, 2).sum(dim=1, keepdim=True).expand(n, m).t() # distmat.addmm_(1, -2, qf, gf.t()) # distmat = distmat.numpy() cmc, mAP = evaluate(-distmat, q_pids, g_pids, q_camids, g_camids) logger.info(f"Results on {test_dataset_name} : ") logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") if is_vis: query_rand = 10 topK = 10 is_save_all = True query_rand_idx = range(0, num_query) if is_save_all else random.sample(range(0, num_query), query_rand) print(f'|-------- Randomly saving top-{topK} results of {len(query_rand_idx)} queries for {test_dataset_name} --------|') qf_rand = qf[query_rand_idx] q_pids_rand = q_pids[query_rand_idx] q_camids_rand = q_camids[query_rand_idx] q_items = test_collection[idx][:num_query] q_items_rand = list() for i in query_rand_idx: q_items_rand.append(q_items[i]) g_items = test_collection[idx][num_query:] distmat_rand = torch.mm(qf_rand, gf.t()).cpu().numpy() distmat_rand = -distmat_rand indices = np.argsort(distmat_rand, axis=1) matches = (g_pids[indices] == q_pids_rand[:, np.newaxis]).astype(np.int32) save_img_size = (256, 256) if test_dataset_name == 'market1501': save_img_size = (128, 256) for q_idx in range(len(query_rand_idx)): savefilename = '' # get query pid and camid q_path = q_items_rand[q_idx][0] q_pid = q_items_rand[q_idx][1] q_camid = q_items_rand[q_idx][2] savefilename += 'q-'+q_path.split('/')[-1]+'_g' # remove gallery samples that have the same pid and camid with query order = indices[q_idx] remove = (g_pids[order] == q_pid) & (g_camids[order] == q_camid) keep = np.invert(remove) print('Query Path : ', q_path) print('Result idx : ', order[:topK]) img_list = list() q_img = cv2.imread(q_path) q_img = cv2.resize(q_img, save_img_size) cv2.rectangle(q_img, (0,0), save_img_size, (255,0,0), 4) img_list.append(q_img) for g_idx in order[:topK]: g_img = cv2.imread(g_items[g_idx][0]) g_img = cv2.resize(g_img, save_img_size) if q_pid == g_items[g_idx][1] and q_camid == g_items[g_idx][2]: cv2.rectangle(g_img, (0,0), save_img_size, (255,255,0), 4) elif q_pid == g_items[g_idx][1] and q_camid != g_items[g_idx][2]: cv2.rectangle(g_img, (0,0), save_img_size, (0,255,0), 4) else: cv2.rectangle(g_img, (0,0), save_img_size, (0,0,255), 4) img_list.append(g_img) savefilename += '-'+str(g_items[g_idx][1]) pic = np.concatenate(img_list, 1) picsavedir = os.path.join(cfg.OUTPUT_DIR, '-'.join(cfg.DATASETS.TEST_NAMES), 'examples', test_dataset_name) if not os.path.exists(picsavedir): os.makedirs(picsavedir) savefilepath = os.path.join(picsavedir, savefilename+'.jpg') cv2.imwrite(savefilepath, pic) print('Save example picture to ', savefilepath)
def update_bn_stats(model, data_loader, num_iters: int = 200): """ Recompute and update the batch norm stats to make them more precise. During training both BN stats and the weight are changing after every iteration, so the running average can not precisely reflect the actual stats of the current model. In this function, the BN stats are recomputed with fixed weights, to make the running average more precise. Specifically, it computes the true average of per-batch mean/variance instead of the running average. Args: model (nn.Module): the model whose bn stats will be recomputed. Note that: 1. This function will not alter the training mode of the given model. Users are responsible for setting the layers that needs precise-BN to training mode, prior to calling this function. 2. Be careful if your models contain other stateful layers in addition to BN, i.e. layers whose state can change in forward iterations. This function will alter their state. If you wish them unchanged, you need to either pass in a submodule without those layers, or backup the states. data_loader (iterator): an iterator. Produce data as inputs to the model. num_iters (int): number of iterations to compute the stats. """ bn_layers = get_bn_modules(model) if len(bn_layers) == 0: return # In order to make the running stats only reflect the current batch, the # momentum is disabled. # bn.running_mean = (1 - momentum) * bn.running_mean + momentum * batch_mean # Setting the momentum to 1.0 to compute the stats without momentum. momentum_actual = [bn.momentum for bn in bn_layers] for bn in bn_layers: bn.momentum = 1.0 # Note that running_var actually means "running average of variance" running_mean = [torch.zeros_like(bn.running_mean) for bn in bn_layers] running_var = [torch.zeros_like(bn.running_var) for bn in bn_layers] ind = 0 num_epoch = num_iters // len(data_loader) + 1 for _ in range(num_epoch): prefetcher = data_prefetcher(data_loader) batch = prefetcher.next() while batch[0] is not None: model(batch[0], batch[1]) for i, bn in enumerate(bn_layers): # Accumulates the bn stats. running_mean[i] += (bn.running_mean - running_mean[i]) / (ind + 1) running_var[i] += (bn.running_var - running_var[i]) / (ind + 1) # We compute the "average of variance" across iterations. if ind == (num_iters - 1): print( f"update_bn_stats is running for {num_iters} iterations.") break ind += 1 batch = prefetcher.next() for i, bn in enumerate(bn_layers): # Sets the precise bn stats. bn.running_mean = running_mean[i] bn.running_var = running_var[i] bn.momentum = momentum_actual[i]
def inference_flipped( cfg, model, test_dataloader, num_query, thetas, use_local_feature=True # 是否使用local特征 ): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") model.eval() feats, feats_flipped, pids, camids = [], [], [], [] local_feats, local_feats_flipped = [], [] local_feats2, local_feats2_flipped = [], [] test_prefetcher = data_prefetcher(test_dataloader) batch = test_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): feat = model(img) feat_flipped = model(torch.flip(img, [3])) if isinstance(feat, tuple): feats.append(feat[0]) feats_flipped.append(feat_flipped[0]) if len(feat[1]) > 1: local_feats.append(feat[1][0]) local_feats2.append(feat[1][1]) local_feats_flipped.append(feat_flipped[1][0]) local_feats2_flipped.append(feat_flipped[1][1]) else: local_feats.append(feat[1]) local_feats_flipped.append(feat_flipped[1]) else: feats.append(feat) feats_flipped.append(feat_flipped) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() feats = torch.cat(feats, dim=0) feats_flipped = torch.cat(feats_flipped, dim=0) if len(local_feats) > 0: local_feats = torch.cat(local_feats, dim=0) local_feats_flipped = torch.cat(local_feats_flipped, dim=0) if len(local_feats2) > 0: local_feats2 = torch.cat(local_feats2, dim=0) local_feats2_flipped = torch.cat(local_feats2_flipped, dim=0) if cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) feats_flipped = F.normalize(feats_flipped, p=2, dim=1) # query qf = feats[:num_query] qf_flipped = feats_flipped[:num_query] if len(local_feats) > 0: lqf = local_feats[:num_query] lqf_flipped = local_feats_flipped[:num_query] if len(local_feats2) > 0: lqf2 = local_feats2[:num_query] lqf2_flipped = local_feats2_flipped[:num_query] q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery gf = feats[num_query:] gf_flipped = feats_flipped[num_query:] if len(local_feats) > 0: lgf = local_feats[num_query:] lgf_flipped = local_feats_flipped[num_query:] if len(local_feats2) > 0: lgf2 = local_feats2[num_query:] lgf2_flipped = local_feats2_flipped[num_query:] g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) # cosine distance # distmat = torch.mm(qf, gf.t()).cpu().numpy() if len(local_feats) > 0: local_distmat = compute_local_distmat(lqf, lgf) local_distmat_flipped = compute_local_distmat(lqf_flipped, lgf_flipped) else: local_distmat = None local_distmat_flipped = None if len(local_feats2) > 0: local_distmat2 = compute_local_distmat(lqf2, lgf2) local_distmat2_flipped = compute_local_distmat(lqf2_flipped, lgf2_flipped) else: local_distmat2 = None local_distmat2_flipped = None # use reranking logger.info("use reranking") theta = 0.95 scores, indices, dist_mats = [], [], [] for theta2 in thetas: distmat = re_ranking_v3(qf, gf, k1=6, k2=2, lambda_value=0.3, local_distmat=local_distmat, theta_value=theta, local_distmat2=local_distmat2, theta_value2=theta2, only_local=False) distmat_flip = re_ranking_v3(qf_flipped, gf_flipped, k1=6, k2=2, lambda_value=0.3, local_distmat=local_distmat_flipped, theta_value=theta, local_distmat2=local_distmat2_flipped, theta_value2=theta2, only_local=False) # 合并距离 distmat = (distmat + distmat_flip) / 2 score = distmat index = np.argsort(score, axis=1) # from small to large scores.append(score) indices.append(index) dist_mats.append(distmat) return scores, indices, dist_mats
def inference_aligned_flipped(cfg, model, test_dataloader, num_query, use_local_feature, use_rerank, use_cross_feature): """ inference an aligned net with flipping and two pairs of global feature and local feature :param cfg: :param model: :param test_dataloader: :param num_query: :return: """ logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing aligned with flipping") model.eval() pids, camids = [], [] gfs, bn_gfs, lfs, bn_lfs = [], [], [], [] gfs_flipped, bn_gfs_flipped, lfs_flipped, bn_lfs_flipped = [], [], [], [] test_prefetcher = data_prefetcher(test_dataloader, cfg) batch = test_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): ret = model(img) ret_flip = model(torch.flip(img, [3])) if len(ret) == 4: gf, bn_gf, lf, bn_lf = ret gff, bn_gff, lff, bn_lff = ret_flip elif len(ret) == 2: gf, bn_gf = ret gff, bn_gff = ret_flip lf, bn_lf = None, None lff, bn_lff = None, None elif ret is not tuple: bn_gf = ret[:, :2048] gf = ret[:, 2048:] gff = ret_flip[:, :2048] bn_gff = ret_flip[:, 2048:] lf, bn_lf = None, None lff, bn_lff = None, None else: # print('ret', ret.size()) raise Exception("Unknown model returns, length = ", len(ret)) # 4 features gfs.append(gf.cpu()) bn_gfs.append(bn_gf.cpu()) if use_local_feature: if use_cross_feature: lfs.append(lf.cpu()) else: bn_lfs.append(bn_lf.cpu()) # 4 features flipped gfs_flipped.append(gff.cpu()) bn_gfs_flipped.append(bn_gff.cpu()) if use_local_feature: if use_cross_feature: lfs_flipped.append(lff.cpu()) else: bn_lfs_flipped.append(bn_lff.cpu()) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) logger.info( f"use_local_feature = {use_local_feature}, use_rerank = {use_rerank}") logger.info("Computing distmat with bn_gf") distmat2 = compute_distmat(cfg, num_query, bn_gfs, bn_gfs_flipped, lfs, lfs_flipped, theta=0.45, use_local_feature=use_local_feature, use_rerank=use_rerank) logger.info("Computing distmat with gf + bn_lf") distmat1 = compute_distmat(cfg, num_query, gfs, gfs_flipped, bn_lfs, bn_lfs_flipped, theta=0.95, use_local_feature=use_local_feature, use_rerank=use_rerank) for theta in np.linspace(0, 1, 21): #theta = 0.55 distmat = distmat1 * (1 - theta) + distmat2 * theta cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) logger.info(f"theta: {theta:.2%} mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") logger.info(f"Score: {(mAP + cmc[0]) / 2.:.1%}")
def inference_flipped(cfg, model, test_dataloader, num_query): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") model.eval() feats, feats_flipped, pids, camids = [], [], [], [] local_feats, local_feats_flipped = [], [] test_prefetcher = data_prefetcher(test_dataloader) batch = test_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): feat = model(img) feat_flipped = model(torch.flip(img, [3])) if isinstance(feat, tuple): feats.append(feat[0]) local_feats.append(feat[1]) feats_flipped.append(feat_flipped[0]) local_feats_flipped.append(feat_flipped[1]) else: feats.append(feat) feats_flipped.append(feat_flipped) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() feats = torch.cat(feats, dim=0) feats_flipped = torch.cat(feats_flipped, dim=0) if len(local_feats) > 0: local_feats = torch.cat(local_feats, dim=0) local_feats_flipped = torch.cat(local_feats_flipped, dim=0) #print('feats_flipped', len(feats_flipped), feats_flipped[0]) if cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) feats_flipped = F.normalize(feats_flipped, p=2, dim=1) # query qf = feats[:num_query] qf_flipped = feats_flipped[:num_query] if len(local_feats) > 0: lqf = local_feats[:num_query] lqf_flipped = local_feats_flipped[:num_query] q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery gf = feats[num_query:] gf_flipped = feats_flipped[num_query:] if len(local_feats) > 0: lgf = local_feats[num_query:] lgf_flipped = local_feats_flipped[num_query:] g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) # cosine distance #distmat = torch.mm(qf, gf.t()).cpu().numpy() if len(local_feats) > 0: #if True: # calculate the local distance lqf = lqf.permute(0, 2, 1) lgf = lgf.permute(0, 2, 1) local_qg_distmat = low_memory_local_dist(lqf.cpu().numpy(), lgf.cpu().numpy(), aligned=True) local_qq_distmat = low_memory_local_dist(lqf.cpu().numpy(), lqf.cpu().numpy(), aligned=True) local_gg_distmat = low_memory_local_dist(lgf.cpu().numpy(), lgf.cpu().numpy(), aligned=True) local_distmat = np.concatenate([ np.concatenate([local_qq_distmat, local_qg_distmat], axis=1), np.concatenate([local_qg_distmat.T, local_gg_distmat], axis=1) ], axis=0) # flipped lqf = lqf_flipped.permute(0, 2, 1) lgf = lgf_flipped.permute(0, 2, 1) local_qg_distmat = low_memory_local_dist(lqf.cpu().numpy(), lgf.cpu().numpy(), aligned=True) local_qq_distmat = low_memory_local_dist(lqf.cpu().numpy(), lqf.cpu().numpy(), aligned=True) local_gg_distmat = low_memory_local_dist(lgf.cpu().numpy(), lgf.cpu().numpy(), aligned=True) local_distmat_flipped = np.concatenate([ np.concatenate([local_qq_distmat, local_qg_distmat], axis=1), np.concatenate([local_qg_distmat.T, local_gg_distmat], axis=1) ], axis=0) else: local_distmat = None # use reranking logger.info("use reranking") #distmat = re_ranking(qf, gf, k1=14, k2=4, lambda_value=0.4) search_theta = True if search_theta: best_score = 0 #for theta in np.linspace(0.9, 1.0, 11): for theta in np.linspace(0, 1.0, 21): distmat = re_ranking(qf, gf, k1=6, k2=2, lambda_value=0.3, local_distmat=local_distmat, theta_value=theta, only_local=False) # (current best) distmat_flipped = re_ranking(qf_flipped, gf_flipped, k1=6, k2=2, lambda_value=0.3, local_distmat=local_distmat_flipped, theta_value=theta, only_local=False) # (current best) distmat = (distmat + distmat_flipped) / 2 #cmc, mAP = evaluate(distmat + distmat_flipped, q_pids, g_pids, q_camids, g_camids) cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) score = (cmc[0] + mAP) / 2 print('theta', np.around(theta, 2), 'r1, mAP, score', np.around(cmc[0], 4), np.around(mAP, 4), np.around(score, 4)) if score > best_score: best_score = score best_param = theta best_distmat = distmat # saving strtime = time.strftime("%Y%m%d_%H%M%S", time.localtime()) if abs(theta - 0.95) < 1e-4: # saving dist_mats f = h5py.File( 'dist_mats/val_%s_%s_t0.95_flip.h5' % (cfg.MODEL.NAME, strtime), 'w') f.create_dataset('dist_mat', data=distmat, compression='gzip') f.close() print('Best Param', best_param) distmat = best_distmat else: distmat = re_ranking(qf, gf, k1=6, k2=2, lambda_value=0.3, local_distmat=local_distmat, only_local=False, theta_value=0.95) #(current best) distmat_flipped = re_ranking(qf_flipped, gf_flipped, k1=6, k2=2, lambda_value=0.3, local_distmat=local_distmat_flipped, theta_value=0.95, only_local=False) # (current best) distmat = (distmat + distmat_flipped) / 2 cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") logger.info(f"Score: {(mAP + cmc[0]) / 2.:.1%}")
def inference_aligned( cfg, model, test_dataloader, num_query, ): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") model.eval() g_feats, l_feats, pids, camids = [], [], [], [] val_prefetcher = data_prefetcher(test_dataloader) batch = val_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): g_feat, l_feat = model(img) #g_feat, l_feat = model(torch.flip(img, [3])) # better g_feats.append(g_feat.data.cpu()) l_feats.append(l_feat.data.cpu()) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = val_prefetcher.next() g_feats = torch.cat(g_feats, dim=0) l_feats = torch.cat(l_feats, dim=0) if cfg.TEST.NORM: g_feats = F.normalize(g_feats, p=2, dim=1) # query qf = g_feats[:num_query] lqf = l_feats[:num_query] q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery gf = g_feats[num_query:] lgf = l_feats[num_query:] g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) # calculate the global distance if True: logger.info("--------use re-ranking--------") lqf = lqf.permute(0, 2, 1) lgf = lgf.permute(0, 2, 1) local_distmat = low_memory_local_dist(lqf.numpy(), lgf.numpy(), aligned=True) local_qq_distmat = low_memory_local_dist(lqf.numpy(), lqf.numpy(), aligned=True) local_gg_distmat = low_memory_local_dist(lgf.numpy(), lgf.numpy(), aligned=True) local_dist = np.concatenate([ np.concatenate([local_qq_distmat, local_distmat], axis=1), np.concatenate([local_distmat.T, local_gg_distmat], axis=1) ], axis=0) distmat = re_ranking(qf, gf, k1=6, k2=2, lambda_value=0.3, local_distmat=local_dist, theta_value=0.5, only_local=False) ## theta hyer-patameters # for theta in np.arange(0,1.1,0.1): # distmat = re_ranking(qf,gf,k1=6,k2=2,lambda_value=0.3,local_distmat=local_dist,theta=theta,only_local=False) # cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) # logger.info(f"mAP: {mAP:.1%}") # for r in [1, 5, 10]: # logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") # logger.info("Theta:{}; Score: {}".format(theta, (mAP+cmc[0])/2.)) #score = distmat #index = np.argsort(score, axis=1) # from small to large cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") logger.info(f"Score: {(mAP + cmc[0]) / 2.:.1%}")
def inference_flipped(cfg, model, test_dataloader, num_query, use_re_ranking=True, distance_metric='global_local'): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") model.eval() g_feats, l_feats, gf_feats, lf_feats, pids, camids = [], [], [], [], [], [] val_prefetcher = data_prefetcher(test_dataloader) batch = val_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): g_feat, l_feat = model(img) gf_feat, lf_feat = model(torch.flip(img, [3])) g_feats.append(g_feat.data.cpu()) l_feats.append(l_feat.data.cpu()) gf_feats.append(gf_feat.data.cpu()) lf_feats.append(lf_feat.data.cpu()) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = val_prefetcher.next() g_feats = torch.cat(g_feats, dim=0) l_feats = torch.cat(l_feats, dim=0) gf_feats = torch.cat(gf_feats, dim=0) lf_feats = torch.cat(lf_feats, dim=0) if cfg.TEST.NORM: g_feats = F.normalize(g_feats, p=2, dim=1) gf_feats = F.normalize(gf_feats, p=2, dim=1) # query qf = g_feats[:num_query] lqf = l_feats[:num_query] qff = gf_feats[:num_query] lqff = lf_feats[:num_query] q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery gf = g_feats[num_query:] lgf = l_feats[num_query:] gff = gf_feats[num_query:] lgff = lf_feats[num_query:] g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) # calculate the global distance if not use_re_ranking: m, n = qf.shape[0], gf.shape[0] global_distmat = torch.pow(qf, 2).sum(dim=1, keepdim=True).expand(m, n) + \ torch.pow(gf, 2).sum(dim=1, keepdim=True).expand(n, m).t() global_distmat.addmm_(1, -2, qf, gf.t()) global_distmat = global_distmat.numpy() # calculate the local distance lqf = lqf.permute(0, 2, 1) lgf = lgf.permute(0, 2, 1) local_distmat = low_memory_local_dist(lqf.numpy(), lgf.numpy(), aligned=True) if distance_metric == 'global': logger.info("--------use global features--------") distmat = global_distmat elif distance_metric == 'local': logger.info("--------use local features--------") distmat = local_distmat elif distance_metric == 'global_local': logger.info("--------use global and local features--------") distmat = global_distmat + local_distmat else: logger.info("--------use re-ranking--------") lqf = lqf.permute(0, 2, 1) lgf = lgf.permute(0, 2, 1) local_distmat = low_memory_local_dist(lqf.numpy(), lgf.numpy(), aligned=True) local_qq_distmat = low_memory_local_dist(lqf.numpy(), lqf.numpy(), aligned=True) local_gg_distmat = low_memory_local_dist(lgf.numpy(), lgf.numpy(), aligned=True) local_dist = np.concatenate([ np.concatenate([local_qq_distmat, local_distmat], axis=1), np.concatenate([local_distmat.T, local_gg_distmat], axis=1) ], axis=0) logger.info("--------use re-ranking flipped--------") lqff = lqff.permute(0, 2, 1) lgff = lgff.permute(0, 2, 1) local_distmat = low_memory_local_dist(lqff.numpy(), lgff.numpy(), aligned=True) local_qq_distmat = low_memory_local_dist(lqff.numpy(), lqff.numpy(), aligned=True) local_gg_distmat = low_memory_local_dist(lgff.numpy(), lgff.numpy(), aligned=True) local_dist_flipped = np.concatenate([ np.concatenate([local_qq_distmat, local_distmat], axis=1), np.concatenate([local_distmat.T, local_gg_distmat], axis=1) ], axis=0) # for theta in np.arange(0.0,1.0,0.05): # distmat = re_ranking(qf,gf,k1=6,k2=2,lambda_value=0.3,local_distmat=local_dist,theta=theta,only_local=False) # distmat_flip = re_ranking(qff,gff,k1=6,k2=2,lambda_value=0.3,local_distmat=local_dist_flipped,theta=theta,only_local=False) # distmat = distmat + distmat_flip # cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) # logger.info(f"mAP: {mAP:.1%}") # for r in [1, 5, 10]: # logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") # logger.info("Theta:{}; Score: {}".format(theta, (mAP+cmc[0])/2.)) theta = 0.45 distmat = re_ranking(qf, gf, k1=6, k2=2, lambda_value=0.3, local_distmat=local_dist, theta_value=theta, only_local=False) distmat_flip = re_ranking(qff, gff, k1=6, k2=2, lambda_value=0.3, local_distmat=local_dist_flipped, theta_value=theta, only_local=False) distmat = (distmat + distmat_flip) / 2 score = distmat index = np.argsort(score, axis=1) # from small to large cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") logger.info(f"Score: {(mAP + cmc[0]) / 2.:.1%}")
def inference(cfg, model, test_dataloader, num_query, thetas): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") model.eval() feats, pids, camids = [], [], [] local_feats = [] test_prefetcher = data_prefetcher(test_dataloader) batch = test_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): feat = model(img) if isinstance(feat, tuple): feats.append(feat[0]) local_feats.append(feat[1]) else: feats.append(feat) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() feats = torch.cat(feats, dim=0) if len(local_feats) > 0: local_feats = torch.cat(local_feats, dim=0) if cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) if len(local_feats) > 0: local_feats = F.normalize(local_feats, p=2, dim=1) # query qf = feats[:num_query] if len(local_feats) > 0: lqf = local_feats[:num_query] # gallery gf = feats[num_query:] if len(local_feats) > 0: lgf = local_feats[num_query:] if len(local_feats) > 0: # calculate the local distance lqf = lqf.permute(0, 2, 1) lgf = lgf.permute(0, 2, 1) #logger.info('Computing local_qg_distmat ...') local_qg_distmat = low_memory_local_dist(lqf.cpu().numpy(), lgf.cpu().numpy(), aligned=True) #logger.info('Computing local_qq_distmat ...') local_qq_distmat = low_memory_local_dist(lqf.cpu().numpy(), lqf.cpu().numpy(), aligned=True) #logger.info('Computing local_gg_distmat ...') local_gg_distmat = low_memory_local_dist(lgf.cpu().numpy(), lgf.cpu().numpy(), aligned=True) local_distmat = np.concatenate([ np.concatenate([local_qq_distmat, local_qg_distmat], axis=1), np.concatenate([local_qg_distmat.T, local_gg_distmat], axis=1) ], axis=0) else: local_distmat = None use_rerank = True if use_rerank: #thetas = [0.4, 0.5, 0.9, 0.95, 1.0] scores, indices, dist_mats = [], [], [] logger.info("use reranking") for theta in thetas: distmat = re_ranking(qf, gf, k1=6, k2=2, lambda_value=0.3, local_distmat=local_distmat, theta_value=theta) score = distmat index = np.argsort(score, axis=1) # from small to large scores.append(score) indices.append(index) dist_mats.append(distmat) return scores, indices, dist_mats else: logger.info("No reranking") distmat = -torch.mm(qf, gf.t()).cpu().numpy() score = distmat index = np.argsort(score, axis=1) # from small to large return score, index
def inference_aligned(cfg, model, test_dataloader, num_query): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") model.eval() feats, pids, camids = [], [], [] local_feats = [] test_prefetcher = data_prefetcher(test_dataloader) batch = test_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): feat = model(img) #feat = model(torch.flip(img, [3])) if isinstance(feat, tuple): feats.append(feat[0]) local_feats.append(feat[1]) else: feats.append(feat) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() feats = torch.cat(feats, dim=0) if len(local_feats) > 0: local_feats = torch.cat(local_feats, dim=0) if cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) # 局部特征是三维的,不做归一化 (对结果没影响) #if len(local_feats) > 0: # local_feats = F.normalize(local_feats, p=2, dim=1) # query qf = feats[:num_query] if len(local_feats) > 0: lqf = local_feats[:num_query] q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery gf = feats[num_query:] if len(local_feats) > 0: lgf = local_feats[num_query:] g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) if len(local_feats) > 0: #if True: # calculate the local distance lqf = lqf.permute(0, 2, 1) lgf = lgf.permute(0, 2, 1) local_qg_distmat = low_memory_local_dist(lqf.cpu().numpy(), lgf.cpu().numpy(), aligned=True) local_qq_distmat = low_memory_local_dist(lqf.cpu().numpy(), lqf.cpu().numpy(), aligned=True) local_gg_distmat = low_memory_local_dist(lgf.cpu().numpy(), lgf.cpu().numpy(), aligned=True) local_distmat = np.concatenate([ np.concatenate([local_qq_distmat, local_qg_distmat], axis=1), np.concatenate([local_qg_distmat.T, local_gg_distmat], axis=1) ], axis=0) else: local_distmat = None # use reranking logger.info("use reranking") #distmat = re_ranking(qf, gf, k1=14, k2=4, lambda_value=0.4) search_param = False search_theta = True if search_param: best_score = 0 best_param = [] for k1 in range(5, 9): for k2 in range(1, k1): for l in np.linspace(0, 0.5, 11): distmat = re_ranking(qf, gf, k1=k1, k2=k2, lambda_value=l) cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) score = (cmc[0] + mAP) / 2 #logger.info(f"mAP: {mAP:.1%}") print('k1, k2, l', k1, k2, np.around(l, 2), 'r1, mAP, score', np.around(cmc[0], 4), np.around(mAP, 4), np.around(score, 4)) if score > best_score: best_score = score best_param = [k1, k2, l] print('Best Param', best_param) distmat = re_ranking(qf, gf, k1=best_param[0], k2=best_param[1], lambda_value=best_param[2], local_distmat=local_distmat, only_local=False) elif search_theta: best_score = 0 for theta in np.linspace(0, 1.0, 11): distmat = re_ranking(qf, gf, k1=6, k2=2, lambda_value=0.3, local_distmat=local_distmat, theta_value=theta, only_local=False) # (current best) cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) score = (cmc[0] + mAP) / 2 print('theta', theta, 'r1, mAP, score', np.around(cmc[0], 4), np.around(mAP, 4), np.around(score, 4)) if score > best_score: best_score = score best_param = theta print('Best Param', best_param) distmat = re_ranking(qf, gf, k1=6, k2=2, lambda_value=0.3, local_distmat=local_distmat, theta_value=best_param, only_local=False) # (current best) else: distmat = re_ranking(qf, gf, k1=6, k2=2, lambda_value=0.3, local_distmat=local_distmat, only_local=False, theta_value=0.9) #(current best) #distmat = re_ranking(qf, gf, k1=6, k2=2, lambda_value=0.4) # try cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") logger.info(f"Score: {(mAP + cmc[0]) / 2.:.1%}")
def estimate_distance( cfg, model, data_loader, sample_number=None ): model.eval() savedir = os.path.join(cfg.OUTPUT_DIR, '-'.join(cfg.DATASETS.TEST_NAMES), 'estimate_dist') if not os.path.exists(savedir): os.makedirs(savedir) if len(data_loader) > 10: print('Estimate distance on train data...') outfile = open(os.path.join(savedir, cfg.DATASETS.TEST_NAMES[0]+'_train.txt'), 'w') feats, pids, camids, pos_dists, mean_dists, neg_dists = [], [], [], [], [], [] prefetcher = data_prefetcher(data_loader) batch = prefetcher.next() batchi = 0 while batch[0] is not None: print(f'Extracting feature for batch {batchi}') img, pid, camid = batch with torch.no_grad(): logit, feat = model(img) feats.append(feat) pids.extend(pid.cpu().numpy().tolist()) camids.extend(np.asarray(camid)) batch = prefetcher.next() batchi += 1 feats = torch.cat(feats, dim=0) pids = np.asarray(pids) camids = np.asarray(camids) if cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) batchN = feats.shape[0]//cfg.TEST.IMS_PER_BATCH print('batchN : ', batchN+1) for batch_i in range(batchN+1): print(f'Processing batch : {batch_i}') if batch_i != batchN: feats_split = feats[batch_i*cfg.TEST.IMS_PER_BATCH:(batch_i+1)*cfg.TEST.IMS_PER_BATCH] pids_split = pids[batch_i*cfg.TEST.IMS_PER_BATCH:(batch_i+1)*cfg.TEST.IMS_PER_BATCH] camids_split = camids[batch_i*cfg.TEST.IMS_PER_BATCH:(batch_i+1)*cfg.TEST.IMS_PER_BATCH] else: feats_split = feats[batch_i*cfg.TEST.IMS_PER_BATCH:] pids_split = pids[batch_i*cfg.TEST.IMS_PER_BATCH:] camids_split = camids[batch_i*cfg.TEST.IMS_PER_BATCH:] # cosine distance distmat_split = torch.mm(feats_split, feats.t()).cpu().numpy() distmat_split = -distmat_split for sample_i in range(len(pids_split)): dist = -distmat_split[sample_i] pid = pids_split[sample_i] camid = camids_split[sample_i] # remove gallery samples that have the same pid and camid with query positive = (pids == pid) & (camids != camid) negtive = (pids != pid) if not np.any(positive): # this condition is true when query identity does not appear in gallery continue dist_pos = dist[positive] dist_neg = dist[negtive] pos_dists.append(np.max(dist_pos)) neg_dists.append(np.max(dist_neg)) mean_dists.append(np.mean(dist_pos)) item = 0 max_sample = 1000000 if len(pids) > max_sample: sample_rand = random.sample(range(len(pids)), max_sample) for sample_i in sample_rand: outfile.write(f'Item {item:6d} : id = {pids[sample_i]:6d} , pos_dist = {pos_dists[sample_i]:.6f}, mean_dist = {mean_dists[sample_i]:.6f}, neg_dist = {neg_dists[sample_i]:.6f}\n') item += 1 else: for a, b, c, d in zip(pids, pos_dists, mean_dists, neg_dists): outfile.write(f'Item {item:6d} : id = {a:6d} , pos_dist = {b:.6f} , mean_dist = {c:.6f}, neg_dist = {d:.6f}\n') item += 1 else: idx = -1 for test_dataset_name, dataloader, num_query in zip(cfg.DATASETS.TEST_NAMES, data_loader, sample_number): print(f'Estimate distance on test data of {test_dataset_name}') idx += 1 outfile = open(os.path.join(savedir, test_dataset_name+'_test.txt'), 'w') feats, pids, camids, pos_dists, mean_dists, neg_dists = [], [], [], [], [], [] prefetcher = data_prefetcher(dataloader) batch = prefetcher.next() batchi = 0 while batch[0] is not None: print(f'Extracting feature for batch {batchi}') img, pid, camid = batch with torch.no_grad(): logit, feat = model(img) feats.append(feat) pids.extend(pid.cpu().numpy().tolist()) camids.extend(np.asarray(camid)) batch = prefetcher.next() batchi += 1 feats = torch.cat(feats, dim=0) pids = np.asarray(pids) camids = np.asarray(camids) if 'veri' == test_dataset_name: feats = feats[1678:] pids = pids[1678:] camids = camids[1678:] if cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) batchN = feats.shape[0]//cfg.TEST.IMS_PER_BATCH print('batchN : ', batchN+1) for batch_i in range(batchN+1): print(f'Processing batch : {batch_i}') if batch_i != batchN: feats_split = feats[batch_i*cfg.TEST.IMS_PER_BATCH:(batch_i+1)*cfg.TEST.IMS_PER_BATCH] pids_split = pids[batch_i*cfg.TEST.IMS_PER_BATCH:(batch_i+1)*cfg.TEST.IMS_PER_BATCH] camids_split = camids[batch_i*cfg.TEST.IMS_PER_BATCH:(batch_i+1)*cfg.TEST.IMS_PER_BATCH] else: feats_split = feats[batch_i*cfg.TEST.IMS_PER_BATCH:] pids_split = pids[batch_i*cfg.TEST.IMS_PER_BATCH:] camids_split = camids[batch_i*cfg.TEST.IMS_PER_BATCH:] # cosine distance distmat_split = torch.mm(feats_split, feats.t()).cpu().numpy() distmat_split = -distmat_split for sample_i in range(len(pids_split)): dist = -distmat_split[sample_i] pid = pids_split[sample_i] camid = camids_split[sample_i] # remove gallery samples that have the same pid and camid with query positive = (pids == pid) & (camids != camid) negtive = (pids != pid) if not np.any(positive): # this condition is true when query identity does not appear in gallery continue dist_pos = dist[positive] dist_neg = dist[negtive] pos_dists.append(np.max(dist_pos)) neg_dists.append(np.max(dist_neg)) mean_dists.append(np.mean(dist_pos)) item = 0 max_sample = 1000000 if len(pids) > max_sample: sample_rand = random.sample(range(len(pids)), max_sample) for sample_i in sample_rand: outfile.write(f'Item {item:6d} : id = {pids[sample_i]:6d} , pos_dist = {pos_dists[sample_i]:.6f}, mean_dist = {mean_dists[sample_i]:.6f}, neg_dist = {neg_dists[sample_i]:.6f}\n') item += 1 else: for a, b, c, d in zip(pids, pos_dists, mean_dists, neg_dists): outfile.write(f'Item {item:6d} : id = {a:6d} , pos_dist = {b:.6f} , mean_dist = {c:.6f}, neg_dist = {d:.6f}\n') item += 1
def inference_aligned_flipped(cfg, model, test_dataloader, num_query, use_local_feature, use_rerank, use_cross_feature): """ inference an aligned net with flipping and two pairs of global feature and local feature :param cfg: :param model: :param test_dataloader: :param num_query: :return: """ logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing aligned with flipping") model.eval() pids, camids = [], [] gfs, bn_gfs, lfs, bn_lfs = [], [], [], [] gfs_flipped, bn_gfs_flipped, lfs_flipped, bn_lfs_flipped = [], [], [], [] test_prefetcher = data_prefetcher(test_dataloader, cfg) batch = test_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): gf, bn_gf, lf, bn_lf = model(img) gff, bn_gff, lff, bn_lff = model(torch.flip(img, [3])) # 4 features gfs.append(gf.cpu()) bn_gfs.append(bn_gf.cpu()) if use_local_feature: lfs.append(lf.cpu()) bn_lfs.append(bn_lf.cpu()) # 4 features flipped gfs_flipped.append(gff.cpu()) bn_gfs_flipped.append(bn_gff.cpu()) if use_local_feature: lfs_flipped.append(lff.cpu()) bn_lfs_flipped.append(bn_lff.cpu()) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) logger.info( f"use_cross_feature = {use_cross_feature}, use_local_feature = {use_local_feature}, use_rerank = {use_rerank}" ) if use_cross_feature: logger.info("Computing distmat with bn_gf (+ lf)") distmat2 = compute_distmat(cfg, num_query, bn_gfs, bn_gfs_flipped, lfs, lfs_flipped, theta=0.45, use_local_feature=use_local_feature, use_rerank=use_rerank) distmat = distmat2 #distmat = (distmat1 + distmat2) / 2 else: logger.info("Computing distmat with gf + bn_lf") distmat1 = compute_distmat(cfg, num_query, gfs, gfs_flipped, bn_lfs, bn_lfs_flipped, theta=0.95, use_local_feature=use_local_feature, use_rerank=use_rerank) distmat = distmat1 #distmat1 = None #distmat2 = None #distmat = original_distmat #distmat[:, new_gallery_index] = distmat1 - 100 cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") logger.info(f"Score: {(mAP + cmc[0]) / 2.:.1%}")
def estimate_logits( cfg, model, data_loader, sample_number=None ): model.eval() savedir = os.path.join(cfg.OUTPUT_DIR, '-'.join(cfg.DATASETS.TEST_NAMES), 'estimate_logits') if not os.path.exists(savedir): os.makedirs(savedir) if len(data_loader) > 10: print('Estimate logits on train data...') outfile = open(os.path.join(savedir, cfg.DATASETS.TEST_NAMES[0]+'_train.txt'), 'w') logits, feats, pids, camids, probs, max_probs, pred_ids = [], [], [], [], [], [], [] prefetcher = data_prefetcher(data_loader) batch = prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): logit, feat = model(img) # logits.append(logit) prob = F.softmax(logit, dim=1) # probs.append(prob) max_prob, pred_id = torch.max(prob, dim=1) pred_ids.extend(pred_id.cpu().numpy().tolist()) max_probs.extend(max_prob.cpu().numpy().tolist()) pids.extend(pid.cpu().numpy().tolist()) # camids.extend(np.asarray(camid)) batch = prefetcher.next() item = 0 max_sample = 1000000 if len(pids) > max_sample: sample_rand = random.sample(range(len(pids)), max_sample) for sample_i in sample_rand: outfile.write(f'Item {item:6d} : id = {pids[sample_i]:6d} , pred = {pred_ids[sample_i]:6d} , prob = {max_probs[sample_i]:.4f}\n') item += 1 else: for a, b, c in zip(pids, pred_ids, max_probs): # print(f'Item {item:6d} : id = {a:4d} , pred = {b:4d} , prob = {c:.4f}') outfile.write(f'Item {item:6d} : id = {a:6d} , pred = {b:6d} , prob = {c:.4f}\n') item += 1 else: idx = -1 for test_dataset_name, dataloader, num_query in zip(cfg.DATASETS.TEST_NAMES, data_loader, sample_number): print(f'Estimate logits on test data of {test_dataset_name}') idx += 1 outfile = open(os.path.join(savedir, test_dataset_name+'_test.txt'), 'w') logits, feats, pids, camids, probs, max_probs, pred_ids = [], [], [], [], [], [], [] prefetcher = data_prefetcher(dataloader) batch = prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): logit, feat = model(img) # logits.append(logit) prob = F.softmax(logit, dim=1) # probs.append(prob) max_prob, pred_id = torch.max(prob, dim=1) pred_ids.extend(pred_id.cpu().numpy().tolist()) max_probs.extend(max_prob.cpu().numpy().tolist()) pids.extend(pid.cpu().numpy().tolist()) # camids.extend(np.asarray(camid)) batch = prefetcher.next() if 'veri' == test_dataset_name: pred_ids = pred_ids[1678:] pids = pids[1678:] max_probs = max_probs[1678:] item = 0 max_sample = 1000000 if len(pids) > max_sample: sample_rand = random.sample(range(len(pids)), max_sample) for sample_i in sample_rand: outfile.write(f'Item {item:6d} : id = {pids[sample_i]:6d} , pred = {pred_ids[sample_i]:6d} , prob = {max_probs[sample_i]:.4f}\n') item += 1 else: for a, b, c in zip(pids, pred_ids, max_probs): # print(f'Item {item:6d} : id = {a:4d} , pred = {b:4d} , prob = {c:.4f}') outfile.write(f'Item {item:6d} : id = {a:6d} , pred = {b:6d} , prob = {c:.4f}\n') item += 1
def inference(cfg, model, test_dataloader, num_query): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") model.eval() feats, pids, camids = [], [], [] #local_feats = [] test_prefetcher = data_prefetcher(test_dataloader, cfg) batch = test_prefetcher.next() while batch[0] is not None: img, pid, camid = batch with torch.no_grad(): feat = model(img) #feat = model(torch.flip(img, [3])) if isinstance(feat, tuple): feats.append(feat[0]) #local_feats.append(feat[1]) else: feats.append(feat) pids.extend(pid.cpu().numpy()) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() feats = torch.cat(feats, dim=0) if cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) # query qf = feats[:num_query] q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery gf = feats[num_query:] g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) local_distmat = None # use reranking logger.info("use reranking") #distmat = re_ranking(qf, gf, k1=14, k2=4, lambda_value=0.4) search_param = False if search_param: best_score = 0 best_param = [] for k1 in range(5, 9): for k2 in range(1, k1): for l in np.linspace(0, 0.5, 11): distmat = re_ranking(qf, gf, k1=k1, k2=k2, lambda_value=l) cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) score = (cmc[0] + mAP) / 2 #logger.info(f"mAP: {mAP:.1%}") print('k1, k2, l', k1, k2, np.around(l, 2), 'r1, mAP, score', np.around(cmc[0], 4), np.around(mAP, 4), np.around(score, 4)) if score > best_score: best_score = score best_param = [k1, k2, l] print('Best Param', best_param) distmat = re_ranking(qf, gf, k1=best_param[0], k2=best_param[1], lambda_value=best_param[2], local_distmat=local_distmat, only_local=False) else: distmat = re_ranking(qf, gf, k1=6, k2=2, lambda_value=0.3, local_distmat=local_distmat, only_local=False, theta_value=0.9) #(current best) #distmat = re_ranking(qf, gf, k1=6, k2=2, lambda_value=0.4) # try cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids) logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") logger.info(f"Score: {(mAP + cmc[0]) / 2.:.1%}")
def inference(cfg, model, train_dataloader, test_dataloader, num_query): logger = logging.getLogger("reid_baseline.inference") logger.info("Start inferencing") logger.info("compute precise batchnorm ...") # model.train() # update_bn_stats(model, train_dataloader, num_iters=300) model.eval() cat_feats, feats, pids, camids = [], [], [], [] test_prefetcher = data_prefetcher(test_dataloader) batch = test_prefetcher.next() while batch[0] is not None: img, pid, camid = batch cat_feat, feat = model(img) cat_feats.append(cat_feat.cpu()) feats.append(feat.cpu()) pids.extend(np.asarray(pid.cpu().numpy())) camids.extend(np.asarray(camid)) batch = test_prefetcher.next() feats = torch.cat(feats, dim=0) cat_feats = torch.cat(cat_feats, dim=0) if cfg.TEST.NORM: feats = F.normalize(feats, p=2, dim=1) cat_feats = F.normalize(cat_feats, p=2, dim=1) # query cat_qf = cat_feats[:num_query] qf = feats[:num_query] q_pids = np.asarray(pids[:num_query]) q_camids = np.asarray(camids[:num_query]) # gallery cat_gf = cat_feats[num_query:] gf = feats[num_query:] g_pids = np.asarray(pids[num_query:]) g_camids = np.asarray(camids[num_query:]) # cosine distance cat_dist = torch.mm(cat_qf, cat_gf.t()) distmat = torch.mm(qf, gf.t()) # IIA post fusion strategy for all query and gallery # qf = qf # gf = gf # m = qf.shape[0] # n = gf.shape[0] # distmat = torch.zeros((m, n)).to(qf) # for i, q_f in enumerate(qf): # print(i) # D = torch.cat([q_f[None, :], gf], dim=0) # [1+g, 2048] # S = torch.mm(D, D.t()) # [1+g, 1+g] # for _ in range(5): # S = S - torch.eye(S.shape[0]).to(S) # s_v, s_i = torch.topk(S, 10, dim=1) # s_v = F.softmax(s_v, dim=1) # s = torch.zeros((S.size()[0], S.size()[0])).to(qf) # [1+g, 1+g] # for j in range(s_i.shape[0]): # s[j, s_i[j]] = s_v[j] # u = 0.8 * torch.eye(S.size()[0]).to(s) + 0.2 * s # D = torch.mm(u, D) # S = torch.mm(D, D.t()) # distmat[i] = S[0][1:] cmc, mAP = evaluate(1 - distmat.numpy(), q_pids, g_pids, q_camids, g_camids) logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}") cmc, mAP = evaluate(1 - cat_dist.numpy(), q_pids, g_pids, q_camids, g_camids) logger.info('cat feature') logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r - 1]:.1%}")