nul*_*tto 4 python similarity cosine-similarity pytorch pairwise-distance
假设我们有一个 3D PyTorch 张量,其中第一个维度表示batch_size,如下所示:
import torch
import torch.nn as nn
x = torch.randn(32, 100, 25)
Run Code Online (Sandbox Code Playgroud)
也就是说,对于每个i,x[i]是一组 100 个 25 维向量。我想计算每个批次项目的这些向量的相似度(例如,余弦相似度——但一般来说是任何这样的成对距离/相似度矩阵)。
也就是说,对于每个x[i]我需要计算一个[100, 100]矩阵,其中包含上述向量的成对相似度。x[t]更具体地说,对于所有,该矩阵的第 (i,j) 个元素应包含 (100x25) 的第 i 行和第 j 行之间的相似度(或距离)t=1, ..., batch_size。
如果我使用torch.nn.CosineSimilarity(),无论dim我使用什么,结果都是[100, 25]( dim=0),或[32, 25]( dim=1) ,其中我需要大小为 的张量[32, 100, 100]。我希望torch.nn.CosineSimilarity()以这种方式工作(因为,至少对我来说,它看起来更直观) ,但事实并非如此。
可以使用类似下面的东西来完成吗?
torch.matmul(x, x.permute(0, 2, 1))
Run Code Online (Sandbox Code Playgroud)
我猜这可以给出距离矩阵,但是如果我需要任意成对运算怎么办?我应该使用上面的内容来构建这个操作吗?
或者也许我应该x以某种方式重复,以便我可以使用内置的torch.nn.CosineSimilarity()?
谢谢。
Nat*_*ell 10
文档暗示输入的形状cosine_similarity必须相等,但事实并非如此。PyTorch 内部通过 进行广播torch.mul,插入带有切片(或torch.unsqueeze)的维度将为您提供所需的结果。由于上下三角形的重复计算和内存,这不是最佳的,但它很简单:
import torch
from torch.nn import functional as F
from scipy.spatial import distance
# compute once in pytorch
x = torch.randn(32, 100, 25)
y = F.cosine_similarity(x[..., None, :, :], x[..., :, None, :], dim=-1)
assert y.shape == torch.Size([32, 100, 100])
# test against scipy by iterating over each batch element
z = []
for i in range(x.shape[0]):
slice = x[i, ...].numpy()
z.append(torch.tensor(distance.cdist(slice, slice, metric='cosine'), dtype=torch.float32))
# convert similarity to distance and ensure they're reasonably close
assert torch.allclose(torch.stack(z), 1.0-y)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11167 次 |
| 最近记录: |