我是机器学习领域的新手,正在尝试创建一个能够预测两个句子之间语义相似度的模型。我使用了以下方法:
1.使用gensim包中的word2vec模型,将问题中句子的每个词向量化
2.计算每个句子/文档中所有词的平均向量
import numpy as npfrom scipy import spatialindex2word_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
3.接下来计算这两个平均向量之间的余弦相似度
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)
参考stackoverflow问题:如何使用gensim的word2vec模型和Python计算句子相似度
需要帮助解决以下挑战:
因为我想创建一个能够预测两个句子之间语义相似度的模型,我对以下问题不太确定:
1.哪种模型最适合这个问题
2.更重要的是,如何训练那个模型?
我是否应该创建一个矩阵,每行包含两个句子:sen1和sen2,然后我将它们向量化并计算余弦相似度(按照上述方法)
然后对于训练数据:
X_Train:sen1和sen2的平均向量以及它们的余弦相似度值
y_Train(预测):一组二进制值(如果余弦相似度> 0.7,则为1或相似,否则为0)
我很困惑我的方法是否正确,以及如何将一个正确的方法形成一个可工作的代码库。
互联网和在线可用的材料是我学习机器学习的唯一老师;因此请求您的指导,帮助我填补理解上的差距,并帮助我为我的问题提出一个好的工作模型。
回答:
您的一般方法是合理的。句子中词向量的平均值通常作为句子的粗略摘要向量效果不错。(还有许多其他可能的技术可能会做得更好,但这是一个很好的简单开始。)
您可以使用别人预先训练的词向量,但如果您有来自您领域的良好的大量训练文本,那些词向量可能会工作得更好。您应该查找如何使用gensim
训练自己的词向量的教程。例如,其中包含一个演示Jupyter笔记本word2vec.ipynb
,在其docs/notebooks
目录中,您也可以在线查看:
https://github.com/RaRe-Technologies/gensim/blob/develop/docs/notebooks/word2vec.ipynb
您当前的avg_feature_vector()
函数存在一些问题。特别是:
-
如果您传递了
model
,它已经包含了固定的index2word
列表和已经确定的维数 – 所以没有必要冗余地传递这些 -
您在模型中的所有词上循环,而不是只在您的句子中的词上,所以不是仅仅基于您的句子计算
-
有更好的、更Pythonic的方式来进行您尝试的各种数组数学操作 – 包括在
numpy
库中一个简单的mean()
函数,可以省去您创建平均值时的加法/除法
您可能想要作为练习修复这些问题,但您也可以使用词向量model
上的实用方法。特别是,看看n_similarity()
– 它专门接受两个词集,自动平均每个集合,然后报告两个集合之间的相似度值(对于更相似,接近1.0;对于最不相似,接近-1.0)。参见:
所以如果您在sent1
和sent2
中有两个句子(作为字符串),并且在kv_model
中有一组词向量(由您自己刚刚训练的,或者从其他地方加载的),您可以通过以下方式获取句子的相似度:
kv_model.n_similarity(sent1.split(), sent2.split())
(如果任何词标记未被模型识别,您可能会遇到错误。)
您是否实际为不同句子创建平均向量并将它们存储在某个列表/字典/数据框等中,或者只是在某处记住成对相似度,将取决于您接下来想做什么。
并且,在您掌握了这个简单的文本相似度度量方法的基础之后,您可以研究其他技术。例如,另一种使用词向量比较两个文本的方法 – 但不是通过简单的平均值 – 称为“词移动距离”(Word Mover’s Distance)。(不过,它计算起来相当慢。)
另一种将文本折叠成单一向量的技术,以便进行比较,在gensim
中作为Doc2Vec
可用 – 它与Word2Vec
的工作方式非常相似,但也为更长的文本创建向量,而不仅仅是为单个词创建向量。