我编写了一个 BiLSTM-Siamese 网络,使用成对距离和余弦相似度来测量字符串相似度,详细信息如下:
class SiameseNetwork(nn.Module):
def __init__(self, num_layers, dropout, weight_matrix, vocabs, similarity_measure):
super(SiameseNetwork, self).__init__()
self.lstm_network = BiLSTM(num_layers, weight_matrix, vocabs)
self.fc_drop = nn.Dropout(p = dropout)
self.similarity_measure = similarity_measure
if self.similarity_measure == 'euclidean_distance':
self.sm = nn.PairwiseDistance(p=2)
else:
self.sm = nn.functional.cosine_similarity
def forward(self, input1, input2):
output1 = self.lstm_network(input1)
output2 = self.lstm_network(input2)
out1 = self.fc_drop(output1)
out2 = self.fc_drop(output2)
x = self.sm(out1, out2)
if self.similarity_measure == 'euclidean_distance':
x = 1-x # The larger the x value is, the more similar the strings are.
x = torch.sigmoid(x)
return x
我使用torch.sigmoid使相似度在0和1之间。但是,sigmoid使同一字符串对的相似度,而不是1。因此,我需要知道如何使相似度的范围在0范围内-1 使用成对距离和余弦相似度。如果字符串对不相似,则为 0;如果字符串对相似,则为 1。任何帮助将不胜感激。谢谢!
有很多方法可以解决您的问题。对于
cosine similariry
的情况,输出应该已经在 [-1,1]
范围内,现在您可以选择将所有小于 0
的值剪辑为 0
(推荐),例如:
x = torch.clamp(x, 0, 1)
或将它们缩放到
[0,1]
范围内(不推荐):
x = (x + 1)/2
对于
euclidian distance
的情况,你的做法是正确的。如果您希望阈值“更难”,请考虑:
x = torch.sigmoid(alpha * x) ## with alpha > 1 make the result more aggresive toward 0 and 1
或者因为
x
是距离,在所有情况下都使得 x >= 0
,您可以使用任何指数函数来计算相似度,例如:
x = self.sm(out1, out2)
x = torch.exp( - alpha * x) ## alpha > 0
需要注意的是,在
sigmoid
情况下不应使用 cosine similarity
。