如何使用gensim的word2vec模型和python计算句子相似度
根据Gensim Word2Vec,我可以使用gensim包中的word2vec模型来计算2个单词之间的相似度。
例如
trained_model.similarity('woman', 'man')
0.73723527
但是,word2vec模型无法预测句子相似性。 我发现在gensim中具有句子相似性的LSI模型,但是,似乎不能与word2vec模型结合。 我所拥有的每个句子的语料库长度不是很长(短于10个单词)。 那么,有没有简单的方法来实现目标?
zhfkt asked 2019-07-21T13:21:44Z
12个解决方案
75 votes
这实际上是一个非常具有挑战性的问题。 计算句子相似度需要建立句子的语法模型,理解等效结构(例如“他昨天走到商店”和“昨天,他走到商店”),不仅在代词和动词中找到相似性,而且在 专有名词,在许多真实文本例子中找到统计共现/关系等。
你可以尝试的最简单的事情 - 虽然我不知道这会有多好,而且肯定不会给你最好的结果 - 首先要删除所有“停止”字样(像“the”,“ “等等,对句子没有多大意义),然后对两个句子中的单词运行word2vec,总结一个句子中的向量,总结另一个句子中的向量,然后找出它们之间的差异 总和。 通过总结它们而不是做一个单词差异,你至少不会受到单词顺序的影响。 话虽如此,这将在很多方面失败,并且无论如何都不是一个好的解决方案(尽管这个问题的好解决方案几乎总是涉及一些NLP,机器学习和其他聪明)。
所以,简短的回答是,不,没有简单的方法可以做到这一点(至少不要做得好)。
Michael Aaron Safyan answered 2019-07-21T13:22:21Z
64 votes
既然你正在使用gensim,你应该使用它的doc2vec实现。 doc2vec是word2vec对短语,句子和文档级别的扩展。 这是一个非常简单的扩展,在这里描述
[http://cs.stanford.edu/~quocle/paragraph_vector.pdf]
Gensim很好,因为它直观,快速,灵活。 最棒的是你可以从官方的word2vec页面中获取预训练的单词嵌入,并且暴露了gensim的Doc2Vec模型的syn0层,这样你就可以使用这些高质量的向量来嵌入单词嵌入!
了Googlenews向量-negative300.bin.gz
我认为gensim绝对是将一个句子嵌入向量空间中最简单的(也是迄今为止我最好的)工具。
还有其他的句子到矢量技术,而不是Le& Mikolov的论文如上。 斯坦福大学的Socher和Manning肯定是这一领域最着名的研究人员之一。 他们的工作基于组合原则 - 句子的语义来自:
1. semantics of the words
2. rules for how these words interact and combine into phrases
他们提出了一些这样的模型(变得越来越复杂),以便如何使用组合来构建句子级表示。
2011 - 展开递归自动编码器(非常简单。如果感兴趣,请从这里开始)
2012年 - 矩阵向量神经网络
2013年 - 神经张量网络
2015年 - 树LSTM
他的论文都可以在socher.org上找到。 其中一些模型可用,但我仍然推荐gensim的doc2vec。 首先,2011 URAE并不是特别强大。 此外,它还预先配备了适用于解释新闻数据的权重。 他提供的代码不允许您重新训练网络。 你也不能交换不同的单词向量,所以你会遇到来自Turian的2011年pre-word2vec嵌入。 这些向量肯定不在word2vec或GloVe的级别上。
尚未使用Tree LSTM,但它看起来很有前途!
tl;博士是的,使用gensim的doc2vec。 但其他方法确实存在!
Willie answered 2019-07-21T13:24:22Z
28 votes
如果您使用的是word2vec,则需要计算每个句子/文档中所有单词的平均向量,并使用向量之间的余弦相似度:
import numpy as np
from scipy import spatial
index2word_set = set(model.wv.index2word)
def avg_feature_vector(sentence, model, num_features, index2word_set):
words = sentence.split()
feature_vec = np.zeros((num_features, ), dtype='float32')
n_words = 0
for word in words:
if word in index2word_set:
n_words += 1
feature_vec = np.add(feature_vec, model[word])
if (n_words > 0):
feature_vec = np.divide(feature_vec, n_words)
return feature_vec
计算相似度:
s1_afv = avg_feature_vector('this is a sentence', model=model, num_features=300, index2word_set=index2word_set)
s2_afv = avg_feature_vector('this is also sentence', model=model, num_features=300, index2word_set=index2word_set)
sim = 1 - spatial.distance.cosine(s1_afv, s2_afv)
print(sim)
> 0.915479828613
tbmihailov answered 2019-07-21T13:24:56Z
21 votes
您可以使用Word Mover的距离算法。 这里有一个关于WMD的简单描述。
#load word2vec model, here GoogleNews is used
model = gensim.models.KeyedVectors.load_word2vec_format('../GoogleNews-vectors-negative300.bin', binary=True)
#two sample sentences
s1 = 'the first sentence'
s2 = 'the second text'
#calculate distance between two sentences using WMD algorithm
distance = model.wmdistance(s1, s2)
print ('distance = %.3f' % distance)
P.s。:如果您遇到有关import pyemd库的错误,可以使用以下命令安装它:
pip install pyemd
Ehsan answered 2019-07-21T13:25:30Z
16 votes
一旦计算了两组单词向量的总和,就应该在向量之间取余弦,而不是差异。 可以通过将两个向量的点积归一化来计算余弦。 因此,字数不是一个因素。
Rani Nelken answered 2019-07-21T13:25:59Z
8 votes
我使用以下方法,它运作良好。你首先需要运行一个POSTagger然后过滤你的句子来摆脱停用词(决定因素,连词,......)。 我推荐TextBlob APTagger。然后通过取句子中每个单词向量的平均值来构建word2vec。 Gemsim word2vec中的n_similarity方法正好通过允许传递两组单词进行比较。
lechatpito answered 2019-07-21T13:26:29Z
8 votes
我想更新现有的解决方案,以帮助那些计算句子语义相似性的人。
步骤1:
使用gensim加载合适的模型,并计算句子中单词的单词向量,并将它们存储为单词列表
第2步 :计算句子向量
句子之间的语义相似度的计算是困难的,但最近一篇名为“一个简单而又难以置信的基础用于句子”的论文“EMBEDDINGS”提出了一种简单的方法,通过计算句子中单词向量的加权平均值,然后去除其第一主成分上的平均向量的投影。这里的单词w的权重为a /(a + p( w))a为参数,p(w)为(估计的)字频率,称为平滑逆频率。该方法表现明显更好。
这里给出了使用SIF(平滑反频率)计算句子向量的简单代码
第3步:使用sklearn cosine_similarity为句子加载两个向量并计算相似度。
这是计算句子相似性的最简单有效的方法。
Poorna Prudhvi answered 2019-07-21T13:27:46Z
6 votes
Word2Vec的扩展旨在解决比较较长文本(如短语或句子)的问题。 其中一个是paragraph2vec或doc2vec。
“句子和文件的分布式表示”[http://cs.stanford.edu/~quocle/paragraph_vector.pdf]
[http://rare-technologies.com/doc2vec-tutorial/]
Max answered 2019-07-21T13:28:45Z
5 votes
文档中有一个函数,它列出了单词列表并比较了它们的相似之处。
s1 = 'This room is dirty'
s2 = 'dirty and disgusting room' #corrected variable name
distance = model.wv.n_similarity(s1.lower().split(), s2.lower().split())
Astariul answered 2019-07-21T13:29:20Z
3 votes
我尝试过以前答案提供的方法。 它起作用,但它的主要缺点是句子越长,相似性越大(计算相似度我使用任意两个句子的两个平均嵌入的余弦得分),因为词越多,语义效果越积极。 将被添加到句子中。
我认为我应该改变主意并使用句子嵌入而不是本文和本文所研究的。
Lerner Zhang answered 2019-07-21T13:29:56Z
2 votes
Facebook研究小组发布了一个名为InferSent的新解决方案结果和代码发布在Github上,检查他们的回购。 这非常棒。 我打算用它。[https://github.com/facebookresearch/InferSent]
他们的论文[https://arxiv.org/abs/1705.02364]抽象:许多现代NLP系统依赖于先前在大型语料库上以无人监督的方式训练的词嵌入作为基本特征。 然而,为诸如句子之类的大块文本获得嵌入的努力并未如此成功。 学习无监督的句子表示的若干尝试尚未达到足够令人满意的性能以被广泛采用。 在本文中,我们展示了使用斯坦福自然语言推理数据集的监督数据训练的通用句子表示如何能够在广泛的传递任务中始终优于SkipThought向量等无监督方法。 就像计算机视觉如何使用ImageNet获取特征,然后可以转移到其他任务一样,我们的工作往往表明自然语言推理对于转移学习对其他NLP任务的适用性。 我们的编码器是公开的。
Ayman Salama answered 2019-07-21T13:30:32Z
1 votes
Gensim为段落嵌入实现了一个名为Doc2Vec的模型。
有不同的教程作为IPython笔记本呈现:
关于Lee Dataset的Doc2Vec教程
关于IMDB情感数据集的Gensim Doc2Vec教程
Doc2Vec到维基百科的文章
另一种方法依赖于Word2Vec和Word Mover的距离(WMD),如本教程所示:
使用Word2Vec和WMD查找类似的文档
另一种解决方案是依赖平均向量:
from gensim.models import KeyedVectors
from gensim.utils import simple_preprocess
def tidy_sentence(sentence, vocabulary):
return [word for word in simple_preprocess(sentence) if word in vocabulary]
def compute_sentence_similarity(sentence_1, sentence_2, model_wv):
vocabulary = set(model_wv.index2word)
tokens_1 = tidy_sentence(sentence_1, vocabulary)
tokens_2 = tidy_sentence(sentence_2, vocabulary)
return model_wv.n_similarity(tokens_1, tokens_2)
wv = KeyedVectors.load('model.wv', mmap='r')
sim = compute_sentence_similarity('this is a sentence', 'this is also a sentence', wv)
print(sim)
最后,如果您可以运行Tensorflow,您可以尝试:[https://tfhub.dev/google/universal-sentence-encoder/2]
Wok answered 2019-07-21T13:31:54Z