spaCy能够比较两个对象,并预测它们的相似程度。 预测相似性对于构建推荐系统或标记重复项很有用。 例如,您可以建议与当前正在查看的用户内容相似的用户内容,或者将支持凭单标记为与现有内容非常相似的副本。
每个Doc、Span和Token都有一个.similarity()方法,它允许您将其与另一个对象进行比较,并确定相似度。当然,相似性总是主观的——“狗”和“猫”是否相似取决于你如何看待它。spaCy的相似模型通常假定一个相当通用的相似性定义。
tokens = nlp(u'dog cat banana')
for token1 in tokens:
for token2 in tokens: print(token1.similarity(token2))
在这种情况下,模型的预测是很准确的。狗和猫非常相似,而香蕉却不是很相似。相同的标记显然是100%相似的(并不总是精确的1.0,因为向量数学和浮点数的不精确)。
相似性是通过比较词向量或“词嵌入”来确定的,即一个词的多维意思表示。单词向量可以通过像word2vec这样的算法生成,通常是这样的:
important note
为了使比较算法简洁和快速,spaCy的小模型(所有以sm结尾的包)都不使用单词向量,而且这些sm包只包含上下文相关的向量。这意味着您仍然可以使用similarity()方法来比较文档、span和token,但是结果不会很好,单个token不会有任何指定的向量。所以为了使用真正的词向量,你需要下载一个更大的模型:
python -m spacy download en_core_web_lg
内置单词向量的模型使它们成为可用的标记。Token.vector, Doc.vector, Span.vector。文本向量将默认为它们的token向量的平均值。您还可以检查一个token是否有分配的向量,并得到L2规范,它可以用来使向量标准化。
nlp = spacy.load('en_core_web_lg')
tokens = nlp(u'dog cat banana sasquatch')
for token in tokens:
print(token.text, token.has_vector, token.vector_norm, token.is_oov)
“dog”、“cat”和“banana”在英语中都很常见,所以它们是模型词汇的一部分,并且带有一个向量。另一方面,“sasquatch”这个词不太常见,也不太常见——所以它的向量表示包含了300个0的维度,这意味着它实际上是不存在的。如果您的应用程序需要包含更多向量的大型词汇表,那么您应该考虑使用一个较大的模型或装入一个完整的向量包,例如,en_vectors_web_lg,其中包含超过100万个唯一的向量。
基于上下文的相似度
除了spaCy内置的单词向量,还有一些根据上下文词汇训练的一些向量,解析、标记和NER模型也依赖于这种上下文中的单词含义的向量表示。当处理管道被应用时,spaCy将文档的内部含义表示为浮点数组,也称为张量。这使得spaCy可以根据周围的单词对单词的意思做出合理的猜测。即使spaCy以前没有见过这个单词,它也会有所了解。因为spaCy使用一个4层的卷积网络,所以张量对一个单词的任意一边的四个单词都很敏感。
例如,这里有三个句子,在不同的语境中包含了“labrador”的单词。
doc1 = nlp(u"The labrador barked.")
doc2 = nlp(u"The labrador swam.")
doc3 = nlp(u"the labrador people live in canada.")
#这边需要注意的是,导入模型不能是md,lg模型,这两个模型计算出来的三个结果是一样
for doc in [doc1, doc2, doc3]: labrador = doc[1] dog = nlp(u"dog") print(labrador.similarity(dog))
尽管模型从来没有见过“labrador”这个词,但它可以很准确地预测它在不同情况下与“dog”的相似性。
整个文档也一样。 在这里,相似性的差异较小,因为所有单词及其顺序都被考虑在内。 但是,特定于上下文的相似性通常仍然非常准确地反映出来。
doc1 = nlp(u"Paris is the largest city in France.")
doc2 = nlp(u"Vilnius is the capital of Lithuania.")
doc3 = nlp(u"An emu is a large bird.")
for doc in [doc1, doc2, doc3]: for other_doc in [doc1, doc2, doc3]: print(doc.similarity(other_doc))
即使关于巴黎和维尔纽斯的句子由不同的词汇和实体组成,它们都描述了相同的概念,并被认为比关于ems的句子更相似。 在这种情况下,即使拼写错误的“维尔纽斯”版本仍然会产生非常相似的结果。
由相同单词组成的句子可能会被认为是非常相似的,但永远不会完全相同。
docs = [nlp(u"dog bites man"), nlp(u"man bites dog"),
nlp(u"man dog bites"), nlp(u"dog man bites")]
for doc in docs: for other_doc in docs: print(doc.similarity(other_doc))
有趣的是,“人咬狗”和“狗咬人”被认为比“人咬狗”和“狗咬人”更相似。这可能是一个巧合——或者是“人”被解释为两个句子的主语的结果。
来源:oschina
链接:https://my.oschina.net/u/4368772/blog/3436931