用于使嵌入相似的 Pytorch 损失函数
Pytorch Loss Function for making embeddings similar
我正在研究一个嵌入模型,其中有一个 BERT 模型,它接受文本输入并输出多维向量。该模型的目标是为相似的文本找到相似的嵌入(高余弦相似度),为不同的文本找到不同的嵌入(低余弦相似度)。
在小批量模式下训练时,BERT 模型给出 N*D
维输出,其中 N
是批量大小,D
是 BERT 模型的输出维度。
此外,我有一个维度为 N*N
的目标矩阵,如果 sentence[i]
和 sentence[j]
是 [i, j]
位置,则它包含 1
在意义上相似,如果不相似 -1
。
我想做的是通过查找 BERT 输出中所有嵌入的余弦相似度并将其与目标矩阵进行比较来找到整个批次的 loss/error。
我所做的只是将张量与其转置相乘,然后取元素 sigmoid。
scores = torch.matmul(document_embedding, torch.transpose(document_embedding, 0, 1))
scores = torch.sigmoid(scores)
loss = self.bceloss(scores, targets)
但这似乎不起作用。
还有其他方法吗?
P.S。我想做的和this paper.
中描述的方法类似
要计算两个向量之间的余弦相似度,您会使用 nn.CosineSimilarity
。但是,我认为这不允许您从一组 n
向量中获得对相似性。幸运的是,您可以通过一些张量操作自己实现它。
让我们调用 x
你的 document_embedding 形状 (n, d)
其中 d
是嵌入大小。我们将采用 n=3
和 d=5
。所以 x
由 [x1, x2, x3].T
.
组成
>>> x = torch.rand(n, d)
tensor([[0.8620, 0.9322, 0.4220, 0.0280, 0.3789],
[0.2747, 0.4047, 0.6418, 0.7147, 0.3409],
[0.6573, 0.3432, 0.5663, 0.2512, 0.0582]])
余弦相似度是归一化的点积。 x@x.T
matrix multiplication 将为您提供成对点积:其中包含:||x1||²
、<x1/x2>
、<x1/x3>
、<x2/x1>
、||x2||²
,等等...
>>> sim = x@x.T
tensor([[1.9343, 1.0340, 1.1545],
[1.0340, 1.2782, 0.8822],
[1.1545, 0.8822, 0.9370]])
要对所有范数的向量进行归一化:||x1||
、||x2||
和 ||x3||
:
>>> norm = x.norm(dim=1)
tensor([1.3908, 1.1306, 0.9680])
构造包含归一化因子的矩阵:||x1||²
、||x1||.||x2||
、||x1||.||x3||
、||x2||.||x1||
、||x2||²
等...
>>> factor = norm*norm.unsqueeze(1)
tensor([[1.9343, 1.5724, 1.3462],
[1.5724, 1.2782, 1.0944],
[1.3462, 1.0944, 0.9370]])
然后归一化:
>>> sim /= factor
tensor([[1.0000, 0.6576, 0.8576],
[0.6576, 1.0000, 0.8062],
[0.8576, 0.8062, 1.0000]])
或者,一种更快的方法 可以避免创建范数矩阵,即在乘法之前进行归一化:
>>> x /= x.norm(dim=1, keepdim=True)
>>> sim = x@x.T
tensor([[1.0000, 0.6576, 0.8576],
[0.6576, 1.0000, 0.8062],
[0.8576, 0.8062, 1.0000]])
对于损失函数,我会应用 nn.CrossEntropyLoss
straight away between the predicted similarity matrix and the target matrix, instead of applying sigmoid + BCE. Note: nn.CrossEntropyLoss
includes nn.LogSoftmax
。
我正在研究一个嵌入模型,其中有一个 BERT 模型,它接受文本输入并输出多维向量。该模型的目标是为相似的文本找到相似的嵌入(高余弦相似度),为不同的文本找到不同的嵌入(低余弦相似度)。
在小批量模式下训练时,BERT 模型给出 N*D
维输出,其中 N
是批量大小,D
是 BERT 模型的输出维度。
此外,我有一个维度为 N*N
的目标矩阵,如果 sentence[i]
和 sentence[j]
是 [i, j]
位置,则它包含 1
在意义上相似,如果不相似 -1
。
我想做的是通过查找 BERT 输出中所有嵌入的余弦相似度并将其与目标矩阵进行比较来找到整个批次的 loss/error。
我所做的只是将张量与其转置相乘,然后取元素 sigmoid。
scores = torch.matmul(document_embedding, torch.transpose(document_embedding, 0, 1))
scores = torch.sigmoid(scores)
loss = self.bceloss(scores, targets)
但这似乎不起作用。
还有其他方法吗?
P.S。我想做的和this paper.
中描述的方法类似要计算两个向量之间的余弦相似度,您会使用 nn.CosineSimilarity
。但是,我认为这不允许您从一组 n
向量中获得对相似性。幸运的是,您可以通过一些张量操作自己实现它。
让我们调用 x
你的 document_embedding 形状 (n, d)
其中 d
是嵌入大小。我们将采用 n=3
和 d=5
。所以 x
由 [x1, x2, x3].T
.
>>> x = torch.rand(n, d)
tensor([[0.8620, 0.9322, 0.4220, 0.0280, 0.3789],
[0.2747, 0.4047, 0.6418, 0.7147, 0.3409],
[0.6573, 0.3432, 0.5663, 0.2512, 0.0582]])
余弦相似度是归一化的点积。 x@x.T
matrix multiplication 将为您提供成对点积:其中包含:||x1||²
、<x1/x2>
、<x1/x3>
、<x2/x1>
、||x2||²
,等等...
>>> sim = x@x.T
tensor([[1.9343, 1.0340, 1.1545],
[1.0340, 1.2782, 0.8822],
[1.1545, 0.8822, 0.9370]])
要对所有范数的向量进行归一化:||x1||
、||x2||
和 ||x3||
:
>>> norm = x.norm(dim=1)
tensor([1.3908, 1.1306, 0.9680])
构造包含归一化因子的矩阵:||x1||²
、||x1||.||x2||
、||x1||.||x3||
、||x2||.||x1||
、||x2||²
等...
>>> factor = norm*norm.unsqueeze(1)
tensor([[1.9343, 1.5724, 1.3462],
[1.5724, 1.2782, 1.0944],
[1.3462, 1.0944, 0.9370]])
然后归一化:
>>> sim /= factor
tensor([[1.0000, 0.6576, 0.8576],
[0.6576, 1.0000, 0.8062],
[0.8576, 0.8062, 1.0000]])
或者,一种更快的方法 可以避免创建范数矩阵,即在乘法之前进行归一化:
>>> x /= x.norm(dim=1, keepdim=True)
>>> sim = x@x.T
tensor([[1.0000, 0.6576, 0.8576],
[0.6576, 1.0000, 0.8062],
[0.8576, 0.8062, 1.0000]])
对于损失函数,我会应用 nn.CrossEntropyLoss
straight away between the predicted similarity matrix and the target matrix, instead of applying sigmoid + BCE. Note: nn.CrossEntropyLoss
includes nn.LogSoftmax
。