def main(args): np.random.seed(args.seed) torch.manual_seed(args.seed) cudnn.benchmark = True # Create data loaders assert args.num_instances > 1, "num_instances should be greater than 1" assert args.batch_size % args.num_instances == 0, \ 'num_instances should divide batch_size' if args.height is None or args.width is None: args.height, args.width = (144, 56) if args.arch == 'inception' else \ (256, 128) # get source data src_dataset, src_extfeat_loader = \ get_source_data(args.src_dataset, args.data_dir, args.height, args.width, args.batch_size, args.workers) # get target data tgt_dataset, num_classes, tgt_extfeat_loader, test_loader = \ get_data(args.tgt_dataset, args.data_dir, args.height, args.width, args.batch_size, args.workers) # Create model # Hacking here to let the classifier be the number of source ids if args.src_dataset == 'dukemtmc': model = models.create(args.arch, num_classes=632, pretrained=False) elif args.src_dataset == 'market1501': model = models.create(args.arch, num_classes=676, pretrained=False) else: raise RuntimeError('Please specify the number of classes (ids) of the network.') # Load from checkpoint if args.resume: print('Resuming checkpoints from finetuned model on another dataset...\n') checkpoint = load_checkpoint(args.resume) model.load_state_dict(checkpoint['state_dict'], strict=False) else: raise RuntimeWarning('Not using a pre-trained model.') model = nn.DataParallel(model).cuda() # evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) # if args.evaluate: return # Criterion criterion = [ # TripletLoss(args.margin, args.num_instances, isAvg=True, use_semi=True).cuda(), SortedTripletLoss(args.margin, isAvg=True).cuda(), # HoughTripletLoss(args.margin, args.num_instances, isAvg=True, use_semi=True).cuda(), # None, None, None, None ] # Optimizer optimizer = torch.optim.Adam( model.parameters(), lr=args.lr ) # training stage transformer on input images normalizer = T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) train_transformer = T.Compose([ T.Resize((args.height,args.width)), T.RandomHorizontalFlip(), T.ToTensor(), normalizer, T.RandomErasing(probability=0.5, sh=0.2, r1=0.3) ]) evaluator = Evaluator(model, print_freq=args.print_freq) evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) st_model = ST_Model(tgt_dataset.meta['num_cameras']) same = None # train_loader2 = None best_mAP = 0 # # Start training for iter_n in range(args.iteration): if args.lambda_value == 0: source_features = 0 else: # get source datas' feature source_features, _ = extract_features(model, src_extfeat_loader, print_freq=args.print_freq) # synchronization feature order with src_dataset.train source_features = torch.cat([source_features[f].unsqueeze(0) for f, _, _, _ in src_dataset.train], 0) # extract training images' features print('Iteration {}: Extracting Target Dataset Features...'.format(iter_n+1)) target_features, tarNames = extract_features(model, tgt_extfeat_loader, print_freq=args.print_freq) # synchronization feature order with dataset.train target_features = torch.cat([target_features[f].unsqueeze(0) for f, _, _, _ in tgt_dataset.trainval], 0) # target_real_label = np.asarray([tarNames[f].unsqueeze(0) for f, _, _, _ in tgt_dataset.trainval]) target_features = target_features.numpy() rerank_dist = re_ranking(source_features, target_features, lambda_value=args.lambda_value) ranking = np.argsort(rerank_dist)[:, 1:] if iter_n != 0: st_dist = np.zeros(rerank_dist.shape) for i, (_, _, c1, t1) in enumerate(tgt_dataset.trainval): for j, (_, _, c2, t2) in enumerate(tgt_dataset.trainval): if not same.in_peak(c1, c2, t1, t2, 0.25): st_dist[i, j] = 1 rerank_dist = rerank_dist + st_dist * 10 # if iter_n > 0: # rerank_dist = st_model.apply(rerank_dist, tgt_dataset.trainval, tgt_dataset.trainval) cluster = HDBSCAN(metric='precomputed', min_samples=10) # select & cluster images as training set of this epochs clusterRes = cluster.fit(rerank_dist.astype(np.float64)) labels, label_num = clusterRes.labels_, clusterRes.labels_.max() + 1 centers = np.zeros((label_num, target_features.shape[1])) nums = [0] * target_features.shape[1] print('clusters num =', label_num) # generate new dataset new_dataset = [] index = -1 for (fname, _, cam, timestamp), label in zip(tgt_dataset.trainval, labels): index += 1 if label == -1: continue # dont need to change codes in trainer.py _parsing_input function and sampler function after add 0 new_dataset.append((fname, label, cam, timestamp)) centers[label] += target_features[index] nums[label] += 1 print('Iteration {} have {} training images'.format(iter_n+1, len(new_dataset))) # learn ST model # if iter_n % 2 == 0: # if iter_n == 0: # cluster = HDBSCAN(metric='precomputed', min_samples=10) # # select & cluster images as training set of this epochs # clusterRes = cluster.fit(rerank_dist.astype(np.float64)) # labels, label_num = clusterRes.labels_, clusterRes.labels_.max() + 1 # centers = np.zeros((label_num, target_features.shape[1])) # nums = [0] * target_features.shape[1] # print('clusters num =', label_num) # # # generate new dataset # new_dataset = [] # index = -1 # for (fname, _, cam, timestamp), label in zip(tgt_dataset.trainval, labels): # index += 1 # if label == -1: continue # # dont need to change codes in trainer.py _parsing_input function and sampler function after add 0 # new_dataset.append((fname, label, cam, timestamp)) # centers[label] += target_features[index] # nums[label] += 1 # print('Iteration {} have {} training images'.format(iter_n + 1, len(new_dataset))) # same, _ = st_model.fit(new_dataset) # st_model.fit(tgt_dataset.trainval) same, _ = st_model.fit(new_dataset) train_loader = DataLoader( Preprocessor(new_dataset, root=tgt_dataset.images_dir, transform=train_transformer), batch_size=args.batch_size, num_workers=4, sampler=RandomIdentitySampler(new_dataset, args.num_instances), pin_memory=True, drop_last=True ) def filter(i, j): _, _, c1, t1 = tgt_dataset.trainval[i] _, _, c2, t2 = tgt_dataset.trainval[j] return st_model.val(c1, c2, t1, t2) > 0.01 # if iter_n == 0: # ranking = np.argsort(rerank_dist)[:, 1:] # dukemtmc # cluster_size = 23.535612535612536 # market1501 cluster_size = 17.22503328894807 must_conn = int(cluster_size / 2) might_conn = int(cluster_size * 2) length = len(tgt_dataset.trainval) pos = [[] for _ in range(length)] neg = [[] for _ in range(length)] for i in range(length): for j_ in range(might_conn): j = ranking[i][j_] if j_ < must_conn and i in ranking[j][:must_conn]: pos[i].append(j) elif i in ranking[j][:might_conn] and filter(i, j): pos[i].append(j) else: neg[i].append(j) # pos[i] = pos[i][-1:] # neg[i] = neg[i][:1] SP, SF, DP, DF = 0, 0, 0, 0 for i in range(length): for j in pos[i]: if tgt_dataset.trainval[i][1] == tgt_dataset.trainval[j][1]: SP += 1 else: SF += 1 for j in neg[i]: if tgt_dataset.trainval[i][1] == tgt_dataset.trainval[j][1]: DP += 1 else: DF += 1 print('stat: %.1f %.1f %.3f, %.3f' % ((SP + SF) / length, (DP + DF) / length, SP / (SP + SF), DF / (DP + DF))) train_loader2 = DataLoader( Preprocessor(tgt_dataset.trainval, root=tgt_dataset.images_dir, transform=train_transformer), batch_size=args.batch_size, num_workers=4, # sampler=RandomIdentitySampler(new_dataset, args.num_instances), # shuffle=True, sampler=TripletSampler(tgt_dataset.trainval, pos, neg), pin_memory=True, drop_last=True ) # learn visual model for i in range(label_num): centers[i] /= nums[i] criterion[3] = ClassificationLoss(normalize(centers, axis=1)).cuda() classOptimizer = torch.optim.Adam([ {'params': model.parameters()}, {'params': criterion[3].classifier.parameters(), 'lr': 1e-3} ], lr=args.lr) # trainer = HoughTrainer(model, st_model, train_loader, criterion, classOptimizer) trainer = ClassificationTrainer(model, train_loader, criterion, classOptimizer) trainer2 = Trainer(model, train_loader2, criterion, optimizer) for epoch in range(args.epochs): trainer.train(epoch) if epoch % 8 == 0: trainer2.train(epoch) # evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) rank_score = evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) if rank_score.map > best_mAP: best_mAP = rank_score.map save_checkpoint({ 'state_dict': model.module.state_dict(), 'epoch': epoch + 1, 'best_top1': rank_score.market1501[0], }, True, fpath=osp.join(args.logs_dir, 'adapted.pth.tar')) # Evaluate rank_score = evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) save_checkpoint({ 'state_dict': model.module.state_dict(), 'epoch': epoch + 1, 'best_top1': rank_score.market1501[0], }, False, fpath=osp.join(args.logs_dir, 'adapted.pth.tar')) return (rank_score.map, rank_score.market1501[0])
def main(args): np.random.seed(args.seed) torch.manual_seed(args.seed) cudnn.benchmark = True # Create data loaders assert args.num_instances > 1, "num_instances should be greater than 1" assert args.batch_size % args.num_instances == 0, \ 'num_instances should divide batch_size' if args.height is None or args.width is None: args.height, args.width = (144, 56) if args.arch == 'inception' else \ (256, 128) # get source data src_dataset, src_extfeat_loader = \ get_source_data(args.src_dataset, args.data_dir, args.height, args.width, args.batch_size, args.workers) # get target data tgt_dataset, num_classes, tgt_extfeat_loader, test_loader = \ get_data(args.tgt_dataset, args.data_dir, args.height, args.width, args.batch_size, args.workers) # Create model # Hacking here to let the classifier be the number of source ids if args.src_dataset == 'dukemtmc': model = models.create(args.arch, num_classes=632, pretrained=False) elif args.src_dataset == 'market1501': model = models.create(args.arch, num_classes=676, pretrained=False) else: raise RuntimeError( 'Please specify the number of classes (ids) of the network.') # Load from checkpoint if args.resume: print( 'Resuming checkpoints from finetuned model on another dataset...\n' ) checkpoint = load_checkpoint(args.resume) model.load_state_dict(checkpoint['state_dict'], strict=False) else: raise RuntimeWarning('Not using a pre-trained model.') model = nn.DataParallel(model).cuda() # Distance metric metric = DistanceMetric(algorithm=args.dist_metric) # Evaluator evaluator = Evaluator(model, print_freq=args.print_freq) print( "Test with the original model trained on target domain (direct transfer):" ) evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) if args.evaluate: return # Criterion criterion = [ TripletLoss(args.margin, args.num_instances).cuda(), TripletLoss(args.margin, args.num_instances).cuda(), ] # Optimizer optimizer = torch.optim.SGD( model.parameters(), lr=args.lr, momentum=0.9, ) # training stage transformer on input images normalizer = T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) train_transformer = T.Compose([ T.Resize((args.height, args.width)), T.RandomHorizontalFlip(), T.ToTensor(), normalizer, T.RandomErasing(probability=0.5, sh=0.2, r1=0.3) ]) # Start training for iter_n in range(args.iteration): if args.lambda_value == 0: source_features = 0 else: # get source datas' feature source_features, _ = extract_features(model, src_extfeat_loader, print_freq=args.print_freq) # synchronization feature order with src_dataset.train source_features = torch.cat([ source_features[f].unsqueeze(0) for f, _, _ in src_dataset.train ], 0) # extract training images' features print('Iteration {}: Extracting Target Dataset Features...'.format( iter_n + 1)) target_features, _ = extract_features(model, tgt_extfeat_loader, print_freq=args.print_freq) # synchronization feature order with dataset.train target_features = torch.cat([ target_features[f].unsqueeze(0) for f, _, _ in tgt_dataset.trainval ], 0) # calculate distance and rerank result print('Calculating feature distances...') target_features = target_features.numpy() rerank_dist = re_ranking(source_features, target_features, lambda_value=args.lambda_value) if iter_n == 0: # DBSCAN cluster tri_mat = np.triu(rerank_dist, 1) # tri_mat.dim=2 tri_mat = tri_mat[np.nonzero(tri_mat)] # tri_mat.dim=1 tri_mat = np.sort(tri_mat, axis=None) top_num = np.round(args.rho * tri_mat.size).astype(int) eps = tri_mat[:top_num].mean() print('eps in cluster: {:.3f}'.format(eps)) cluster = DBSCAN(eps=eps, min_samples=4, metric='precomputed', n_jobs=8) # select & cluster images as training set of this epochs print('Clustering and labeling...') labels = cluster.fit_predict(rerank_dist) num_ids = len(set(labels)) - 1 print('Iteration {} have {} training ids'.format(iter_n + 1, num_ids)) # generate new dataset new_dataset = [] for (fname, _, _), label in zip(tgt_dataset.trainval, labels): if label == -1: continue # dont need to change codes in trainer.py _parsing_input function and sampler function after add 0 new_dataset.append((fname, label, 0)) print('Iteration {} have {} training images'.format( iter_n + 1, len(new_dataset))) train_loader = DataLoader(Preprocessor(new_dataset, root=tgt_dataset.images_dir, transform=train_transformer), batch_size=args.batch_size, num_workers=4, sampler=RandomIdentitySampler( new_dataset, args.num_instances), pin_memory=True, drop_last=True) # train model with new generated dataset trainer = Trainer(model, criterion, print_freq=args.print_freq) evaluator = Evaluator(model, print_freq=args.print_freq) # Start training for epoch in range(args.epochs): trainer.train(epoch, train_loader, optimizer) # Evaluate rank_score = evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) return (rank_score.map, rank_score.market1501[0])
def main(args): np.random.seed(args.seed) torch.manual_seed(args.seed) cudnn.benchmark = True # Create data loaders assert args.num_instances > 1, "num_instances should be greater than 1" assert args.batch_size % args.num_instances == 0, \ 'num_instances should divide batch_size' if args.height is None or args.width is None: args.height, args.width = (144, 56) if args.arch == 'inception' else \ (256, 128) # get source data src_dataset, src_extfeat_loader = \ get_source_data(args.src_dataset, args.data_dir, args.height, args.width, args.batch_size, args.workers) # get target data tgt_dataset, num_classes, tgt_extfeat_loader, test_loader = \ get_data(args.tgt_dataset, args.data_dir, args.height, args.width, args.batch_size, args.workers) # Create model # Hacking here to let the classifier be the number of source ids if args.src_dataset == 'dukemtmc': model = models.create(args.arch, num_classes=632, pretrained=False) elif args.src_dataset == 'market1501': model = models.create(args.arch, num_classes=676, pretrained=False) else: raise RuntimeError( 'Please specify the number of classes (ids) of the network.') # Load from checkpoint if args.resume: print( 'Resuming checkpoints from finetuned model on another dataset...\n' ) checkpoint = load_checkpoint(args.resume) model.load_state_dict(checkpoint['state_dict'], strict=False) else: raise RuntimeWarning('Not using a pre-trained model.') model = nn.DataParallel(model).cuda() # Criterion criterion = [ TripletLoss(args.margin, args.num_instances, use_semi=False).cuda(), TripletLoss(args.margin, args.num_instances, use_semi=False).cuda() ] optimizer = torch.optim.Adam(model.parameters(), lr=args.lr) # training stage transformer on input images normalizer = T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) train_transformer = T.Compose([ T.Resize((args.height, args.width)), T.RandomHorizontalFlip(), T.ToTensor(), normalizer, T.RandomErasing(probability=0.5, sh=0.2, r1=0.3) ]) # # Start training for iter_n in range(args.iteration): if args.lambda_value == 0: source_features = 0 else: # get source datas' feature source_features, _ = extract_features(model, src_extfeat_loader, print_freq=args.print_freq) # synchronization feature order with src_dataset.train source_features = torch.cat([ source_features[f].unsqueeze(0) for f, _, _ in src_dataset.train ], 0) # extract training images' features print('Iteration {}: Extracting Target Dataset Features...'.format( iter_n + 1)) target_features, _ = extract_features(model, tgt_extfeat_loader, print_freq=args.print_freq) # synchronization feature order with dataset.train target_features = torch.cat([ target_features[f].unsqueeze(0) for f, _, _ in tgt_dataset.trainval ], 0) # calculate distance and rerank result print('Calculating feature distances...') target_features = target_features.numpy() rerank_dist = re_ranking(source_features, target_features, lambda_value=args.lambda_value) if iter_n == 0: # DBSCAN cluster tri_mat = np.triu(rerank_dist, 1) # tri_mat.dim=2 tri_mat = tri_mat[np.nonzero(tri_mat)] # tri_mat.dim=1 tri_mat = np.sort(tri_mat, axis=None) top_num = np.round(args.rho * tri_mat.size).astype(int) eps = tri_mat[:top_num].mean() print('eps in cluster: {:.3f}'.format(eps)) cluster = DBSCAN(eps=eps, min_samples=4, metric='precomputed', n_jobs=8) # select & cluster images as training set of this epochs print('Clustering and labeling...') labels = cluster.fit_predict(rerank_dist) num_ids = len(set(labels)) - 1 print('Iteration {} have {} training ids'.format(iter_n + 1, num_ids)) # generate new dataset new_dataset = [] # assign label for target ones newLab = labelNoise(torch.from_numpy(target_features), torch.from_numpy(labels)) # unknownFeats = target_features[labels==-1,:] counter = 0 from collections import defaultdict realIDs, fakeIDs = defaultdict(list), [] for (fname, realID, cam), label in zip(tgt_dataset.trainval, newLab): # dont need to change codes in trainer.py _parsing_input function and sampler function after add 0 new_dataset.append((fname, label, cam)) realIDs[realID].append(counter) fakeIDs.append(label) counter += 1 precision, recall, fscore = calScores(realIDs, np.asarray(fakeIDs)) print('Iteration {} have {} training images'.format( iter_n + 1, len(new_dataset))) print( f'precision:{precision * 100}, recall:{100 * recall}, fscore:{fscore}' ) train_loader = DataLoader(Preprocessor(new_dataset, root=tgt_dataset.images_dir, transform=train_transformer), batch_size=args.batch_size, num_workers=4, sampler=RandomIdentitySampler( new_dataset, args.num_instances), pin_memory=True, drop_last=True) trainer = Trainer(model, criterion) # Start training for epoch in range(args.epochs): trainer.train(epoch, train_loader, optimizer) # to at most 80% # test only evaluator = Evaluator(model, print_freq=args.print_freq) # rank_score = evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) # Evaluate rank_score = evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) save_checkpoint( { 'state_dict': model.module.state_dict(), 'epoch': epoch + 1, 'best_top1': rank_score.market1501[0], }, True, fpath=osp.join(args.logs_dir, 'adapted.pth.tar')) return rank_score.map, rank_score.market1501[0]
def main(args): np.random.seed(args.seed) torch.manual_seed(args.seed) cudnn.benchmark = True # Create data loaders assert args.num_instances > 1, "num_instances should be greater than 1" assert args.batch_size % args.num_instances == 0, \ 'num_instances should divide batch_size' if args.height is None or args.width is None: args.height, args.width = (144, 56) if args.arch == 'inception' else \ (256, 128) # get source data src_dataset, src_extfeat_loader = \ get_source_data(args.src_dataset, args.data_dir, args.height, args.width, args.batch_size, args.workers) # get target data tgt_dataset, num_classes, tgt_extfeat_loader, test_loader = \ get_data(args.tgt_dataset, args.data_dir, args.height, args.width, args.batch_size, args.workers) # Create model # Hacking here to let the classifier be the number of source ids if args.src_dataset == 'dukemtmc': model = models.create(args.arch, num_classes=632, pretrained=False) elif args.src_dataset == 'market1501': model = models.create(args.arch, num_classes=676, pretrained=False) elif args.src_dataset == 'msmt17': model = models.create(args.arch, num_classes=1041, pretrained=False) elif args.src_dataset == 'cuhk03': model = models.create(args.arch, num_classes=1230, pretrained=False) else: raise RuntimeError( 'Please specify the number of classes (ids) of the network.') # Load from checkpoint if args.resume: print( 'Resuming checkpoints from finetuned model on another dataset...\n' ) checkpoint = load_checkpoint(args.resume) model.load_state_dict(checkpoint['state_dict'], strict=False) else: raise RuntimeWarning('Not using a pre-trained model.') model = nn.DataParallel(model).cuda() evaluator = Evaluator(model, print_freq=args.print_freq) evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) # if args.evaluate: return # Criterion criterion = [ HoughTripletLoss(args.margin, args.num_instances, isAvg=False, use_semi=False).cuda(), HoughTripletLoss(args.margin, args.num_instances, isAvg=False, use_semi=False).cuda() ] # Optimizer optimizer = torch.optim.Adam(model.parameters(), lr=args.lr) # training stage transformer on input images normalizer = T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) train_transformer = T.Compose([ T.Resize((args.height, args.width)), T.RandomHorizontalFlip(), T.ToTensor(), normalizer, T.RandomErasing(probability=0.5, sh=0.2, r1=0.3) ]) # # Start training for iter_n in range(args.iteration): if args.lambda_value == 0: source_features = 0 else: # get source datas' feature source_features, _ = extract_features(model, src_extfeat_loader, print_freq=args.print_freq) # synchronization feature order with src_dataset.train source_features = torch.cat([ source_features[f].unsqueeze(0) for f, _, _, _ in src_dataset.train ], 0) # extract training images' features print('Iteration {}: Extracting Target Dataset Features...'.format( iter_n + 1)) target_features, _ = extract_features(model, tgt_extfeat_loader, print_freq=args.print_freq) # synchronization feature order with dataset.train target_features = torch.cat([ target_features[f].unsqueeze(0) for f, _, _, _ in tgt_dataset.trainval ], 0) # calculate distance and rerank result print('Calculating feature distances...') target_features = target_features.numpy() rerank_dist = re_ranking(source_features, target_features, lambda_value=args.lambda_value) if iter_n == 0: # DBSCAN cluster tri_mat = np.triu(rerank_dist, 1) # tri_mat.dim=2 tri_mat = tri_mat[np.nonzero(tri_mat)] # tri_mat.dim=1 tri_mat = np.sort(tri_mat, axis=None) top_num = np.round(args.rho * tri_mat.size).astype(int) eps = tri_mat[:top_num].mean() print('eps in cluster: {:.3f}'.format(eps)) cluster = DBSCAN(eps=eps, min_samples=4, metric='precomputed', n_jobs=8) # select & cluster images as training set of this epochs print('Clustering and labeling...') labels = cluster.fit_predict(rerank_dist) num_ids = len(set(labels)) - 1 print('Iteration {} have {} training ids'.format(iter_n + 1, num_ids)) # generate new dataset new_dataset, unknown_dataset = [], [] # assign label for target ones unknownLab = labelNoise(torch.from_numpy(target_features), torch.from_numpy(labels)) # unknownFeats = target_features[labels==-1,:] unCounter, index = 0, 0 from collections import defaultdict realIDs, fakeIDs = defaultdict(list), [] record_labels = {} hough = Hough(8, 40, 230, 2935, 25, args.short_cut) for (fname, realPID, cam, timestamp), label in zip(tgt_dataset.trainval, labels): if label == -1: unknown_dataset.append((fname, int(unknownLab[unCounter]), cam, timestamp)) # unknown data fakeIDs.append(int(unknownLab[unCounter])) realIDs[realPID].append(index) unCounter += 1 index += 1 continue # dont need to change codes in trainer.py _parsing_input function and sampler function after add 0 if label not in record_labels: record_labels[label] = [] for index2 in record_labels[label]: hough.update(cam, tgt_dataset.trainval[index2][2], timestamp, tgt_dataset.trainval[index2][3]) record_labels[label].append(index) new_dataset.append((fname, label, cam, timestamp)) fakeIDs.append(label) realIDs[realPID].append(index) index += 1 print('Iteration {} have {} training images'.format( iter_n + 1, len(new_dataset))) precision, recall, fscore = calScores( realIDs, np.asarray(fakeIDs)) # fakeIDs does not contain -1 print('precision:{}, recall:{}, fscore: {}'.format( 100 * precision, 100 * recall, fscore)) T_pseu, TP_pseu, T_gt, TP_gt, index = (0, 0, 0, 0, -1) for (fname, realPID, cam, timestamp), label in zip(tgt_dataset.trainval, labels): index += 1 # calc by gt label T_gt = T_gt + len(realIDs[realPID]) - 1 for index2 in realIDs[realPID]: if index2 == index: continue if hough.on_peak(cam, tgt_dataset.trainval[index2][2], timestamp, tgt_dataset.trainval[index2][3]): TP_gt += 1 # calc by pseudo label if label == -1: continue T_pseu = T_pseu + len(record_labels[label]) - 1 for index2 in record_labels[label]: if index2 == index: continue if hough.on_peak(cam, tgt_dataset.trainval[index2][2], timestamp, tgt_dataset.trainval[index2][3]): TP_pseu += 1 print('gt label: T = %d, TP = %d, recall = %f' % (T_gt, TP_gt, TP_pseu / T_gt)) print('pseudo label: T = %d, TP = %d, recall = %f' % (T_pseu, TP_pseu, TP_pseu / T_pseu)) train_loader = DataLoader(Preprocessor(new_dataset, root=tgt_dataset.images_dir, transform=train_transformer), batch_size=args.batch_size, num_workers=4, sampler=RandomIdentitySampler( new_dataset, args.num_instances), pin_memory=True, drop_last=True) # hard samples # noiseImgs = [name[1] for name in unknown_dataset] # saveAll(noiseImgs, tgt_dataset.images_dir, 'noiseImg') # import ipdb; ipdb.set_trace() unLoader = DataLoader(Preprocessor(unknown_dataset, root=tgt_dataset.images_dir, transform=train_transformer), batch_size=args.batch_size, num_workers=4, sampler=RandomIdentitySampler( unknown_dataset, args.num_instances), pin_memory=True, drop_last=True) # train model with new generated dataset trainer1 = HoughTrainer(model, hough, train_loader, criterion, optimizer) trainer2 = HoughTrainer(model, hough, unLoader, criterion, optimizer) # Start training for epoch in range(args.epochs): trainer1.train(epoch) trainer2.train(epoch) # test only rank_score = evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) # print('co-model:\n') # rank_score = evaluatorB.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) # Evaluate rank_score = evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) save_checkpoint( { 'state_dict': model.module.state_dict(), 'epoch': epoch + 1, 'best_top1': rank_score.market1501[0], }, True, fpath=osp.join(args.logs_dir, 'asyCo.pth')) return rank_score.map, rank_score.market1501[0]
def main(args): np.random.seed(args.seed) torch.manual_seed(args.seed) cudnn.benchmark = True # Create data loaders assert args.num_instances > 1, "num_instances should be greater than 1" assert args.batch_size % args.num_instances == 0, \ 'num_instances should divide batch_size' if args.height is None or args.width is None: args.height, args.width = (144, 56) if args.arch == 'inception' else \ (256, 128) # get source data src_dataset, src_extfeat_loader = \ get_source_data(args.src_dataset, args.data_dir, args.height, args.width, args.batch_size, args.workers) # get target data tgt_dataset, num_classes, tgt_extfeat_loader, test_loader = \ get_data(args.tgt_dataset, args.data_dir, args.height, args.width, args.batch_size, args.workers) # Create model # Hacking here to let the classifier be the number of source ids if args.src_dataset == 'dukemtmc': model = models.create(args.arch, num_classes=632, pretrained=False) elif args.src_dataset == 'market1501': model = models.create(args.arch, num_classes=676, pretrained=False) else: raise RuntimeError( 'Please specify the number of classes (ids) of the network.') # Load from checkpoint if args.resume: print( 'Resuming checkpoints from finetuned model on another dataset...\n' ) checkpoint = load_checkpoint(args.resume) model.load_state_dict(checkpoint['state_dict'], strict=False) else: raise RuntimeWarning('Not using a pre-trained model.') model = nn.DataParallel(model).cuda() # Distance metric # metric = DistanceMetric(algorithm=args.dist_metric) # Evaluator evaluator = Evaluator(model, print_freq=args.print_freq) print( "Test with the original model trained on source domain (direct transfer):" ) rank_score_best = evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) best_map = rank_score_best.map #market1501[0]-->rank-1 if args.evaluate: return # Criterion criterion = [ TripletLoss(args.margin, args.num_instances).cuda(), TripletLoss(args.margin, args.num_instances).cuda(), AccumulatedLoss(args.margin, args.num_instances).cuda(), nn.CrossEntropyLoss().cuda() ] # Optimizer optimizer = torch.optim.SGD( model.parameters(), lr=args.lr, momentum=0.9, ) # training stage transformer on input images normalizer = T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) train_transformer = T.Compose([ T.Resize((args.height, args.width)), T.RandomHorizontalFlip(), T.ToTensor(), normalizer, T.RandomErasing(probability=0.5, sh=0.2, r1=0.3) ]) # Start training for iter_n in range(args.iteration): if args.lambda_value == 0: source_features = 0 #this value controls the usage of source data else: # get source datas' feature source_features, _ = extract_features(model, src_extfeat_loader, print_freq=args.print_freq) # synchronization feature order with src_dataset.train source_features = torch.cat([ source_features[f].unsqueeze(0) for f, _, _ in src_dataset.train ], 0) # extract training images' features print('Iteration {}: Extracting Target Dataset Features...'.format( iter_n + 1)) target_features, _ = extract_features(model, tgt_extfeat_loader, print_freq=args.print_freq) # synchronization feature order with dataset.train target_features = torch.cat([ target_features[f].unsqueeze(0) for f, _, _ in tgt_dataset.trainval ], 0) # calculate distance and rerank result print('Calculating feature distances...') target_features = target_features.numpy() rerank_dist = re_ranking(source_features, target_features, lambda_value=args.lambda_value) if iter_n == 0: # DBSCAN cluster tri_mat = np.triu(rerank_dist, 1) # tri_mat.dim=2 tri_mat = tri_mat[np.nonzero(tri_mat)] # tri_mat.dim=1 tri_mat = np.sort(tri_mat, axis=None) top_num = np.round(args.rho * tri_mat.size).astype(int) eps = tri_mat[:top_num].mean() print('eps in cluster: {:.3f}'.format(eps)) cluster = DBSCAN(eps=eps, min_samples=4, metric='precomputed', n_jobs=8) # HDBSCAN cluster import hdbscan cluster_hdbscan = hdbscan.HDBSCAN(min_cluster_size=10, min_samples=4, metric='precomputed') # select & cluster images as training set of this epochs print('Clustering and labeling...') if args.use_hdbscan_clustering: print( 'Use the better chlustering algorithm HDBSCAN for clustering' ) labels = cluster_hdbscan.fit_predict(rerank_dist) else: print('Use DBSCAN for clustering') labels = cluster.fit_predict(rerank_dist) num_ids = len(set(labels)) - 1 print('Only do once, Iteration {} have {} training ids'.format( iter_n + 1, num_ids)) # generate new dataset new_dataset = [] for (fname, _, _), label in zip(tgt_dataset.trainval, labels): if label == -1: continue # dont need to change codes in trainer.py _parsing_input function and sampler function after add 0 new_dataset.append((fname, label, 0)) print('Only do once, Iteration {} have {} training images'.format( iter_n + 1, len(new_dataset))) train_loader = DataLoader( Preprocessor_return_index(new_dataset, root=tgt_dataset.images_dir, transform=train_transformer), batch_size=args.batch_size, num_workers=4, sampler=RandomIdentitySampler(new_dataset, args.num_instances), pin_memory=True, drop_last=True) # init pseudo/fake labels, y_tilde in cvpr19's paper: new_label = np.zeros([len(new_dataset), num_ids]) # init y_tilde, let softmax(y_tilde) is noisy labels for index, (imgs, _, pids, _, index) in enumerate(train_loader): index = index.numpy() onehot = torch.zeros(pids.size(0), num_ids).scatter_(1, pids.view(-1, 1), 10.0) onehot = onehot.numpy() new_label[index, :] = onehot # Using clustered label to init the new classifier: classifier = nn.Linear(2048, num_ids, bias=False) classifier.apply(weights_init_classifier) classifier = nn.DataParallel(classifier).cuda() optimizer_cla = torch.optim.SGD(classifier.parameters(), lr=args.lr * 10, momentum=0.9) # train model with new generated dataset trainer = Trainer_with_learnable_label(model, classifier, criterion, print_freq=args.print_freq) evaluator = Evaluator(model, print_freq=args.print_freq) # Start training for epoch in range(args.epochs): trainer.train(epoch, train_loader, new_label, optimizer, optimizer_cla) # Evaluate rank_score = evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) #Save the best ckpt: rank1 = rank_score.market1501[0] mAP = rank_score.map is_best_mAP = mAP > best_map best_map = max(mAP, best_map) save_checkpoint( { 'state_dict': model.module.state_dict(), 'epoch': iter_n + 1, 'best_mAP': best_map, # 'num_ids': num_ids, }, is_best_mAP, fpath=osp.join(args.logs_dir, 'checkpoint.pth.tar')) print( '\n * Finished epoch {:3d} top1: {:5.1%} mAP: {:5.1%} best_mAP: {:5.1%}{}\n' .format(iter_n + 1, rank1, mAP, best_map, ' *' if is_best_mAP else '')) return (rank_score.map, rank_score.market1501[0])
def main(args): np.random.seed(args.seed) torch.manual_seed(args.seed) cudnn.benchmark = True # Create data loaders assert args.num_instances > 1, "num_instances should be greater than 1" assert args.batch_size % args.num_instances == 0, \ 'num_instances should divide batch_size' if args.height is None or args.width is None: args.height, args.width = (144, 56) if args.arch == 'inception' else \ (256, 128) # get source data src_dataset, src_extfeat_loader = \ get_source_data(args.src_dataset, args.data_dir, args.height, args.width, args.batch_size, args.workers) # get target data tgt_dataset, num_classes, tgt_extfeat_loader, test_loader = \ get_data(args.tgt_dataset, args.data_dir, args.height, args.width, args.batch_size, args.workers) # Create model # Hacking here to let the classifier be the number of source ids if args.src_dataset == 'dukemtmc': model = models.create(args.arch, num_classes=632, pretrained=False) elif args.src_dataset == 'market1501': model = models.create(args.arch, num_classes=676, pretrained=False) else: raise RuntimeError( 'Please specify the number of classes (ids) of the network.') # Load from checkpoint if args.resume: print( 'Resuming checkpoints from finetuned model on another dataset...\n' ) checkpoint = load_checkpoint(args.resume) model.load_state_dict(checkpoint['state_dict'], strict=False) else: raise RuntimeWarning('Not using a pre-trained model.') model = nn.DataParallel(model).cuda() # evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) # if args.evaluate: return # Criterion criterion = [ TripletLoss(args.margin, args.num_instances, isAvg=True, use_semi=True).cuda(), TripletLoss(args.margin, args.num_instances, isAvg=True, use_semi=True).cuda(), None, None ] # Optimizer optimizer = torch.optim.Adam(model.parameters(), lr=args.lr) # training stage transformer on input images normalizer = T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) train_transformer = T.Compose([ T.Resize((args.height, args.width)), T.RandomHorizontalFlip(), T.ToTensor(), normalizer, T.RandomErasing(probability=0.5, sh=0.2, r1=0.3) ]) evaluator = Evaluator(model, print_freq=args.print_freq) evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) # # Start training for iter_n in range(args.iteration): if args.lambda_value == 0: source_features = 0 else: # get source datas' feature source_features, _ = extract_features(model, src_extfeat_loader, print_freq=args.print_freq) # synchronization feature order with src_dataset.train source_features = torch.cat([ source_features[f].unsqueeze(0) for f, _, _, _ in src_dataset.train ], 0) # extract training images' features print('Iteration {}: Extracting Target Dataset Features...'.format( iter_n + 1)) target_features, tarNames = extract_features( model, tgt_extfeat_loader, print_freq=args.print_freq) # synchronization feature order with dataset.train target_features = torch.cat([ target_features[f].unsqueeze(0) for f, _, _, _ in tgt_dataset.trainval ], 0) # target_real_label = np.asarray([tarNames[f].unsqueeze(0) for f, _, _, _ in tgt_dataset.trainval]) # calculate distance and rerank result # method 1 target_features = target_features.numpy() rerank_dist = re_ranking(source_features, target_features, lambda_value=args.lambda_value) # method 2 # distmat_qq = calDis(source_features, source_features) # distmat_qg = calDis(source_features, target_features) # distmat_gg = calDis(target_features, target_features) # rerank_dist = re_ranking2(distmat_qg.numpy(), distmat_qq.numpy(), distmat_gg.numpy()) cluster = HDBSCAN(metric='precomputed', min_samples=10) # select & cluster images as training set of this epochs clusterRes = cluster.fit(rerank_dist) labels, label_num = clusterRes.labels_, clusterRes.labels_.max() + 1 centers = np.zeros((label_num, target_features.shape[1])) nums = [0] * target_features.shape[1] print('clusters num =', label_num) # generate new dataset new_dataset = [] index = -1 for (fname, _, cam, timestamp), label in zip(tgt_dataset.trainval, labels): index += 1 if label == -1: continue # dont need to change codes in trainer.py _parsing_input function and sampler function after add 0 new_dataset.append((fname, label, cam, timestamp)) centers[label] += target_features[index] nums[label] += 1 print('Iteration {} have {} training images'.format( iter_n + 1, len(new_dataset))) train_loader = DataLoader(Preprocessor(new_dataset, root=tgt_dataset.images_dir, transform=train_transformer), batch_size=args.batch_size, num_workers=4, sampler=RandomIdentitySampler( new_dataset, args.num_instances), pin_memory=True, drop_last=True) for i in range(label_num): centers[i] /= nums[i] criterion[3] = ClassificationLoss(normalize(centers, axis=1)).cuda() classOptimizer = torch.optim.Adam( [{ 'params': model.parameters() }, { 'params': criterion[3].classifier.parameters(), 'lr': 1e-3 }], lr=args.lr) class_trainer = ClassificationTrainer(model, train_loader, criterion, classOptimizer) for epoch in range(args.epochs): class_trainer.train(epoch) rank_score = evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) # Evaluate rank_score = evaluator.evaluate(test_loader, tgt_dataset.query, tgt_dataset.gallery) save_checkpoint( { 'state_dict': model.module.state_dict(), 'epoch': epoch + 1, 'best_top1': rank_score.market1501[0], }, True, fpath=osp.join(args.logs_dir, 'adapted.pth.tar')) return (rank_score.map, rank_score.market1501[0])