Gensim Doc2vec 模型:如何计算使用预训练的 doc2vec 模型获得的语料库的相似度?

Gensim Doc2vec model: how to compute similarity on a corpus obtained using a pre-trained doc2vec model?

我有一个基于 doc2vec 在多个文档上训练的模型。我想使用该模型来推断另一个文档的向量,我想将其用作语料库进行比较。因此,当我寻找与我介绍的句子最相似的句子时,它会使用这个新的文档向量而不是经过训练的语料库。 目前,我正在使用 infer_vector() 为新文档的每个句子计算向量,但我不能将 most_similar() 函数与我获得的向量列表一起使用,它必须是 KeyedVectors.

我想知道是否有任何方法可以为允许使用 most_similar() 函数的新文档计算这些向量,或者我是否必须计算每个向量之间的相似度新文档的句子和我单独介绍的句子(在这种情况下,Gensim中是否有任何实现可以让我计算2个向量之间的余弦相似度?)。

我是 Gensim 和 NLP 的新手,我愿意听取您的建议。

我无法提供完整的代码,因为这是一个大学项目,但这里是我遇到问题的主要部分。

对数据进行一些预处理后,这就是我训练模型的方式:

documents = [TaggedDocument(doc, [i]) for i, doc in enumerate(train_data)]
assert gensim.models.doc2vec.FAST_VERSION > -1

cores = multiprocessing.cpu_count()

doc2vec_model = Doc2Vec(vector_size=200, window=5, workers=cores)
doc2vec_model.build_vocab(documents)
doc2vec_model.train(documents, total_examples=doc2vec_model.corpus_count, epochs=30)

我尝试用这种方式计算新文档的向量:

questions = [doc2vec_model.infer_vector(line) for line in lines_4]

然后我尝试计算新文档向量与输入短语之间的相似度:

text = str(input('Me: '))

tokens = text.split()

new_vector = doc2vec_model.infer_vector(tokens)

index = questions[i].most_similar([new_vector])

我大约一个月前在 gensim==3.2.0 中使用的一个肮脏的解决方案(语法可能已更改)。

您可以将推断的向量保存为 KeyedVectors 格式。

from gensim.models import KeyedVectors
from gensim.models.doc2vec import Doc2Vec
vectors = dict()
# y_names = doc2vec_model.docvecs.doctags.keys()
y_names = range(len(questions))

for name in y_names:
    # vectors[name] = doc2vec_model.docvecs[name]
    vectors[str(name)] = questions[name]
f = open("question_vectors.txt".format(filename), "w")
f.write("")
f.flush()
f.close()
f = open("question_vectors.txt".format(filename), "a")
f.write("{} {}\n".format(len(questions), doc2vec_model.vector_size))
for v in vectors:
    line = "{} {}\n".format(v, " ".join(questions[v].astype(str)))
    f.write(line)
f.close()

然后你可以加载并使用most_similar函数

keyed_model = KeyedVectors.load_word2vec_format("question_vectors.txt")
keyed_model.most_similar(str(list(y_names)[0]))

另一种解决方案(尤其是如果问题的数量不是那么多)只是将问题转换为 np.array 并获得余弦距离),例如

import numpy as np

questions = np.array(questions)
texts_norm = np.linalg.norm(questions, axis=1)[np.newaxis].T
norm = texts_norm * texts_norm.T

product = np.matmul(questions, questions.T)
product = product.T / norm

# Otherwise the item is the closest to itself
for j in range(len(questions)):
    product[j, j] = 0

# Gives the top 10 most similar items to the 0th question
np.argpartition(product[0], 10)