需要帮助创建一个合适的模型来预测两个句子之间的语义相似度。

4
我是机器学习领域的新手,正在尝试创建一个模型,可以预测两个句子之间的语义相似度。我采用以下方法:
1.使用gensim包中的word2vec模型对每个句子中的单词进行向量化处理。
2.对每个句子或文档中的所有单词计算平均向量。
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

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(prediction):一组二进制值(如果余弦相似度> 0.7,则为1或类似值,否则为0)

我很困惑我的方法是否正确以及如何以可工作的代码形式提出正确的方法。

因为互联网和在线材料是我学习ML的唯一教师,所以请求您的指导,帮助我消除理解上的差距,并帮忙为我的问题提供一个良好的工作模型。

2个回答

3
你的整体思路是合理的。对于一个句子,词向量的平均值通常可以作为该句子的粗略摘要向量。(还有许多其他可能更好的技术,但这是一个不错的易于入手的开始。)
你可以使用别人预先训练好的词向量,但如果你有一个良好的大型域文本训练集,那么这些词向量可能会更好地发挥作用。你应该寻找一个关于如何使用gensim训练自己的词向量的教程。例如,在其docs/notebooks目录下包含一个演示Jupyter笔记本word2vec.ipynb,你也可以在网上查看它。

https://github.com/RaRe-Technologies/gensim/blob/develop/docs/notebooks/word2vec.ipynb

您当前的avg_feature_vector()函数存在一些问题。 特别是:
  • 如果您传入model,它已经包含了固定的index2word列表和已确定的维数-因此没有必要冗余地传递这些内容

  • 您正在循环遍历模型中的所有单词,而不仅仅是句子中的单词,因此不是基于您的句子计算

  • 有更好的、更符合Python风格的方法来执行各种数组数学运算,包括在numpy库中使用一个简单的mean()函数,可以省去创建平均值的加法/除法操作

您可能希望解决这些问题作为练习,但您也可以使用单词向量model上的实用程序方法。 特别是,请查看n_similarity() - 它专门接受两组单词,自动对每个组进行平均,然后报告两组之间的相似度值(越接近1.0表示更相似,越接近-1.0表示最不相似)。 参见:

https://radimrehurek.com/gensim/models/keyedvectors.html#gensim.models.keyedvectors.Word2VecKeyedVectors.n_similarity

如果您有两个句子(作为字符串)在sent1sent2中,并且有一组单词向量(可以是您刚刚训练的,也可以从其他地方加载)在kv_model中,则可以通过以下方式获取句子的相似度:

kv_model.n_similarity(sent1.split(), sent2.split())

(如果模型中的任何单词令牌不被识别,则仍可能出现错误。)
无论您实际上是为不同的句子创建平均向量并将它们存储在某个列表/字典/数据框等中,还是只是在某个地方记住成对相似性,这将取决于您想做什么下一步。
在此简单的文本相似度测量基础上工作正常后,您可以研究其他技术。例如,使用单词向量比较两个文本的另一种方式-但不是通过简单的平均值-称为“词移距离”。 (不过计算速度要慢得多。)
另一种将文本折叠成单个向量的比较目的的技术可以在gensim中作为Doc2Vec使用-它的工作方式与Word2Vec 非常相似,但还会创建每个较长文本的向量,而不仅仅是单个词的向量。

1

首先感谢您提出这个问题,我也在研究同样的问题。首要问题是解决语言的细微差别以及如何让机器理解人类语言,这并不是一个简单的问题。

自从这个问题被提出以来,ML/AI领域发生了很多变化,因此我认为更新这个答案可能会对某些人有所帮助。

您的方法存在问题,即获取句子中所有单词的平均值,并将其平均化以获得派生向量,尽管该工具在当时可能还可以,但您应该选择更复杂的工具,例如gensim中的Doc2Vec

对于今天的时间,我觉得存在更为复杂和有效的词嵌入而不是句子嵌入可供使用。

其中一些非常聪明的列表已经在HuggingFace的this github仓库中进行了精心策划。

我还想指出一个很棒的讨论,供大家阅读:

https://github.com/huggingface/transformers/issues/876

人们经常尝试使用ElasticSearch BM25 + Embeddings的组合,但实际准确率仍然较低。
我还在寻找一种语义搜索技术,可以帮助我在我的领域数据上进行语义搜索。
最接近的是“迁移学习”,您可以使用预训练模型,并将您的领域数据添加到其中以微调该模型。
您可以查看以下示例:https://github.com/UKPLab/sentence-transformers/blob/master/examples/application_semantic_search.py 但是,即使这样,我们也不能考虑本体论和各种情况,其中词重叠应该出现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接