如何使用来自BERT的嵌入来比较句子相似度

问题描述 投票:1回答:2

我正在使用HuggingFace Transformers软件包访问预训练的模型。由于我的用例需要英语和阿拉伯语的功能,因此我正在使用bert-base-multilingual-cased预训练模型。我需要能够使用余弦相似度来比较句子的相似度。要使用此功能,我首先需要为每个句子获取一个嵌入向量,然后可以计算余弦相似度。

首先,从BERT模型中提取语义嵌入的最佳方法是什么?喂完句子后,是否可以采用模型的最后隐藏状态?

import torch
from transformers import BertModel, BertTokenizer

model_class = BertModel
tokenizer_class = BertTokenizer
pretrained_weights = 'bert-base-multilingual-cased'

tokenizer = tokenizer_class.from_pretrained(pretrained_weights)
model = model_class.from_pretrained(pretrained_weights)

sentence = 'this is a test sentence'

input_ids = torch.tensor([tokenizer.encode(sentence, add_special_tokens=True)])
with torch.no_grad():
    output_tuple = model(input_ids)
    last_hidden_states = output_tuple[0]

print(last_hidden_states.size(), last_hidden_states)

[第二,如果这是从我的句子中获取嵌入的足够方法,那么我现在又遇到另一个问题,其中嵌入向量的长度取决于原始句子的长度而不同。输出的形状为[1, n, vocab_size],其中n可以具有任何值。

为了计算两个向量的余弦相似度,它们必须具有相同的长度。我该怎么办?像第一次在axis=1上求和一样幼稚的方法仍然可行吗?我还有什么其他选择?

python vector nlp cosine-similarity huggingface-transformers
2个回答
1
投票

您可以将[CLS]标记用作整个序列的表示。该令牌通常在预处理步骤中加在您的句子前。此令牌通常用于分类任务(请参见BERT paper中的图2和第3.2段)。

这是嵌入的第一个标记。

或者,您可以获取序列的平均向量(就像您在first(?)轴上所说的那样),根据huggingface documentation(第三个技巧),可以产生更好的结果。

[请注意,BERT并不是为使用余弦距离而设计的句子相似度设计的,尽管以我的经验,它的确产生了不错的结果。


0
投票

除了一个已经很好接受的答案之外,我想向您指出sentence-BERT,它更详细地讨论了相似性方面和特定度量(例如余弦相似性)的含义。他们也有一个在线sentence-BERT。这里的主要优点是,与“幼稚的”句子嵌入比较相比,它们似乎获得了很多处理速度,但是我对实现本身还不够熟悉。

重要的是,通常要在什么样的相似性中有一个更细粒度的区别。为此,SemEval 2014的very convenient implementation之一(SICK数据集)中也进行了精彩的讨论,对此进行了更详细的介绍。从您的任务描述中,我假设您已经在使用来自以后SemEval任务之一的数据,该任务也将其扩展到了多语言相似性。

© www.soinside.com 2019 - 2024. All rights reserved.