Machine learning 如何计算一个矩阵中所有行相对于另一个矩阵中所有行的余弦_相似性

Machine learning 如何计算一个矩阵中所有行相对于另一个矩阵中所有行的余弦_相似性,machine-learning,neural-network,pytorch,Machine Learning,Neural Network,Pytorch,在pytorch中,假设我有2个矩阵,我如何计算每个矩阵中所有行与另一个矩阵中所有行的余弦相似性 比如说 给定输入= matrix_1 = [a b] [c d] matrix_2 = [e f] [g h] 我希望输出是 输出= [cosine_sim([a b] [e f]) cosine_sim([a b] [g h])] [cosine_sim([c d] [e f]) cosine_sim([c d] [g h])] 目前

在pytorch中,假设我有2个矩阵,我如何计算每个矩阵中所有行与另一个矩阵中所有行的余弦相似性

比如说

给定输入=

matrix_1 = [a b] 
           [c d] 
matrix_2 = [e f] 
           [g h]
我希望输出是

输出=

 [cosine_sim([a b] [e f])  cosine_sim([a b] [g h])]
 [cosine_sim([c d] [e f])  cosine_sim([c d] [g h])] 
目前,我正在使用torch.nn.functional.cosine_similarity(矩阵_1,矩阵_2),它返回该行的余弦,而另一个矩阵中只有对应的行

在我的示例中,我只有2行,但我想要一个适用于多行的解决方案。我甚至想处理每个矩阵中的行数不同的情况


我意识到我可以使用expand,但是我想在不使用如此大的内存占用的情况下使用它。

通过手动计算相似性并使用矩阵乘法+转置:

导入火炬
从scipy导入空间
将numpy作为np导入
a=火炬。随机数(2,2)
b=火炬。randn(3,2)#不同的行号,为了好玩
#假设cos_sim(u,v)=点(u,v)/(范数(u)*范数(v))
#=点(u/norm(u),v/norm(v))
#我们首先对行进行标准化,然后通过换位计算行的点积:
a_norm=a/a.norm(dim=1)[:无]
b_norm=b/b.norm(dim=1)[:,无]
res=torch.mm(a_范数,b_范数转置(0,1))
打印(res)
#  0.9978 -0.9986 -0.9985
# -0.8629  0.9172  0.9172
# -------
#让我们使用numpy/scipy验证我们的计算是否正确:
a_n=a.numpy()
b_n=b.numpy()
res_n=np.零((2,3))
对于范围(2)中的i:
对于范围(3)内的j:
#cos_sim(u,v)=1-cos_dist(u,v)
res_n[i,j]=1-空间距离余弦(a_n[i],b_n[j])
打印(分辨率)
# [[ 0.9978022  -0.99855876 -0.99854881]
#  [-0.86285472  0.91716063  0.9172349 ]]

根据benjaminplanche的回答,为数值稳定性添加
eps

def sim_矩阵(a、b、eps=1e-8):
"""
为数值稳定性增加eps
"""
a_n,b_n=a.norm(dim=1)[:无],b.norm(dim=1)[:无]
a_norm=a/torch.max(a_n,eps*torch.one_like(a_n))
b_norm=b/torch.max(b_n,eps*torch.one_like(b_n))
sim_mt=torch.mm(a_范数,b_范数转置(0,1))
返回sim_mt
与的答案相同,但使用了clamp而不是max,并且没有创建新的张量。我用timeit做了一个小测试,这表明夹钳更快,尽管我不擅长使用那个工具

def sim_matrix(a, b, eps=1e-8):
    """
    added eps for numerical stability
    """
    a_n, b_n = a.norm(dim=1)[:, None], b.norm(dim=1)[:, None]
    a_norm = a / torch.clamp(a_n, min=eps)
    b_norm = b / torch.clamp(b_n, min=eps)
    sim_mt = torch.mm(a_norm, b_norm.transpose(0, 1))
    return sim_mt

如果性能不是问题,则从sklearn.metrics.pairwise导入余弦相似性矩阵1=矩阵1.cpu().detach().numpy()矩阵2=矩阵2.cpu().detach().numpy()余弦相似性(矩阵1,矩阵2)您查看过pytorch API吗?我发现pytorch API的问题与子问题OP一起发布。pytorch API无法处理不同大小的张量。pytorch API是否更可靠?是否可以使用pytorch API计算余弦距离?