如何使用gensim的word2vec模型和python计算句子相似度

zhf*_*fkt 113 python gensim word2vec

根据Gensim Word2Vec,我可以使用gensim包中的word2vec模型来计算2个单词之间的相似度.

例如

trained_model.similarity('woman', 'man') 
0.73723527
Run Code Online (Sandbox Code Playgroud)

但是,word2vec模型无法预测句子相似性.我发现在gensim中具有句子相似性的LSI模型,但是,似乎不能与word2vec模型结合.我所拥有的每个句子的语料库长度不是很长(短于10个单词).那么,有没有简单的方法来实现目标?

Mic*_*yan 81

这实际上是一个非常具有挑战性的问题.计算句子相似度需要建立句子的语法模型,理解等效结构(例如"他昨天走到商店"和"昨天,他走到商店"),不仅在代词和动词中找到相似性,而且在专有名词,在许多真实文本例子中找到统计共现/关系等.

你可以尝试的最简单的事情 - 虽然我不知道这会有多好,而且肯定不会给你最好的结果 - 首先要删除所有"停止"字样(像"the"," "等等,对句子没有多大意义),然后对两个句子中的单词运行word2vec,总结一个句子中的向量,总结另一个句子中的向量,然后找出它们之间的差异总和.通过总结它们而不是做一个单词差异,你至少不会受到单词顺序的影响.话虽如此,这将在很多方面失败,并且无论如何都不是一个好的解决方案(尽管这个问题的好解决方案几乎总是涉及一些NLP,机器学习和其他聪明).

所以,简短的回答是,不,没有简单的方法可以做到这一点(至少不要做得好).

  • 我想你是对的.最简单的方法是在一个句子中累积所有单词的向量,并找出总和之间的差异.顺便说一句,这个简单的方法是否会受到单词计数的影响?因为一个句子中的单词越多,就会得出更多的直方图. (3认同)
  • @zhfkt,很有可能,是的.所以你可能需要除以单词的数量或其他一些来尝试将其分解出来.无论哪种方式,任何这样的启发式都将存在严重缺陷. (2认同)
  • 另请参阅https://datascience.stackexchange.com/questions/23969/sentence-similarity-prediction (2认同)

小智 70

既然你正在使用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
Run Code Online (Sandbox Code Playgroud)

他们提出了一些这样的模型(变得越来越复杂),以便如何使用组合来构建句子级表示.

2011 - 展开递归自动编码器(非常简单.如果感兴趣,请从这里开始)

2012年 - 矩阵向量神经网络

2013年 - 神经张量网络

2015年 - 树LSTM

他的论文都可以在socher.org上找到.其中一些模型可用,但我仍然推荐gensim的doc2vec.首先,2011 URAE并不是特别强大.此外,它还预先配备了适用于解释新闻数据的权重.他提供的代码不允许您重新训练网络.你也不能交换不同的单词向量,所以你会遇到来自Turian的2011年pre-word2vec嵌入.这些向量肯定不在word2vec或GloVe的级别上.

尚未使用Tree LSTM,但它看起来很有前途!

tl;博士是的,使用gensim的doc2vec.但其他方法确实存在!

  • 那些试图找到链接下载GoogleNews-vectors-negative300.bin.gz << https://drive.google.com/file/d/0B7XkCwpI5KDYNlNUTTlSS21pQmM/edit >> (3认同)

小智 34

如果您使用的是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
Run Code Online (Sandbox Code Playgroud)

计算相似度:

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
Run Code Online (Sandbox Code Playgroud)

  • 我很惊讶为什么这不是最佳答案,它工作得很好并且不存在平均方法所具有的序列问题。 (4认同)
  • 你能否就index2word_set和model.index2word提供更多解释?谢谢. (3认同)
  • 请注意,计算"平均向量"同样是任意选择,因为根本不计算它. (2认同)
  • 这就是我一直在寻找的答案。解决了我的问题。感谢您的解决方案 (2认同)

小智 25

您可以使用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)
Run Code Online (Sandbox Code Playgroud)

Ps:如果您遇到有关import pyemd库的错误,可以使用以下命令安装它:

pip install pyemd
Run Code Online (Sandbox Code Playgroud)

  • 我以前使用过WMD,它运作安静,但是在大型语料库上会阻塞。尝试使用SoftCosineSimilarity。也可以在gensim中找到(https://twitter.com/gensim_py/status/963382840934195200) (2认同)

小智 18

一旦计算了两组单词向量的总和,就应该在向量之间取余弦,而不是差异.可以通过将两个向量的点积归一化来计算余弦.因此,字数不是一个因素.


Poo*_*hvi 10

我想更新现有的解决方案,以帮助那些计算句子语义相似性的人.

步骤1:

使用gensim加载合适的模型,并计算句子中单词的单词向量,并将它们存储为单词列表

第2步:计算句子向量

句子之间的语义相似度的计算是困难的,但是最近提出了一篇名为" 简单但是针对句子嵌入的强烈基础的基础 "的论文,它提出了一种简单的方法,通过计算句子中单词向量的加权平均值然后删除平均向量在它们的第一主成分上的投影.这里w的权重是a /(a + p(w)),其中a是参数,p(w)是(估计的)单词频率,称为平滑反频率这种方法表现得更好.

这里给出使用SIF(平滑反频率)计算句子向量的简单代码

步骤3:使用sklearn cosine_similarity为句子加载两个向量并计算相似度.

这是计算句子相似性的最简单有效的方法.

  • 非常好的纸.注意:指向SIF实现的链接需要编写get_word_frequency()方法,这可以通过使用Python的Counter()并使用键返回一个dict来轻松完成:唯一的单词w,值:#w/#total doc len (2认同)

Ast*_*iul 10

文档中有一项功能,可获取单词列表并比较它们的相似性。

s1 = 'This room is dirty'
s2 = 'dirty and disgusting room' #corrected variable name

distance = model.wv.n_similarity(s1.lower().split(), s2.lower().split())
Run Code Online (Sandbox Code Playgroud)


lec*_*ito 8

我使用以下方法,它运作良好.你首先需要运行一个POSTagger然后过滤你的句子来摆脱停用词(决定因素,连词,......).我推荐TextBlob APTagger.然后通过取句子中每个单词向量的平均值来构建word2vec.Gemsim word2vec中的n_similarity方法正好通过允许传递两组单词进行比较.


小智 6

Word2Vec的扩展旨在解决比较较长文本(如短语或句子)的问题.其中一个是paragraph2vec或doc2vec.

"句子和文件的分布式表示" http://cs.stanford.edu/~quocle/paragraph_vector.pdf

http://rare-technologies.com/doc2vec-tutorial/

  • 不久之后值得一提的是所提出的算法是如何工作的.您基本上为每个话语添加一个唯一的"标记"并计算word2vec向量.最后,您将获得语料库中每个单词的单词向量(假设您要求所有单词,还有唯一单词).话语中的每个独特"标记"将代表该话语.关于论文中提出的结果存在一些争议,但这是另一个故事. (2认同)

Wok*_*Wok 5

Gensim段落嵌入实现了一个称为Doc2Vec的模型。

IPython笔记本提供了不同的教程:

另一种方法将依赖Word2VecWord Mover的距离(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)
Run Code Online (Sandbox Code Playgroud)

最后,如果您可以运行Tensorflow,则可以尝试:https ://tfhub.dev/google/universal-sentence-encoder/2