pytorch “torch.einsum”API如何工作?

wqsoz72f  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(163)

torch.einsum API如何工作?
我想知道torch.einsum("ac,bc->ab",norm_max_func_embedding,norm_nl_embedding)是如何计算相似度的?
我知道这是在操作Tensor。
我认为“ac”指定一个维度为(a,c)的Tensor。但“bc->ab”是做什么的。如何计算相似度。我假设相似度可以通过余弦相似度或欧几里得距离来计算。

# Encode maximum function
func = "def f(a,b): if a>b: return a else return b"
tokens_ids = model.tokenize([func],max_length=512,mode="<encoder-only>")
source_ids = torch.tensor(tokens_ids).to(device)
tokens_embeddings,max_func_embedding = model(source_ids)

# Encode minimum function
func = "def f(a,b): if a<b: return a else return b"
tokens_ids = model.tokenize([func],max_length=512,mode="<encoder-only>")
source_ids = torch.tensor(tokens_ids).to(device)
tokens_embeddings,min_func_embedding = model(source_ids)

norm_max_func_embedding = torch.nn.functional.normalize(max_func_embedding, p=2, dim=1)
norm_min_func_embedding = torch.nn.functional.normalize(min_func_embedding, p=2, dim=1)
norm_nl_embedding = torch.nn.functional.normalize(nl_embedding, p=2, dim=1)

max_func_nl_similarity = torch.einsum("ac,bc->ab",norm_max_func_embedding,norm_nl_embedding)
min_func_nl_similarity = torch.einsum("ac,bc->ab",norm_min_func_embedding,norm_nl_embedding)

我指的是这个github repository:https://github.com/microsoft/CodeBERT/tree/master/UniXcoder
它衡量的是什么样的相似性?
任何帮助或指向文件是高度赞赏。

6jjcrrmo

6jjcrrmo1#

ac,bc->ab表示两个输入Tensor和一个输出Tensor。左手侧标记输入的尺寸,用逗号分隔。右侧显示了输出Tensor的维度(->之后的所有内容)。

  • 第一个输入Tensor的维度为ac
  • 第二个输入Tensor的维度为bc

由于c是两个Tensor共享的,所以两个Tensor的维数必须相同。另外两个维度是“自由”的。

  • 输出Tensor的维度为ab

由于c没有出现在输出中,因此我们沿该维度进行和积沿着。如果c确实出现在输出中,它将只是一个产品。例如ab,ab->ab是两个相同形状矩阵的元素乘积。
维度的顺序很重要。例如,ab->ba是一个转置操作。

hwamh0ep

hwamh0ep2#

@MadPhysicist的答案是对正在发生的事情的一个很好的对象级描述,但我想为正在计算的东西提供一种直觉。
如果你想象两个输入矩阵的每一行都代表一个向量,那么torch.einsum("ac,bc->ab", A, B)就是计算A中的每个向量与B中的每个向量的点积。
换句话说,在结果矩阵M中,数M[i,j]表示A[i]和B[j]的点积。您可以将其视为类似于cdist
你也可以把它看作余弦相似度。如果向量是标准化的(并且所示的代码在前一步中对它们进行了标准化),那么点积等价于余弦相似性。
这里有一个代码示例,你可以使用它来建立对正在发生的事情的直觉:

import numpy as np
import scipy
# Generate random matricies
matrix1 = np.random.rand(3,3)
matrix2 = np.random.rand(3,3)
# Normalize matrix to have length 1 in each row vector
matrix1 /= np.linalg.norm(matrix1, axis=1)[:, np.newaxis]
matrix2 /= np.linalg.norm(matrix2, axis=1)[:, np.newaxis]
print("matrix1")
print(matrix1)
print("matrix2")
print(matrix2)
# Compute dot products / cosine similarity using einsum
print("einsum")
print(np.einsum("ac,bc->ab",matrix1, matrix2))
# Note: cdist computes cosine "distance," not similarity
print("cdist")
print(1 - scipy.spatial.distance.cdist(matrix1, matrix2, metric="cosine"))

相关问题