例如:
trained_model.similarity('woman', 'man')
0.73723527
然而,word2vec模型无法预测句子的相似性。我在gensim中发现了具有句子相似度的LSI模型,但它似乎不能与word2vec模型结合使用。我拥有的每个句子的语料库长度不是很长(少于10个单词)。那么,有没有简单的方法来实现这个目标呢?
trained_model.similarity('woman', 'man')
0.73723527
然而,word2vec模型无法预测句子的相似性。我在gensim中发现了具有句子相似度的LSI模型,但它似乎不能与word2vec模型结合使用。我拥有的每个句子的语料库长度不是很长(少于10个单词)。那么,有没有简单的方法来实现这个目标呢?
这实际上是一个相当具有挑战性的问题。计算句子相似度需要建立一个句子的语法模型,了解等效结构(例如,“他昨天走到商店”和“昨天,他走到商店”),不仅在代词和动词中找到相似性,还要在专有名词中找到统计共现/关系,并在许多真实文本示例中找到相似之处。
最简单的方式是- 虽然我不知道它的表现如何,而且肯定不能为您提供最佳结果- 首先删除所有“停用词”(像“the”,“an”等不太影响句子意义的词),然后在两个句子中运行word2vec,汇总一个句子中的向量,汇总另一个句子中的向量,然后找到总和之间的差异。通过对它们进行求和而不是逐个单词进行差异,你至少不会受到单词顺序的影响。也就是说,这种方式将在许多方面失败,并且绝不是一个好的解决方案(尽管解决此问题的好方法几乎总涉及一些NLP、机器学习和其他巧妙的技术)。
所以,简而言之,答案是否定的,没有容易的方法(至少没有做得好的方法)。
由于您正在使用gensim,您应该使用它的doc2vec实现。doc2vec是对phrase、sentence和document级别的word2vec的扩展。这是一个相当简单的扩展,可以在此处找到描述。
http://cs.stanford.edu/~quocle/paragraph_vector.pdf
Gensim很棒,因为它直观、快速和灵活。更棒的是,你可以从官方的word2vec页面获取预训练的词向量,并且gensim的Doc2Vec模型中的syn0层被公开,这样你就可以使用这些高质量的向量来生成词向量!
GoogleNews-vectors-negative300.bin.gz(在Google Code中链接)
我认为gensim肯定是将句子嵌入向量空间最简单(到目前为止也是最好的)的工具。
除了Le&Mikolov论文中提出的技术外,还存在其他的句子到向量的技术。斯坦福大学的Socher和Manning无疑是这个领域中最著名的两位研究人员。他们的工作基于组合的原则-句子的语义来自于:
1. semantics of the words
2. rules for how these words interact and combine into phrases
如果您正在使用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
你可以使用词移距离算法(Word Mover's Distance algorithm)。这里有一个关于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)
提示:如果您遇到有关导入pyemd库的错误,您可以使用以下命令进行安装:
pip install pyemd
一旦计算出两组单词向量的总和,应该取向量之间的余弦值而不是差值。可以通过对两个向量进行标准化并计算点积来计算余弦值。因此,单词计数不是一个因素。
我想更新现有的解决方案,以帮助那些要计算句子语义相似度的人。
步骤1:
使用gensim加载适合的模型,并计算句子中单词的词向量,将它们存储为一个单词列表
步骤2: 计算句子向量
以前计算句子间的语义相似性很困难,但最近提出了一篇名为"A SIMPLE BUT TOUGH-TO-BEAT BASELINE FOR SENTENCE EMBEDDINGS"的论文,建议通过计算句子中单词向量的加权平均值,然后去除其在第一主成分上的投影来计算。这里一个词w的权重是a / (a + p(w)),其中a是一个参数,p(w)是(估计的)称为平滑逆频率的词频。这种方法表现得更好。
给出了一个使用SIF(平滑逆频率)方法计算句子向量的简单代码,该方法在论文中提出这里
步骤3: 使用sklearn cosine_similarity加载两个句子向量并计算相似度。
这是最简单和高效的方法来计算句子相似度。
从文档中有一个函数,它接受单词列表并比较它们之间的相似性。
s1 = 'This room is dirty'
s2 = 'dirty and disgusting room' #corrected variable name
distance = model.wv.n_similarity(s1.lower().split(), s2.lower().split())
有一些Word2Vec的扩展旨在解决比如短语或句子这样更长的文本比较问题。其中之一是paragraph2vec或doc2vec。
"句子和文档的分布式表示" http://cs.stanford.edu/~quocle/paragraph_vector.pdf
Gensim 实现了一个名为 Doc2Vec 的模型,用于段落嵌入。
有不同的教程以 IPython 笔记本的形式呈现:
另一种方法会依赖于 Word2Vec 和 Word Mover's Distance (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)