Модель Gensim Doc2vec: как вычислить сходство на корпусе, полученном с использованием предварительно обученной модели doc2vec? - PullRequest
0 голосов
/ 19 ноября 2018

У меня есть модель на основе 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])

1 Ответ

0 голосов
/ 20 ноября 2018

Грязное решение, которое я использовал около месяца назад в 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_s 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)
...