【问题标题】:Cosine Similarity on large matrix大矩阵的余弦相似度
【发布时间】:2020-01-28 21:20:08
【问题描述】:

我正在尝试计算所有大矩阵对 (3m x 2048) 之间的余弦距离,并使用 pytorch 提取前 30 个相似向量。 以下是我的代码,它工作正常,但每次迭代大约需要 30 秒,这对于 300 万个词向量来说太长了。 有什么加快速度的想法吗?

import torch.nn.functional as F
import torch
from tqdm import tqdm
import gc



sym_dict={}
tmp_list=[]

tot_dict=torch.load('xbx.pt')


all_tensors = torch.cat([v.unsqueeze(0) for k,v in tot_dict.items()], dim=0)
token_list= [i for i in tot_dict.keys()]

del tot_dict
gc.collect()



for counter ,value in tqdm(enumerate(token_list)):


  uniq_vec=torch.unsqueeze(all_tensors[counter],dim=0)

  dist = 1 - F.cosine_similarity(uniq_vec,all_tensors)
  index_sorted = torch.argsort(dist)


  roll_me=index_sorted[:30].cpu().numpy().tolist()

  for ind in roll_me:
    tmp_list.append(token_list[ind])
  sym_dict.update({value:tmp_list})
  tmp_list=[]



#save .pt file
torch.save(sym_dict,'sym_dict.pt')

【问题讨论】:

  • 张量的形状、每个循环试图做什么等一些细节会让我们更容易回答
  • 每个张量的形状 (1x2048) 表示一个词嵌入向量。整个矩阵由 300 万个词向量组成,因此其形状为 (3M x 2048)。每个循环将一个向量与整个矩阵进行比较,以使用余弦距离找到前 30 个最近的向量。应该这样比较 3M 个词向量中的每一个,以便我们可以找到每个词的 top30 列表

标签: python numpy pytorch cosine-similarity


【解决方案1】:

直接找到两个矩阵之间的成对距离会起作用吗?代码如下:

def pairwise_dist(x, y,p=2, eps=1e-6):
    x_a  =x[..., None, :, :]
    y_a  =y[...,None,:]
    dist = torch.pow(torch.abs((x_a - y_a) + eps), p).sum(dim=-1, keepdim=True).squeeze(2)
    return torch.pow(dist, 1/p)

t1 = torch.rand(3, 10)
t2 = torch.rand(4,10)
dist = pairwise_dist(t1,t2, eps=0)
print(dist)

dist 的形状为4 x 3,其中每一行表示t1 的所有向量与t2 向量的距离。

请注意,这里两个向量之间的成对距离与 Pytorch 的 F. pairwise_distance 完全相同。

【讨论】:

  • 即使是小尺寸的矩阵也会消耗所有内存(测试了 10,000 个词向量)
猜你喜欢
  • 2015-07-17
  • 2019-12-23
  • 2021-08-20
  • 2012-07-09
  • 2017-06-13
  • 2016-09-08
  • 2020-10-28
  • 2014-03-25
  • 2016-10-22
相关资源
最近更新 更多