def __init__(self, margin=0.2, nu=0.0, weight=None, batch_axis=0, **kwargs): super(MarginLoss, self).__init__() self.margin = margin self.nu = nu self.pdist = PairwiseDistance(2) self.weight = weight
class MarginLoss(Function): r"""Margin based loss. Parameters ---------- margin : float Margin between positive and negative pairs. nu : float Regularization parameter for beta. Inputs: - anchors: sampled anchor embeddings. - positives: sampled positive embeddings. - negatives: sampled negative embeddings. - beta_in: class-specific betas. - a_indices: indices of anchors. Used to get class-specific beta. Outputs: - Loss. """ def __init__(self, margin=0.2, nu=0.0, weight=None, batch_axis=0, **kwargs): super(MarginLoss, self).__init__() self.margin = margin self.nu = nu self.pdist = PairwiseDistance(2) self.weight = weight def forward(self, anchors, positives, negatives, beta_in, a_indices=None): if a_indices is not None: #确认beta_in是否需要是variable # Jointly train class-specific beta. beta = beta_in.index_select(0, a_indices) beta_reg_loss = torch.sum(beta) * self.nu else: # Use a constant beta. beta = beta_in beta_reg_loss = 0.0 d_p = self.pdist.forward(anchors, positives) d_n = self.pdist.forward(anchors, negatives) # d_ap = F.sqrt(F.sum(F.square(positives - anchors), axis=1) + 1e-8) # d_an = F.sqrt(F.sum(F.square(negatives - anchors), axis=1) + 1e-8) pos_loss = torch.clamp(self.margin + d_p - beta, min=0.0) neg_loss = torch.clamp(self.margin - d_n + beta, min=0.0) pair_cnt = float( np.sum((pos_loss.cpu().data.numpy() > 0.0) + (neg_loss.cpu().data.numpy() > 0.0))) # Normalize based on the number of pairs. loss = (torch.sum(torch.pow(pos_loss, 2) + torch.pow(neg_loss, 2)) + beta_reg_loss) / pair_cnt if self.weight: loss = loss * self.weight return loss
class TripletSoftMarginLoss(Function): def __init__(self): super(TripletSoftMarginLoss).__init__() self.pdist = PairwiseDistance(2) self.activion = torch.nn.Softplus() def forward(self, anchor, positive, negative): d_p = self.pdist.forward(anchor, positive) d_n = self.pdist.forward(anchor, negative) dist_hinge = torch.clamp(self.activion(d_p) + d_p - d_n, min=0.0) loss = torch.mean(dist_hinge) return loss
class TripletMarginLoss(Function): """Triplet loss function. """ def __init__(self, margin): super(TripletMarginLoss, self).__init__() self.margin = margin self.pdist = PairwiseDistance(2) # norm 2 def forward(self, anchor, positive, negative): d_p = self.pdist.forward(anchor, positive) d_n = self.pdist.forward(anchor, negative) dist_hinge = torch.clamp(self.margin + d_p - d_n, min=0.0) loss = torch.mean(dist_hinge) return loss
def __init__(self, cfg, model, dataloader=None, transform=None): """Initializer model Arguments: cfg {[type]} -- [description] model {[type]} -- [description] dataloader {[type]} -- [description] """ self.cfg = cfg self.model = model self.dataloader = dataloader self.device = torch.device( "cuda" if torch.cuda.is_available() else "cpu") self.dataprocess = None self.l2_dist = PairwiseDistance() self.transform = transform
def __init__(self, margin): super(TripletMarginLoss, self).__init__() self.margin = margin self.pdist = PairwiseDistance(2) # norm 2
if (w <= h and w == self.size) or (h <= w and h == self.size): return img if w < h: ow = self.size oh = int(self.size * h / w) return img.resize((ow, oh), self.interpolation) else: oh = self.size ow = int(self.size * w / h) return img.resize((ow, oh), self.interpolation) else: return img.resize(self.size, self.interpolation) kwargs = {'num_workers': 2, 'pin_memory': True} l2_dist = PairwiseDistance(2) transform = transforms.Compose([ Scale(96), transforms.ToTensor(), transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]) ]) train_dir = TripletFaceDataset(dir=args.dataroot, n_triplets=args.n_triplets, transform=transform) train_loader = torch.utils.data.DataLoader(train_dir, batch_size=args.batch_size, shuffle=False, **kwargs)
def train_epoch_some(train_loader, model, loss_fn, optimizer, cuda, log_interval, metrics): for metric in metrics: metric.reset() model.train() losses = [] total_loss = 0 pbar = tqdm(enumerate(train_loader)) labels, distances = [], [] l2_dist = PairwiseDistance(2) for batch_idx, (data_a, data_p, data_n, label_p, label_n) in pbar: data_a, data_p, data_n = data_a.cuda(), data_p.cuda(), data_n.cuda() data_a, data_p, data_n = Variable(data_a), Variable(data_p), \ Variable(data_n) # compute output out_a, out_p, out_n = model(data_a), model(data_p), model(data_n) # Choose the hard negatives d_p = l2_dist.forward(out_a, out_p) d_n = l2_dist.forward(out_a, out_n) all = (d_n - d_p < args.margin).cpu().data.numpy().flatten() hard_triplets = np.where(all == 1) if len(hard_triplets[0]) == 0: continue out_selected_a = Variable( torch.from_numpy(out_a.cpu().data.numpy()[hard_triplets]).cuda()) out_selected_p = Variable( torch.from_numpy(out_p.cpu().data.numpy()[hard_triplets]).cuda()) out_selected_n = Variable( torch.from_numpy(out_n.cpu().data.numpy()[hard_triplets]).cuda()) selected_data_a = Variable( torch.from_numpy(data_a.cpu().data.numpy()[hard_triplets]).cuda()) selected_data_p = Variable( torch.from_numpy(data_p.cpu().data.numpy()[hard_triplets]).cuda()) selected_data_n = Variable( torch.from_numpy(data_n.cpu().data.numpy()[hard_triplets]).cuda()) selected_label_p = torch.from_numpy( label_p.cpu().numpy()[hard_triplets]) selected_label_n = torch.from_numpy( label_n.cpu().numpy()[hard_triplets]) triplet_loss = loss_fn.forward(out_selected_a, out_selected_p, out_selected_n) cls_a = model.forward_classifier(selected_data_a) cls_p = model.forward_classifier(selected_data_p) cls_n = model.forward_classifier(selected_data_n) cls_a = model.forward_classifier(selected_data_a) cls_p = model.forward_classifier(selected_data_p) cls_n = model.forward_classifier(selected_data_n) criterion = nn.CrossEntropyLoss() predicted_labels = torch.cat([cls_a, cls_p, cls_n]) true_labels = torch.cat([ Variable(selected_label_p.cuda()), Variable(selected_label_p.cuda()), Variable(selected_label_n.cuda()) ]) cross_entropy_loss = criterion(predicted_labels.cuda(), true_labels.cuda()) loss = cross_entropy_loss + triplet_loss # compute gradient and update weights optimizer.zero_grad() loss.backward() optimizer.step() # update the optimizer learning rate adjust_learning_rate(optimizer)
def experimenter(data_name='cora', train_ratio=0.03, cuda=True, random_seed=42, hidden=16, dropout_ratio=0.5, learning_rate=0.01, weight_decay=5e-4, num_epochs=65, early_stopping=30, task='classification', public_splitting=False): # helper function to run epxeriment if data_name in ['cora', 'citeseer', 'pubmed']: print("Loading Classification Datasets") Tmat, eadj, edge_name, edge_feature_dict, adj, features, edge_features, labels, idx_train, idx_val, idx_test = tqdm( load_data(data_name=data_name, train_ratio=train_ratio, public_splitting=public_splitting)) model = GCN(nfeat_v=features.shape[1], nfeat_e=edge_features.shape[1], nhid=hidden, nclass=labels.max().item() + 1, dropout=dropout_ratio) ssl_agent_n = PairwiseDistance(adj, features, nhid=args.hidden, cuda=cuda, node=True) ssl_agent_e = PairwiseDistance(eadj, edge_features, nhid=args.hidden, cuda=cuda, node=False) else: ValueError("The input data is not supported! ") print(">" * 100) print("Loaded and preprocessed the graph data! ") print(">" * 100) optimizer = optim.Adam(model.parameters(), lr=learning_rate, weight_decay=weight_decay) np.random.seed(random_seed) torch.manual_seed(random_seed) if cuda: torch.cuda.manual_seed(random_seed) torch.set_default_tensor_type('torch.cuda.FloatTensor') if cuda: model.cuda() Tmat = Tmat.cuda() eadj = eadj.cuda() adj = adj.cuda() features = features.cuda() edge_features = edge_features.cuda() labels = labels.cuda() idx_train = idx_train.cuda() idx_val = idx_val.cuda() idx_test = idx_test.cuda() # pooling = pooling.cuda() # node_count = node_count.cuda() if task == "classification": criteria = F.nll_loss acc_measure = accuracy elif task == "regression": criteria = torch.nn.L1Loss acc_measure = RMSELoss # --------------------------------------- # training function # --------------------------------------- # count_time = 0 def train(epoch): t = time.time() model.train() optimizer.zero_grad() output, n_feature, e_feature = model(features, edge_features, eadj, adj, Tmat, task) loss_n = ssl_agent_n.classification_loss(n_feature) loss_e = ssl_agent_e.classification_loss(e_feature) loss_train = criteria(output[idx_train], labels[idx_train]) loss_train = loss_train + 0.1 * loss_n + 0.1 * loss_e acc_train = acc_measure(output[idx_train], labels[idx_train]) loss_train.backward() optimizer.step() if not args.fastmode: # Evaluate validation set performance separately, # deactivates dropout during validation run. model.eval() output, _, _ = model(features, edge_features, eadj, adj, Tmat, task) loss_val = criteria(output[idx_val], labels[idx_val]) acc_val = acc_measure(output[idx_val], labels[idx_val]) print('Epoch: {:04d}'.format(epoch + 1), 'loss_train: {:.4f}'.format(loss_train.item()), 'acc_train: {:.4f}'.format(acc_train.item()), 'loss_val: {:.4f}'.format(loss_val.item()), 'acc_val: {:.4f}'.format(acc_val.item()), 'time: {:.4f}s'.format(time.time() - t)) return loss_val.item() # ------------------------------------------- # testing function # ------------------------------------------- def test(): model.eval() output, _, _ = model(features, edge_features, eadj, adj, Tmat, task) loss_test = criteria(output[idx_test], labels[idx_test]) acc_test = acc_measure(output[idx_test], labels[idx_test]) print("Test set results:", "loss= {:.4f}".format(loss_test.item()), "accuracy= {:.4f}".format(acc_test.item())) return acc_test.item() def pretrain(epoch): t = time.time() model.train() optimizer.zero_grad() output, node_f, edge_f = model(features, edge_features, eadj, adj, Tmat, task) loss_n = ssl_agent_n.classification_loss(node_f) loss_e = ssl_agent_e.classification_loss(edge_f) # loss_train = criteria(output[idx_train], labels[idx_train]) loss_train = loss_n + loss_e acc_train = acc_measure(output[idx_train], labels[idx_train]) loss_train.backward() optimizer.step() if not args.fastmode: # Evaluate validation set performance separately, # deactivates dropout during validation run. model.eval() output, _, _ = model(features, edge_features, eadj, adj, Tmat, task) loss_val = criteria(output[idx_val], labels[idx_val]) acc_val = acc_measure(output[idx_val], labels[idx_val]) print('Epoch: {:04d}'.format(epoch + 1), 'loss_train: {:.4f}'.format(loss_train.item()), 'acc_train: {:.4f}'.format(acc_train.item()), 'loss_val: {:.4f}'.format(loss_val.item()), 'acc_val: {:.4f}'.format(acc_val.item()), 'time: {:.4f}s'.format(time.time() - t)) return loss_val.item() # Train model t_total = time.time() val_watch = [] pre_val_watch = [] input_idx_train = idx_train # for epoch in range(50): # pre_val_watch.append(pretrain(epoch)) # test() # if epoch > early_stopping and pre_val_watch[-1] > np.mean(pre_val_watch[-(early_stopping + 1):-1]): # print("Early stopping...") # break for epoch in range(num_epochs): # val_adj, val_fea = ssl_agent.transform_data() val_watch.append(train(epoch)) test() if epoch > early_stopping and val_watch[-1] > np.mean( val_watch[-(early_stopping + 1):-1]): print("Early stopping...") break print("Optimization Finished!") print("Total time elapsed: {:.4f}s".format(time.time() - t_total)) print("Printing the weights : ") return test()
def select_three_sample(model, args, epoch, writer): model.eval() num_each_class = [500, 500, 500, 500, 500, 500, 500, 50, 50, 50] # num_each_class = [500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500] transform = transforms.Compose([ transforms.Resize(32), transforms.ToTensor(), transforms.Normalize(mean=np.array([0.485, 0.456, 0.406]), std=np.array([0.229, 0.224, 0.225])), ]) train_set = torchvision.datasets.ImageFolder(root=args.train_set, transform=transform) train_loader = torch.utils.data.DataLoader(train_set, batch_size=args.test_batch_size, shuffle=False) NearestCentroid, KNeighbors, features, label, labels = [], [], [], [], [] for i, (data, target) in enumerate(train_loader): data, target = data.cuda(), target.cuda() data, target = Variable(data), Variable(target) output = model(data) features.extend(output.data) KNeighbors.extend(output.data.cpu().numpy()) labels.extend(target.data.cpu().numpy()) count = 0 l2_dist = PairwiseDistance(2) destination = os.path.join(args.check_path, 'epoch' + str(epoch)) if not os.path.exists(destination): os.mkdir(destination) for i in range(len(num_each_class)): num_sample = features[count:count + num_each_class[i]] m = torch.tensor(np.zeros(args.embedding_size)).float().cuda() for x in num_sample: m += x m /= num_each_class[i] sample1 = min(num_sample, key=lambda x: l2_dist.forward_val(x, m)) sample2 = max(num_sample, key=lambda x: l2_dist.forward_val(x, sample1)) sample3 = max(num_sample, key=lambda x: l2_dist.forward_val(x, sample2)) NearestCentroid.append(sample1.cpu().numpy()) label.append(i) sample1_loc, sample2_loc, sample3_loc = -1, -1, -1 for j in range(num_sample.__len__()): if (num_sample[j] == sample1).all(): sample1_loc = j if (num_sample[j] == sample2).all(): sample2_loc = j if (num_sample[j] == sample3).all(): sample3_loc = j frame = pd.read_csv(args.train_set_csv) destination_class = os.path.join( destination, str(frame['name'][count + sample1_loc])) if not os.path.exists(destination_class): os.mkdir(destination_class) sample1_source = os.path.join( args.train_set, str(frame['name'][count + sample1_loc]), str(frame['id'][count + sample1_loc]) + '.png') sample2_source = os.path.join( args.train_set, str(frame['name'][count + sample2_loc]), str(frame['id'][count + sample2_loc]) + '.png') sample3_source = os.path.join( args.train_set, str(frame['name'][count + sample3_loc]), str(frame['id'][count + sample3_loc]) + '.png') shutil.copy(sample1_source, destination_class + '/sample1.png') shutil.copy(sample2_source, destination_class + '/sample2.png') shutil.copy(sample3_source, destination_class + '/sample3.png') count += num_each_class[i] clf = neighbors.NearestCentroid() clf.fit(NearestCentroid, label) return features, labels, clf, destination
args.cuda = not args.no_cuda and torch.cuda.is_available() np.random.seed(args.seed) if not os.path.exists(args.log_dir): os.makedirs(args.log_dir) if args.cuda: cudnn.benchmark = True LOG_DIR = args.log_dir + '/run-optim_{}-lr{}-wd{}-embeddings{}-center{}-MSCeleb'.format(args.optimizer, args.lr, args.wd,args.embedding_size,args.center_loss_weight) # create logger logger = Logger(LOG_DIR) kwargs = {'num_workers': 2, 'pin_memory': True} if args.cuda else {} l2_dist = PairwiseDistance(2) transform = transforms.Compose([ transforms.Scale(96), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean = [ 0.5, 0.5, 0.5 ], std = [ 0.5, 0.5, 0.5 ]) ]) train_dir = ImageFolder(args.dataroot,transform=transform) testacc_dir = ImageFolder(args.testdataroot,transform=transform) train_loader = torch.utils.data.DataLoader(train_dir, batch_size=args.batch_size, shuffle=True, **kwargs) testaccuracy_loader = torch.utils.data.DataLoader(testacc_dir,
def main(): parser = argparse.ArgumentParser( description='Classifiar using triplet loss.') parser.add_argument('--CVDs', type=str, default='0,1,2,3', metavar='CUDA_VISIBLE_DEVICES', help='CUDA_VISIBLE_DEVICES') parser.add_argument( '--train-set', type=str, default='/home/zili/memory/FaceRecognition-master/data/mnist/train', metavar='dir', help='path of train set.') parser.add_argument( '--test-set', type=str, default='/home/zili/memory/FaceRecognition-master/data/mnist/test', metavar='dir', help='path of test set.') parser.add_argument( '--train-set-csv', type=str, default='/home/zili/memory/FaceRecognition-master/data/mnist/train.csv', metavar='file', help='path of train set.csv.') parser.add_argument( '--test-set-csv', type=str, default='/home/zili/memory/FaceRecognition-master/data/mnist/test.csv', metavar='file', help='path of test set.csv.') parser.add_argument('--num-triplet', type=int, default=10000, metavar='N', help='number of triplet in dataset (default: 32)') parser.add_argument('--train-batch-size', type=int, default=256, metavar='N', help='input batch size for training (default: 32)') parser.add_argument('--test-batch-size', type=int, default=512, metavar='N', help='input batch size for testing (default: 64)') parser.add_argument('--epochs', type=int, default=100, metavar='N', help='number of epochs to train (default: 100)') parser.add_argument('--embedding-size', type=int, default=256, metavar='N', help='embedding size of model (default: 256)') parser.add_argument('--lr', type=float, default=0.05, metavar='LR', help='learning rate (default: 0.01)') parser.add_argument('--margin', type=float, default=1.0, metavar='margin', help='loss margin (default: 1.0)') parser.add_argument('--kneighbor', type=int, default=20, metavar='N', help='how many neighbor in testing') parser.add_argument('--num-classes', type=int, default=10, metavar='N', help='classes number of dataset') parser.add_argument('--momentum', type=float, default=0.8, metavar='M', help='SGD momentum (default: 0.9)') parser.add_argument('--seed', type=int, default=1, metavar='S', help='random seed (default: 1)') parser.add_argument( '--log-interval', type=int, default=4, metavar='N', help='how many batches to wait before logging training status') parser.add_argument('--model-name', type=str, default='resnet34', metavar='M', help='model name (default: resnet34)') parser.add_argument('--dropout-p', type=float, default=0.2, metavar='D', help='Dropout probability (default: 0.2)') parser.add_argument('--check-path', type=str, default='checkpoints3', metavar='C', help='Checkpoint path') parser.add_argument( '--is-semihard', type=bool, default=True, metavar='R', help='whether the dataset is selected in semi-hard way.') parser.add_argument('--is-pretrained', type=bool, default=False, metavar='R', help='whether model is pretrained.') args = parser.parse_args() os.environ["CUDA_VISIBLE_DEVICES"] = args.CVDs output1 = 'main' + str(datetime.datetime.now()) f = open(args.check_path + os.path.sep + output1 + '.txt', 'w+') l2_dist = PairwiseDistance(2) writer = SummaryWriter() print('Loading model...') model = FaceModel(embedding_size=args.embedding_size, num_classes=args.num_classes, pretrained=args.is_pretrained) f.write(" model: {}".format(model.model) + '\r\n') if torch.cuda.is_available(): model = torch.nn.DataParallel(model).cuda() cudnn.benchmark = True optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum, weight_decay=1e-5) # optimizer = optim.Adam(model.parameters(), lr=args.lr) print('start training...') features, labels, clf = feature(model, args) for epoch in range(args.epochs): if epoch % 5 == 0: file_operation(f, args, optimizer) if (epoch + 1) % 2 == 0: args.lr = args.lr / 3 update_lr(optimizer, args.lr) generate_csv(args) train(epoch, model, optimizer, args, f, writer, features) features, labels, clf = feature(model, args) validate(epoch, model, clf, args, f, writer) f.write('\r\n') torch.save(model, args.check_path + os.path.sep + output1 + '.pkl')
def generate_triplets(df, ps, num_triplets, features, preserved_features, margin): def make_dictionary_for_face_class(df): ''' - face_classes = {'class0': [class0_id0, ...], 'class1': [class1_id0, ...], ...} ''' face_classes = dict() for idx, label in enumerate(df['class']): if label not in face_classes: face_classes[label] = [] face_classes[label].append(df.iloc[idx, 0]) return face_classes triplets = [] classes = ps['class'].unique() face_classes = make_dictionary_for_face_class(df) preserved_image = make_dictionary_for_face_class(ps) i = 0 now_time = datetime.datetime.now() while i < num_triplets + 1: ''' - all three image is selected from new train set ''' pos_class = np.random.choice([7, 8, 9]) neg_class = np.random.choice([7, 8, 9]) while len(face_classes[pos_class]) < 2: pos_class = np.random.choice([7, 8, 9]) while pos_class == neg_class: neg_class = np.random.choice([7, 8, 9]) pos_name = df.loc[df['class'] == pos_class, 'name'].values[0] neg_name = df.loc[df['class'] == neg_class, 'name'].values[0] if len(face_classes[pos_class]) == 2: ianc, ipos = np.random.choice(2, size=2, replace=False) else: ianc = np.random.randint(0, len(face_classes[pos_class])) ipos = np.random.randint(0, len(face_classes[pos_class])) while ianc == ipos: ipos = np.random.randint(0, len(face_classes[pos_class])) ineg = np.random.randint(0, len(face_classes[neg_class])) triplets.append([ face_classes[pos_class][ianc], face_classes[pos_class][ipos], face_classes[neg_class][ineg], pos_class, neg_class, pos_name, neg_name, 1, 1, 1 ]) i += 1 i = 0 last_time = now_time now_time = datetime.datetime.now() print(now_time - last_time) while i < num_triplets + 1: ''' - all three images are selected from preserved images ''' pos_class = np.random.choice(classes) neg_class = np.random.choice(classes) while len(preserved_image[pos_class]) < 2: pos_class = np.random.choice(classes) while pos_class == neg_class: neg_class = np.random.choice(classes) pos_name = ps.loc[ps['class'] == pos_class, 'name'].values[0] neg_name = ps.loc[ps['class'] == neg_class, 'name'].values[0] if len(preserved_image[pos_class]) == 2: ianc, ipos = np.random.choice(2, size=2, replace=False) else: ianc = np.random.randint(0, len(preserved_image[pos_class])) ipos = np.random.randint(0, len(preserved_image[pos_class])) while ianc == ipos: ipos = np.random.randint(0, len(preserved_image[pos_class])) ineg = np.random.randint(0, len(preserved_image[neg_class])) triplets.append([ preserved_image[pos_class][ianc], preserved_image[pos_class][ipos], preserved_image[neg_class][ineg], pos_class, neg_class, pos_name, neg_name, 2, 2, 2 ]) i += 1 i = 0 last_time = now_time now_time = datetime.datetime.now() print(now_time - last_time) while i < num_triplets + 1: ''' -a and p are from preserved images -n is from new train set ''' pos_class = np.random.choice(classes) neg_class = np.random.choice([7, 8, 9]) while len(preserved_image[pos_class]) < 2: pos_class = np.random.choice(classes) while pos_class == neg_class: neg_class = np.random.choice([7, 8, 9]) pos_name = ps.loc[ps['class'] == pos_class, 'name'].values[0] neg_name = df.loc[df['class'] == neg_class, 'name'].values[0] if len(preserved_image[pos_class]) == 2: ianc, ipos = np.random.choice(2, size=2, replace=False) else: ianc = np.random.randint(0, len(preserved_image[pos_class])) ipos = np.random.randint(0, len(preserved_image[pos_class])) while ianc == ipos: ipos = np.random.randint(0, len(preserved_image[pos_class])) ineg = np.random.randint(0, len(face_classes[neg_class])) a_position = pos_class * 3 + ianc p_position = pos_class * 3 + ipos n_position = \ df.loc[df['class'] == neg_class, 'id'].ix[df['id'] == face_classes[neg_class][ineg]].index.values[0] l2_dist = PairwiseDistance(2) dp = l2_dist.forward_val(preserved_features[a_position], preserved_features[p_position]) dn = l2_dist.forward_val(preserved_features[a_position], features[n_position]) if dp - dn + margin > 0: triplets.append([ preserved_image[pos_class][ianc], preserved_image[pos_class][ipos], face_classes[neg_class][ineg], pos_class, neg_class, pos_name, neg_name, 2, 2, 1 ]) i += 1 i = 0 last_time = now_time now_time = datetime.datetime.now() print(now_time - last_time) while i < num_triplets + 1: ''' -a is from preserved images -p and n are from new train set ''' pos_class = np.random.choice([7, 8, 9]) neg_class = np.random.choice([7, 8, 9]) while len(face_classes[pos_class]) < 2: pos_class = np.random.choice([7, 8, 9]) while pos_class == neg_class: neg_class = np.random.choice([7, 8, 9]) pos_name = ps.loc[ps['class'] == pos_class, 'name'].values[0] neg_name = df.loc[df['class'] == neg_class, 'name'].values[0] if len(face_classes[pos_class]) == 2: ianc, ipos = np.random.choice(2, size=2, replace=False) else: ianc = np.random.randint(0, len(preserved_image[pos_class])) ipos = np.random.randint(0, len(face_classes[pos_class])) ineg = np.random.randint(0, len(face_classes[neg_class])) a_position = \ ps.loc[ps['class'] == pos_class, 'id'].ix[ps['id'] == preserved_image[pos_class][ianc]].index.values[0] p_position = \ df.loc[df['class'] == pos_class, 'id'].ix[df['id'] == face_classes[pos_class][ipos]].index.values[0] n_position = \ df.loc[df['class'] == neg_class, 'id'].ix[df['id'] == face_classes[neg_class][ineg]].index.values[0] l2_dist = PairwiseDistance(2) dp = l2_dist.forward_val(preserved_features[a_position], features[p_position]) dn = l2_dist.forward_val(preserved_features[a_position], features[n_position]) if dp - dn + margin > 0: triplets.append([ preserved_image[pos_class][ianc], face_classes[pos_class][ipos], face_classes[neg_class][ineg], pos_class, neg_class, pos_name, neg_name, 2, 1, 1 ]) i += 1 i = 0 last_time = now_time now_time = datetime.datetime.now() print(now_time - last_time) while i < num_triplets: ''' -a and p are from new train set -n is from pre ''' pos_class = np.random.choice([7, 8, 9]) neg_class = np.random.choice(classes) while len(face_classes[pos_class]) < 2: pos_class = np.random.choice([7, 8, 9]) while pos_class == neg_class: neg_class = np.random.choice(classes) pos_name = df.loc[df['class'] == pos_class, 'name'].values[0] neg_name = ps.loc[ps['class'] == neg_class, 'name'].values[0] if len(face_classes[pos_class]) == 2: ianc, ipos = np.random.choice(2, size=2, replace=False) else: ianc = np.random.randint(0, len(face_classes[pos_class])) ipos = np.random.randint(0, len(face_classes[pos_class])) while ianc == ipos: ipos = np.random.randint(0, len(face_classes[pos_class])) ineg = np.random.randint(0, len(preserved_image[neg_class])) a_position = \ df.loc[df['class'] == pos_class, 'id'].ix[df['id'] == face_classes[pos_class][ianc]].index.values[0] p_position = \ df.loc[df['class'] == pos_class, 'id'].ix[df['id'] == face_classes[pos_class][ipos]].index.values[0] n_position = \ ps.loc[ps['class'] == neg_class, 'id'].ix[ps['id'] == preserved_image[neg_class][ineg]].index.values[0] l2_dist = PairwiseDistance(2) dp = l2_dist.forward_val(features[a_position], features[p_position]) dn = l2_dist.forward_val(features[a_position], preserved_features[n_position]) if dp - dn + margin > 0: triplets.append([ face_classes[pos_class][ianc], face_classes[pos_class][ipos], preserved_image[neg_class][ineg], pos_class, neg_class, pos_name, neg_name, 1, 1, 2 ]) i += 1 i = 0 last_time = now_time now_time = datetime.datetime.now() print(now_time - last_time) while i < num_triplets: ''' -a is from new train set -p and n is from pre ''' pos_class = np.random.choice([7, 8, 9]) neg_class = np.random.choice(classes) while len(face_classes[pos_class]) < 2: pos_class = np.random.choice([7, 8, 9]) while pos_class == neg_class: neg_class = np.random.choice(classes) pos_name = df.loc[df['class'] == pos_class, 'name'].values[0] neg_name = ps.loc[ps['class'] == neg_class, 'name'].values[0] if len(face_classes[pos_class]) == 2: ianc, ipos = np.random.choice(2, size=2, replace=False) else: ianc = np.random.randint(0, len(face_classes[pos_class])) ipos = np.random.randint(0, len(preserved_image[pos_class])) ineg = np.random.randint(0, len(preserved_image[neg_class])) a_position = \ df.loc[df['class'] == pos_class, 'id'].ix[df['id'] == face_classes[pos_class][ianc]].index.values[0] p_position = \ ps.loc[ps['class'] == pos_class, 'id'].ix[ps['id'] == preserved_image[pos_class][ipos]].index.values[0] n_position = \ ps.loc[ps['class'] == neg_class, 'id'].ix[ps['id'] == preserved_image[neg_class][ineg]].index.values[0] l2_dist = PairwiseDistance(2) dp = l2_dist.forward_val(features[a_position], preserved_features[p_position]) dn = l2_dist.forward_val(features[a_position], preserved_features[n_position]) if dp - dn + margin > 0: triplets.append([ face_classes[pos_class][ianc], preserved_image[pos_class][ipos], preserved_image[neg_class][ineg], pos_class, neg_class, pos_name, neg_name, 1, 2, 2 ]) i += 1 last_time = now_time now_time = datetime.datetime.now() print(now_time - last_time) return triplets
def __init__(self): super(TripletSoftMarginLoss).__init__() self.pdist = PairwiseDistance(2) self.activion = torch.nn.Softplus()
if (w <= h and w == self.size) or (h <= w and h == self.size): return img if w < h: ow = self.size oh = int(self.size * h / w) return img.resize((ow, oh), self.interpolation) else: oh = self.size ow = int(self.size * w / h) return img.resize((ow, oh), self.interpolation) else: return img.resize(self.size, self.interpolation) kwargs = {'num_workers': 2, 'pin_memory': True} if args.cuda else {} l2_dist = PairwiseDistance(2) ##计算两个向量之间的标准差 transform = transforms.Compose([ Scale(96), transforms.ToTensor(), transforms.Normalize(mean = [ 0.5, 0.5, 0.5 ], std = [ 0.5, 0.5, 0.5 ]) ]) ##args.n_triplets表示会产生多少个训练对,每个训练对有三个图片 train_dir = TripletFaceDataset(dir=args.dataroot,n_triplets=args.n_triplets,transform=transform) train_loader = torch.utils.data.DataLoader(train_dir, batch_size=args.batch_size, shuffle=False, **kwargs) test_loader = torch.utils.data.DataLoader( LFWDataset(dir=args.lfw_dir,pairs_path=args.lfw_pairs_path, transform=transform),
def generate_triplets(df, num_triplets, features, margin): def make_dictionary_for_face_class(df): ''' - face_classes = {'class0': [class0_id0, ...], 'class1': [class1_id0, ...], ...} ''' face_classes = dict() for idx, label in enumerate(df['class']): if label not in face_classes: face_classes[label] = [] face_classes[label].append(df.iloc[idx, 0]) return face_classes triplets = [] classes = df['class'].unique() face_classes = make_dictionary_for_face_class(df) i = 0 while i < num_triplets: ''' - randomly choose anchor, positive and negative images for triplet loss - anchor and positive images in pos_class - negative image in neg_class - at least, two images needed for anchor and positive images in pos_class - negative image should have different class as anchor and positive images by definition ''' pos_class = np.random.choice(classes) neg_class = np.random.choice(classes) while len(face_classes[pos_class]) < 2: pos_class = np.random.choice(classes) while pos_class == neg_class: neg_class = np.random.choice(classes) pos_name = df.loc[df['class'] == pos_class, 'name'].values[0] neg_name = df.loc[df['class'] == neg_class, 'name'].values[0] if len(face_classes[pos_class]) == 2: ianc, ipos = np.random.choice(2, size=2, replace=False) else: ianc = np.random.randint(0, len(face_classes[pos_class])) ipos = np.random.randint(0, len(face_classes[pos_class])) while ianc == ipos: ipos = np.random.randint(0, len(face_classes[pos_class])) ineg = np.random.randint(0, len(face_classes[neg_class])) a_position = df.loc[df['class'] == pos_class, 'id'].ix[ df['id'] == face_classes[pos_class][ianc]].index.values[0] p_position = df.loc[df['class'] == pos_class, 'id'].ix[ df['id'] == face_classes[pos_class][ipos]].index.values[0] n_position = df.loc[df['class'] == neg_class, 'id'].ix[ df['id'] == face_classes[neg_class][ineg]].index.values[0] l2_dist = PairwiseDistance(2) dp = l2_dist.forward_val(features[a_position], features[p_position]) dn = l2_dist.forward_val(features[a_position], features[n_position]) if dp - dn + margin > 0: triplets.append([ face_classes[pos_class][ianc], face_classes[pos_class][ipos], face_classes[neg_class][ineg], pos_class, neg_class, pos_name, neg_name ]) i += 1 return triplets