两个句子之间的空间性,奇怪相似性

时间:2018-08-31 10:55:19

标签: python nlp spacy

我已经下载了en_core_web_lg模型并试图找到两个句子之间的相似性:

nlp = spacy.load('en_core_web_lg')

search_doc = nlp("This was very strange argument between american and british person")

main_doc = nlp("He was from Japan, but a true English gentleman in my eyes, and another one of the reasons as to why I liked going to school.")

print(main_doc.similarity(search_doc))

哪个返回值很奇怪:

0.9066019751888448

这两个句子的相似度不应 90%

为什么会这样?我是否需要添加某种额外的词汇表以使相似性结果更合理?

4 个答案:

答案 0 :(得分:5)

向量相似性的Spacy documentation解释了其基本概念:
每个单词都有一个向量表示法,可以通过上下文嵌入(Word2Vec)进行学习,并根据语料库对其进行训练,如文档中所述。

现在,完整句子的单词嵌入只是所有不同单词的平均值。如果您现在有很多单词在语义上位于同一区域(例如,“ he”,“ was”,“ this”,...等填充词)和附加词汇“ cancel out”,那么您最终可能会与您的情况相似。

正确的问题是您可以做什么:从我的角度来看,您可以想出一个更复杂的相似性度量。由于search_docmain_doc具有其他信息,例如原始句子,因此您可以通过长度差罚分来修改向量,或者尝试比较句子的较短部分,然后计算成对相似度(然后再次,问题是要比较哪些部分。

遗憾的是,目前还没有一种简单的方法可以简单地解决此问题。

答案 1 :(得分:5)

Spacy通过平均单词嵌入来构造句子嵌入。由于在一个普通的句子中有很多毫无意义的单词(称为stop words),所以您得到的结果很差。您可以这样删除它们:

search_doc = nlp("This was very strange argument between american and british person")
main_doc = nlp("He was from Japan, but a true English gentleman in my eyes, and another one of the reasons as to why I liked going to school.")

search_doc_no_stop_words = nlp(' '.join([str(t) for t in search_doc if not t.is_stop]))
main_doc_no_stop_words = nlp(' '.join([str(t) for t in main_doc if not t.is_stop]))

print(search_doc_no_stop_words.similarity(main_doc_no_stop_words))

或仅保留名词,因为它们具有最多的信息:

doc_nouns = nlp(' '.join([str(t) for t in doc if t.pos_ in ['NOUN', 'PROPN']))

答案 2 :(得分:5)

如其他人所述,您可能要使用通用句子编码器或推断。

对于Universal Sentence编码器,您可以安装用于管理TFHub包装的预构建SpaCy模型,因此只需安装带有pip的软件包即可使矢量和相似性按预期工作。

您可以按照此存储库中的说明操作(我是作者)https://github.com/MartinoMensio/spacy-universal-sentence-encoder-tfhub

  1. 安装模型:pip install https://github.com/MartinoMensio/spacy-universal-sentence-encoder-tfhub/releases/download/en_use_md-0.2.0/en_use_md-0.2.0.tar.gz#en_use_md-0.2.0

  2. 加载并使用模型

import spacy
# this loads the wrapper
nlp = spacy.load('en_use_md')

# your sentences
search_doc = nlp("This was very strange argument between american and british person")

main_doc = nlp("He was from Japan, but a true English gentleman in my eyes, and another one of the reasons as to why I liked going to school.")

print(main_doc.similarity(search_doc))
# this will print 0.310783598221594

答案 3 :(得分:1)

正如@dennlinger所指出的那样,Spacy的句子嵌入只是各个单词向量嵌入的平均值。因此,如果您的句子中带有否定词,例如“好”和“坏”,则它们的向量可能会相互抵消,从而导致上下文嵌入效果不佳。如果您的用例特定于获取句子嵌入,则应尝试使用以下SOTA方法。

  1. Google的通用句子编码器:https://tfhub.dev/google/universal-sentence-encoder/2

  2. Facebook的推断编码器:https://github.com/facebookresearch/InferSent

我已经尝试了这两种嵌入,并在大多数情况下为您提供了良好的效果,并使用词嵌入作为构建句子嵌入的基础。

干杯!