def forward(self, x): x1 = self.encoder(x[0]) x2 = self.encoder(x[1]) x3 = self.encoder(x[2]) dap = torch.pairwise_distance(x1, x2) dan = torch.pairwise_distance(x1, x3) return dap, dan, self.decoder(x1), self.decoder(x3)
def mmd(x, y, sigmas=[1, 5, 10], normalize=False): """Maximum Mean Discrepancy with several Gaussian kernels.""" # Flatten: x = x.view(x.shape[0], -1) y = y.view(y.shape[0], -1) if len(sigmas) == 0: mean_dist = torch.mean(torch.pow(torch.pairwise_distance(x, y, p=2), 2)) factors = (-1 / (2 * mean_dist)).view(1, 1, 1) else: factors = _get_mmd_factor(sigmas, x.device) if normalize: x = F.normalize(x, p=2, dim=1) y = F.normalize(y, p=2, dim=1) xx = torch.pairwise_distance(x, x, p=2)**2 yy = torch.pairwise_distance(y, y, p=2)**2 xy = torch.pairwise_distance(x, y, p=2)**2 k_xx, k_yy, k_xy = 0, 0, 0 div = 1 / (x.shape[1]**2) k_xx = div * torch.exp(factors * xx).sum(0).squeeze() k_yy = div * torch.exp(factors * yy).sum(0).squeeze() k_xy = div * torch.exp(factors * xy).sum(0).squeeze() mmd_sq = torch.sum(k_xx) - 2 * torch.sum(k_xy) + torch.sum(k_yy) return torch.sqrt(mmd_sq)
def forward(self, x1, x2, y): d = torch.pairwise_distance(x1, x2, keepdim=False) margin = 1. d = torch.pairwise_distance(x1, x2, keepdim=False) zero_tensor = torch.Tensor([0] * d.shape[0]) loss = 0.5 * y * d * d + 0.5 * (1 - y) * torch.max( zero_tensor, margin - d) * torch.max(zero_tensor, margin - d) return torch.mean(loss)
def tripletmarginloss_reference(anchor, positive, negative, margin=1.0, p=2, eps=1e-6, swap=False, size_average=True, reduce=True): d_p = torch.pairwise_distance(anchor, positive, p, eps) d_n = torch.pairwise_distance(anchor, negative, p, eps) if swap: d_s = torch.pairwise_distance(positive, negative, p, eps) d_n = torch.min(d_n, d_s) output = torch.clamp(margin + d_p - d_n, min=0.0) if reduce and size_average: return output.mean() elif reduce: return output.sum() return output
def tripletmarginloss_reference(anchor, positive, negative, margin=1.0, p=2, eps=1e-6, swap=False, reduction='elementwise_mean'): d_p = torch.pairwise_distance(anchor, positive, p, eps) d_n = torch.pairwise_distance(anchor, negative, p, eps) if swap: d_s = torch.pairwise_distance(positive, negative, p, eps) d_n = torch.min(d_n, d_s) output = torch.clamp(margin + d_p - d_n, min=0.0) if reduction == 'elementwise_mean': return output.mean() elif reduction == 'sum': return output.sum() return output
def outer_pairwise_distance(A, B=None): """ Compute pairwise_distance of Tensors A (size(A) = n x d, where n - rows count, d - vector size) and B (size(A) = m x d, where m - rows count, d - vector size) return matrix C (size n x m), such as C_ij = distance(i-th row matrix A, j-th row matrix B) if only one Tensor was given, computer pairwise distance to itself (B = A) """ if B is None: B = A max_size = 2**26 n = A.size(0) m = B.size(0) d = A.size(1) if n * m * d <= max_size or m == 1: return torch.pairwise_distance( A[:, None].expand(n, m, d).reshape((-1, d)), B.expand(n, m, d).reshape((-1, d))).reshape((n, m)) else: batch_size = max(1, max_size // (n * d)) batch_results = [] for i in range((m - 1) // batch_size + 1): id_left = i * batch_size id_rigth = min((i + 1) * batch_size, m) batch_results.append( outer_pairwise_distance(A, B[id_left:id_rigth])) return torch.cat(batch_results, dim=1)
def stest_one_versus_many(model, data_dir, img_size): """ """ data_iterator = iter( DataLoader( PairDataset( data_dir, transform=transforms.Compose([ transforms.Grayscale(), transforms.Resize(img_size), transforms.ToTensor(), ]), split=SplitEnum.testing, ), num_workers=0, batch_size=1, shuffle=True, )) x0, *_ = next(data_iterator) for i in range(10): _, x1, _ = next(data_iterator) dis = (torch.pairwise_distance(*model( to_tensor(x0, device=global_torch_device()), to_tensor(x1, device=global_torch_device()), )).cpu().item()) boxed_text_overlay_plot( torchvision.utils.make_grid(torch.cat((x0, x1), 0)), f"Dissimilarity: {dis:.2f}", )
def minimal_mean_distance(self, other, p=2): mean_distances = [] for i in range(self.vertices): rolled = self.roll(i).float() distances = torch.pairwise_distance(rolled, other.to_float(), p=p) mean_distances.append(distances.mean().item()) return min(mean_distances)
def _test(metric_device): engine = Engine(update) m = MeanPairwiseDistance(device=metric_device) m.attach(engine, "mpwd") data = list(range(n_iters)) engine.run(data=data, max_epochs=1) assert "mpwd" in engine.state.metrics res = engine.state.metrics["mpwd"] true_res = [] for i in range(n_iters * idist.get_world_size()): true_res.append( torch.pairwise_distance( y_true[i * s : (i + 1) * s, ...], y_preds[i * s : (i + 1) * s, ...], p=m._p, eps=m._eps ) .cpu() .numpy() ) true_res = np.array(true_res).ravel() true_res = true_res.mean() assert pytest.approx(res) == true_res
def get_working_points(self, spatial1, spatial2, truth, margin): """ Args: spatial (``torch.tensor``, required): The spatial embedding of the data truth (``torch.tensor``, required): The truth graph of the data Returns: ``torch.tensor``: The R95, R98, R99 values """ margin_multiple = 1 max_dist = torch.tensor(margin_multiple * margin).float().to( self.device) distances = torch.pairwise_distance(spatial1[truth[0]], spatial2[truth[1]]) # Sort the distances distances, indices = torch.sort(distances, descending=False) working_radii = [ min( distances[int( len(distances) * (working_point_efficiency / 100))], max_dist).item() for working_point_efficiency in self.hparams["working_points"] ] return working_radii
def eval(model, criterion, dataloader, log_interval=50): model.eval() running_loss = 0 number_samples = 0 distances = [] for batch_idx, (x1, x2, y) in enumerate(dataloader): x1, x2, y = x1.to(device), x2.to(device), y.to(device) x1, x2 = model(x1, x2) loss = criterion(x1, x2, y) distances.extend( zip( torch.pairwise_distance(x1, x2, 2).cpu().tolist(), y.cpu().tolist())) number_samples += len(x1) running_loss += loss.item() * len(x1) if (batch_idx + 1) % log_interval == 0 or batch_idx == len(dataloader) - 1: print('{}/{}: Loss: {:.4f}'.format(batch_idx + 1, len(dataloader), running_loss / number_samples)) distances, y = zip(*distances) distances, y = torch.tensor(distances), torch.tensor(y) max_accuracy = accuracy(distances, y) print(f'Max accuracy: {max_accuracy}') return running_loss / number_samples, max_accuracy
def __call__(self, x): """Clustering. Args: x (Tensor) - Data points of number n by feature dim m. """ idx = np.random.choice(len(x), self.n_clusters) state = x[idx] while True: pre_state = state.clone() dis = setwise_distance(x, state).squeeze() result = torch.argmin(dis, dim=1) for i in range(self.n_clusters): idx = torch.nonzero(result == i).squeeze() items = torch.index_select(x, 0, idx) if items.size(0): state[i] = items.mean(dim=0) else: state[i] = pre_state[i].clone() shift = torch.pairwise_distance(pre_state, state) total = torch.pow(torch.sum(shift), 2.0) if total < self.tol: return result, state
def stest_many_versus_many(model, data_dir, img_size, threshold=0.5): """ """ data_iterator = iter( DataLoader( PairDataset( data_dir, transform=transforms.Compose([ transforms.Grayscale(), transforms.Resize(img_size), transforms.ToTensor(), ]), ), num_workers=0, batch_size=1, shuffle=True, )) for i in range(10): x0, x1, is_diff = next(data_iterator) distance = (torch.pairwise_distance(*model( to_tensor(x0, device=global_torch_device()), to_tensor(x1, device=global_torch_device()), )).cpu().item()) boxed_text_overlay_plot( torchvision.utils.make_grid(torch.cat((x0, x1), 0)), f"Truth: {'Different' if is_diff.cpu().item() else 'Alike'}," f" Dissimilarity: {distance:.2f}," f" Verdict: {'Different' if distance > threshold else 'Alike'}", )
def get_working_points(self, spatial1, spatial2, truth): """ Args: spatial (``torch.tensor``, required): The spatial embedding of the data truth (``torch.tensor``, required): The truth graph of the data Returns: ``torch.tensor``: The R95, R98, R99 values """ margin_multiple = 1 max_dist = torch.tensor(margin_multiple * self.hparams["margin"]).float().to(self.device) # Get the R95, R98, R99 values # distances = torch.sum((spatial[truth[0]] - spatial[truth[1]])**2, dim=-1) distances = torch.pairwise_distance(spatial1[truth[0]], spatial2[truth[1]]) # Sort the distances distances, indices = torch.sort(distances, descending=False) # Get the indices of the 95th, 98th, 99th percentile R95 = min(distances[int(len(distances) * 0.95)], max_dist) R98 = min(distances[int(len(distances) * 0.98)], max_dist) R99 = min(distances[int(len(distances) * 0.99)], max_dist) return R95.item(), R98.item(), R99.item()
def get_distance(trajectories): euclid_distance = [] for a, b in zip(trajectories[:, :], trajectories[1:, :]): dist = torch.pairwise_distance(a, b) dist = dist.cpu().detach().numpy() euclid_distance.append(dist.reshape(1, -1)) euclid_distance = torch.from_numpy(np.concatenate(euclid_distance, axis=0)).type(torch.float) return euclid_distance
def distance_measure(ref, target): ref = ref.unsqueeze(0) target = target.unsqueeze(0) euc_dist = torch.pairwise_distance(ref, target) cos_dist = 1 - torch.nn.functional.cosine_similarity(ref, target) query_dist = euc_dist.item() / 200.0 + cos_dist.item( ) # the coefficients are taken from the original implementation. return query_dist
def fake_speed(fake_traj): output_speed = [] for a, b in zip(fake_traj[:, :], fake_traj[1:, :]): dist = torch.pairwise_distance(a, b) speed = dist / 0.4 output_speed.append(speed.view(1, -1)) output_fake_speed = torch.cat(output_speed, dim=0).unsqueeze(dim=2).permute(1, 0, 2) return output_fake_speed
def evaluate_model_pairwise(model, loss, g1, g2, prec_k=(1, 3, 5, 10, 30), compute_accuracy=False): model.eval() metrics = {} metrics['pair'] = g1.graph_name + '-->' + g2.graph_name pos_anchor_idx = g1.anchor_data[g2.gidx]['anchor_edge_index'] neg_anchor_idx = g1.anchor_data[g2.gidx]['negative_anchor_edge_index'] print(">>> Evaluating model...") x1, x2 = model(g1, g2, edge_index_labels=('anchor_edge_index', 'negative_anchor_edge_index')) if loss == 'contrastive': euc_dist = torch.pairwise_distance(x1, x2, keepdim=True) model_pred = 1. / (1. + euc_dist) elif loss == 'cosine': cos = torch.nn.CosineSimilarity(dim=1, eps=1e-6) model_pred = 1. - 0.5 * (1. - cos(x1, x2)) elif loss == 'BCE': model_pred = torch.sigmoid(torch.einsum("ef,ef->e", x1, x2)) else: raise NotImplementedError("Loss function not implemented") model_pred = model_pred.detach().numpy() anchor_idx = torch.cat([pos_anchor_idx, neg_anchor_idx], dim=-1).detach().numpy() true_anchor_idx = list(map(tuple, pos_anchor_idx.numpy().T)) ####### Computing Accuracy ####### if compute_accuracy: print(">>> Computing accuracy...") pred_anchor_idx = greedy_matching(anchor_idx, model_pred) metrics['accuracy'] = accuracy(true_anchor_idx, pred_anchor_idx) ####### Computing Precision ####### print(">>> Computing precision metrics...") ordered_sim = soft_ordering(anchor_idx, model_pred) for k in prec_k: metrics['precision@' + str(k)] = precision(true_anchor_idx, ordered_sim, k) metrics['MAP'] = MAP(true_anchor_idx, ordered_sim) return metrics
def batched_eucl(coord): """Compute adjacency matrix for a batched coordinates Tensor `c`. https://github.com/pytorch/pytorch/issues/9406#issuecomment-472269698 """ B, M, N = coord.shape return t.pairwise_distance( coord[:, :, None].expand(B, M, M, N).reshape((-1, N)), coord[:, None].expand(B, M, M, N).reshape((-1, N)), ).reshape((B, M, M))
def print_closest(word_map, word, n=10): """ Sanity check for the pre-trained embedding: >> WORKING """ word_idx = {i: v for v, i in word_map.items()} idx = word_map[word] vector = embedding[idx] distances = torch.pairwise_distance(embedding, vector) _, idx = distances.sort(descending=False) for k in range(n): print(word_idx[idx[k].item()])
def update(self, homography, src_pts, dst_pts, src_confs, dst_confs, src_img_size, dst_img_size): """ Updates the internal evaluation result. Parameters ---------- homography : torch.Tensor Homography (from source image to destination one). src_pts : torch.Tensor Detected points for the first (source) image. dst_pts : torch.Tensor Detected points for the second (destination) image. src_confs : torch.Tensor Confidences for detected points on the source image. dst_confs : torch.Tensor Confidences for detected points on the destination image. src_img_size : tuple of 2 int Size (H, W) of the source image. dst_img_size : tuple of 2 int Size (H, W) of the destination image. """ # from scipy.spatial.distance import pdist from scipy.optimize import linear_sum_assignment with torch.no_grad(): src_hmg_pts = self.calc_homogeneous_coords(src_pts.float()) dst_hmg_pts = self.calc_homogeneous_coords(dst_pts.float()) self.filter_inside_points(src_hmg_pts, src_confs, homography, dst_img_size) self.filter_inside_points(dst_hmg_pts, dst_confs, homography.inverse(), src_img_size) src_pts_count = src_hmg_pts.shape[0] dst_pts_count = dst_hmg_pts.shape[0] pts_count = min(src_pts_count, dst_pts_count, 100) assert (pts_count > 0) src_hmg_pts = self.filter_best_points(src_hmg_pts, src_confs, pts_count) dst_hmg_pts = self.filter_best_points(dst_hmg_pts, dst_confs, pts_count) preds_dst_hmg_pts = self.transform_points(src_hmg_pts, homography) cost = torch.pairwise_distance( x1=preds_dst_hmg_pts, x2=dst_hmg_pts).cpu().detach().numpy() row_ind, col_ind = linear_sum_assignment(cost) mean_resudual = cost[row_ind, col_ind].sum() mean_resudual *= (100.0 / dst_img_size[0]) self.sum_metric += mean_resudual self.global_sum_metric += mean_resudual self.num_inst += 1 self.global_num_inst += 1
def _test(y_pred, y, batch_size): mpd.reset() if batch_size > 1: n_iters = y.shape[0] // batch_size + 1 for i in range(n_iters): idx = i * batch_size mpd.update((y_pred[idx : idx + batch_size], y[idx : idx + batch_size])) else: mpd.update((y_pred, y)) np_res = np.mean(torch.pairwise_distance(y_pred, y, p=mpd._p, eps=mpd._eps).numpy()) assert isinstance(mpd.compute(), float) assert pytest.approx(mpd.compute()) == np_res
def _test_distrib_itegration(device): import numpy as np import torch.distributed as dist from ignite.engine import Engine rank = dist.get_rank() torch.manual_seed(12) n_iters = 100 s = 50 offset = n_iters * s y_true = torch.rand(offset * dist.get_world_size(), 10).to(device) y_preds = torch.rand(offset * dist.get_world_size(), 10).to(device) def update(engine, i): return ( y_preds[i * s + offset * rank : (i + 1) * s + offset * rank, ...], y_true[i * s + offset * rank : (i + 1) * s + offset * rank, ...], ) engine = Engine(update) m = MeanPairwiseDistance(device=device) m.attach(engine, "mpwd") data = list(range(n_iters)) engine.run(data=data, max_epochs=1) assert "mpwd" in engine.state.metrics res = engine.state.metrics["mpwd"] true_res = [] for i in range(n_iters * dist.get_world_size()): true_res.append( torch.pairwise_distance( y_true[i * s : (i + 1) * s, ...], y_preds[i * s : (i + 1) * s, ...], p=m._p, eps=m._eps, ) .cpu() .numpy() ) true_res = np.array(true_res).ravel() true_res = true_res.mean() assert pytest.approx(res) == true_res
def forward(self, x1, x2, y): ''' Shapes: ------- x1: [B,C] x2: [B,C] y: [B,1] Returns: -------- loss: [B,1]] ''' distance = torch.pairwise_distance(x1, x2, p=2) loss = self.alpha * (1-y) * distance**2 + \ self.beta * y * (torch.max(torch.zeros_like(distance), self.margin - distance)**2) return torch.mean(loss, dtype=torch.float)
def contrastive_loss(self, x1, x2, y): margin = 1. d = torch.pairwise_distance(x1, x2, keepdim=False) d = d.tolist() y = y.tolist() loss = [] for i, item in enumerate(d): loss.append(0.5 * y[i] * item * item + 0.5 * (1 - y[i]) * max(0, (margin - item)) * max(0, (margin - item))) loss = np.array(loss) loss_mean = torch.Tensor([loss.mean()]) return Variable(loss_mean, requires_grad=True)
def pdist2(x, y): """ Compute distance between each pair of row vectors in x and y Args: x: tensor of shape n*p y: tensor of shape m*p Returns: dist: tensor of shape n*m """ p = x.shape[1] n = x.shape[0] m = y.shape[0] xtile = torch.cat([x] * m, dim=1).view(-1, p) ytile = torch.cat([y] * n, dim=0) dist = torch.pairwise_distance(xtile, ytile) return dist.view(n, m)
def get_query_x(self, Query_x, centroid_per_class, Query_y_labels): """ Returns distance matrix from each Query image to each centroid. """ centroid_matrix = self.get_centroid_matrix(centroid_per_class, Query_y_labels) Query_x = self.f(Query_x) m = Query_x.size(0) n = centroid_matrix.size(0) centroid_matrix = centroid_matrix.expand(m, centroid_matrix.size(0), centroid_matrix.size(1)) Query_matrix = Query_x.expand( n, Query_x.size(0), Query_x.size(1)).transpose(0, 1) # Expanding Query matrix "n" times Qx = torch.pairwise_distance(centroid_matrix.transpose(1, 2), Query_matrix.transpose(1, 2)) return Qx
def forward( self, sequence_a: TextFieldTensors, sequence_b: TextFieldTensors, distance: Optional[torch.Tensor] = None, ) -> Dict[str, torch.Tensor]: embedded_sequence_a = self.encode_sequence(sequence_a) embedded_sequence_b = self.encode_sequence(sequence_b) euclidian_distance = torch.pairwise_distance(embedded_sequence_a, embedded_sequence_b) output_dict = { "edit_distance": euclidian_distance, "emb_sequence_a": embedded_sequence_a, "emb_sequence_b": embedded_sequence_b, } if distance is not None: loss = self._loss(euclidian_distance, distance.view(-1)) output_dict["loss"] = loss return output_dict
def get_query_x(self, Query_x, centroid_per_class, Query_y_labels): """ Returns distance matrix from each Query image to each centroid. """ centroid_matrix = self.get_centroid_matrix( centroid_per_class, Query_y_labels) Query_x = self.f(Query_x) m = Query_x.size(0) n = centroid_matrix.size(0) # The below expressions expand both the matrices such that they become compatible to each other in order to caclulate L2 distance. # Expanding centroid matrix to "m". centroid_matrix = centroid_matrix.expand( m, centroid_matrix.size(0), centroid_matrix.size(1)) Query_matrix = Query_x.expand(n, Query_x.size(0), Query_x.size( 1)).transpose(0, 1) # Expanding Query matrix "n" times Qx = torch.pairwise_distance(centroid_matrix.transpose( 1, 2), Query_matrix.transpose(1, 2)) return Qx
def get_adjacency_eu(self, x, y): # x,y:[1, 2704, 256] # A = torch.matmul(x, y.transpose(1, 2)) A = torch.rand(x.shape[1], y.shape[1]) # [2704, 2704] for i in range(x.shape[1]): # A[i][j] = torch.sqrt(torch.sum((x[0][i] - y[0][j])**2)) A[i] = torch.pairwise_distance(x[0][i].unsqueeze(0).cpu(), y[0].cpu(), p=2) temp = torch.ones_like(A) * 100 A = temp - A _, idx = torch.topk(A, k=10, dim=-1, largest=True) for i in range(idx.shape[0]): # [2704, 10] for index in idx[i]: A[i][index] = 1 zero = torch.zeros_like(A) A = torch.where(A == 1, A, zero).unsqueeze(0) return A