From 9962b8389ed20132e94d6a52bb278f3518477a78 Mon Sep 17 00:00:00 2001 From: SYWDAzlq <30711641+SYWDAzlq@users.noreply.github.com> Date: Mon, 18 Oct 2021 13:51:50 +0800 Subject: [PATCH 1/3] Update n_pair_loss.py In line 45, I change the "set(labels)" to "labels".If you use the "set(labels)", the outputs are wrong shape. --- losses/n_pair_loss.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/losses/n_pair_loss.py b/losses/n_pair_loss.py index 3033fda..abc7001 100755 --- a/losses/n_pair_loss.py +++ b/losses/n_pair_loss.py @@ -42,7 +42,7 @@ def get_n_pairs(labels): labels = labels.cpu().data.numpy() n_pairs = [] - for label in set(labels): + for label in labels: label_mask = (labels == label) label_indices = np.where(label_mask)[0] if len(label_indices) < 2: From dba7e4770a5edf57c6a64e675493d1bda53e0ffc Mon Sep 17 00:00:00 2001 From: SYWDAzlq <30711641+SYWDAzlq@users.noreply.github.com> Date: Mon, 18 Oct 2021 14:18:09 +0800 Subject: [PATCH 2/3] Update n_pair_loss.py --- losses/n_pair_loss.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/losses/n_pair_loss.py b/losses/n_pair_loss.py index abc7001..8353a12 100755 --- a/losses/n_pair_loss.py +++ b/losses/n_pair_loss.py @@ -42,7 +42,7 @@ def get_n_pairs(labels): labels = labels.cpu().data.numpy() n_pairs = [] - for label in labels: + for label in list(labels): label_mask = (labels == label) label_indices = np.where(label_mask)[0] if len(label_indices) < 2: From d4252e2bfa4d748023e5c997009ca0d4dcf9c4b3 Mon Sep 17 00:00:00 2001 From: SYWDAzlq <30711641+SYWDAzlq@users.noreply.github.com> Date: Mon, 18 Oct 2021 14:19:36 +0800 Subject: [PATCH 3/3] Delete n_pair_loss.py --- losses/n_pair_loss.py | 95 ------------------------------------------- 1 file changed, 95 deletions(-) delete mode 100755 losses/n_pair_loss.py diff --git a/losses/n_pair_loss.py b/losses/n_pair_loss.py deleted file mode 100755 index 8353a12..0000000 --- a/losses/n_pair_loss.py +++ /dev/null @@ -1,95 +0,0 @@ -import numpy as np -import torch.nn as nn -import torch - - -class NPairLoss(nn.Module): - """ - N-Pair loss - Sohn, Kihyuk. "Improved Deep Metric Learning with Multi-class N-pair Loss Objective," Advances in Neural Information - Processing Systems. 2016. - http://papers.nips.cc/paper/6199-improved-deep-metric-learning-with-multi-class-n-pair-loss-objective - """ - - def __init__(self, l2_reg=0.02): - super(NPairLoss, self).__init__() - self.l2_reg = l2_reg - - def forward(self, embeddings, labels): - n_pairs, n_negatives = self.get_n_pairs(labels) - - if embeddings.is_cuda: - n_pairs = n_pairs.cuda() - n_negatives = n_negatives.cuda() - - anchors = embeddings[n_pairs[:, 0]] # (n, embedding_size) - positives = embeddings[n_pairs[:, 1]] # (n, embedding_size) - negatives = embeddings[n_negatives] # (n, n-1, embedding_size) - - losses = self.n_pair_loss(anchors, positives, negatives) - # + self.l2_reg * self.l2_loss(anchors, positives) - - return losses, len(n_pairs) - - @staticmethod - def get_n_pairs(labels): - """ - Get index of n-pairs and n-negatives - :param labels: label vector of mini-batch - :return: A tuple of n_pairs (n, 2) - and n_negatives (n, n-1) - """ - labels = labels.cpu().data.numpy() - n_pairs = [] - - for label in list(labels): - label_mask = (labels == label) - label_indices = np.where(label_mask)[0] - if len(label_indices) < 2: - continue - anchor, positive = np.random.choice(label_indices, 2, replace=False) - n_pairs.append([anchor, positive]) - - n_pairs = np.array(n_pairs) - - n_negatives = [] - for i in range(len(n_pairs)): - negative = np.concatenate([n_pairs[:i, 1], n_pairs[i+1:, 1]]) - n_negatives.append(negative) - - n_negatives = np.array(n_negatives) - - return torch.LongTensor(n_pairs), torch.LongTensor(n_negatives) - - @staticmethod - def n_pair_loss(anchors, positives, negatives): - """ - Calculates N-Pair loss - :param anchors: A torch.Tensor, (n, embedding_size) - :param positives: A torch.Tensor, (n, embedding_size) - :param negatives: A torch.Tensor, (n, n-1, embedding_size) - :return: A scalar - """ - anchors = anchors.unsqueeze(1) - positives = positives.unsqueeze(1) - - # x = anchors.mm(negatives.sub(positives).transpose(1, 2)) - # x = torch.matmul(anchors, (negatives - positives).transpose(1, 2)) - # x = x.exp().sum(2) - x = (anchors-positives).pow(2).sum(2) - x = x - (anchors-negatives).pow(2).sum(2) - x[x > 0] = 0 - x[x < -0.5] = 0 - x = x.exp().sum(1) - loss = x.add(1).log().sum() - return loss - - @staticmethod - def l2_loss(anchors, positives): - """ - Calculates L2 norm regularization loss - :param anchors: A torch.Tensor, (n, embedding_size) - :param positives: A torch.Tensor, (n, embedding_size) - :return: A scalar - """ - return (anchors.pow(2) + positives.pow(2)).sum().div(float(anchors.size(0)))