Doc2Vec: Сходство между закодированными и невидимыми документами - PullRequest
0 голосов
/ 08 октября 2018

У меня есть образец ~ 60 000 документов.700 из них мы закодировали вручную как имеющие определенный тип контента.Теперь мы хотели бы найти «наиболее похожие» документы на 700, которые мы уже написали вручную.Мы используем gensim doc2vec, и я не могу найти лучший способ сделать это.

Вот как выглядит мой код:

cores = multiprocessing.cpu_count()

model = Doc2Vec(dm=0, vector_size=100, negative=5, hs=0, min_count=2, sample=0, 
        epochs=10, workers=cores, dbow_words=1, train_lbls=False)

all_docs = load_all_files() # this function returns a named tuple
random.shuffle(all_docs)
print("Docs loaded!")
model.build_vocab(all_docs)
model.train(all_docs, total_examples=model.corpus_count, epochs=5)

Я не могу понятьправильный путь, чтобы идти вперед.Это то, что может сделать doc2vec?В конце я хотел бы получить список из 60 000 документов, в котором первый из них является «наиболее похожим» документом.

Спасибо за любую помощь, которая вам может понадобиться!Я потратил много времени, читая справочные документы gensim и различные учебные пособия, и не смог понять это.

РЕДАКТИРОВАТЬ: я могу использовать этот код, чтобы получить документы, наиболее похожие накороткое предложение:

token = "words associated with my research questions".split()
new_vector = model.infer_vector(token)
sims = model.docvecs.most_similar([new_vector])
for x in sims:
    print(' '.join(all_docs[x[0]][0]))

Если есть способ изменить это, чтобы вместо этого получить документы, наиболее похожие на 700 закодированных документов, я хотел бы узнать, как это сделать!

Ответы [ 3 ]

0 голосов
/ 08 октября 2018

Ваш общий подход разумен.Несколько замечаний о вашей настройке:

  • вам нужно будет указать epochs=10 в вашем train() вызове, чтобы действительно получить 10 тренировочных пропусков - и 10 или более чаще всего встречается в опубликованных работах
  • sample -контролируемая понижающая выборка помогает ускорить обучение и часто улучшает качество вектора, и значение может стать более агрессивным (меньшим) с большими наборами данных
  • train_lbls не является параметром для Doc2Vec в любой недавней gensim версии

Существует несколько возможных способов интерпретации и достижения вашей цели «найти« наиболее похожие »документы для 700, которые мы уже закодировали вручную».Например, для документа-кандидата, как определить его сходство с набором 700 - как сходство с одним итоговым вектором «центроида» для полного набора?Или как его сходство с любым из документов?

Есть несколько способов получить один суммарный вектор для набора:

  • усреднить их 700 векторов вместе

  • объединить все их слова в один синтетический составной документ и infer_vector() в этом документе.(Но обратите внимание: тексты, переданные в оптимизированные подпрограммы word2vec / doc2vec gensim, сталкиваются с внутренним пределом реализации в 10 000 токенов - лишние слова игнорируются.)

Фактически, *Метод 1033 * может взять список из нескольких векторов в качестве «положительной» цели и автоматически усреднить их вместе, прежде чем вернуть свои результаты.Так, если, скажем, 700 идентификаторов документов (теги, используемые во время обучения) находятся в списке ref_docs, вы можете попробовать ...

sims = model.docvecs.most_similar(positive=ref_docs, topn=0)

... и получить ранжированный список всех другихв модельных документах, по своему сходству со средним числом всех этих positive примеров.

Однако альтернативная интерпретация того, что сходство документа с набором ссылок является его наибольшим сходством с каким-либо одним документом внутри набора, может быть лучше для вашей цели.Особенно это может быть в том случае, если сам набор ссылок варьируется по многим темам, и, следовательно, его нельзя суммировать одним усредненным вектором.

Вам придется вычислять эти сходства с вашими собственными циклами.Например, примерно:

sim_to_ref_set = {}
for doc_id in all_doc_ids:
    sim_to_ref_set[doc_id] = max([model.docvecs.similarity(doc_id, ref_id) for ref_id in ref_docs])
sims_ranked = sorted(sim_to_ref_set.items(), key=lambda it:it[1], reverse=True)

Верхние элементы в sims_ranked будут наиболее похожи на любой элемент в наборе ссылок.(Предполагая, что идентификаторы набора ссылок также находятся в all_doc_ids, первые 700 результатов снова будут выбранными документами, все с самоподобием 1.0.)

0 голосов
/ 22 октября 2018

Я думаю, что вы можете делать то, что вы хотите с TaggedDocument.Основной вариант использования - просто добавить уникальный тег (идентификатор документа) для каждого документа, но здесь вы захотите добавить специальный тег ко всем 700 выбранным вами документам.Называй это как хочешь, в этом случае я называю это TARGET.Добавьте этот тег только к своим 700 документам, помеченным вручную, пропустите его для остальных 59 300.

TaggedDocument(words=gensim.utils.simple_preprocess(document),tags=['TARGET',document_id])

Теперь обучите свой Doc2Vec.

Далее вы можетеиспользуйте model.docvecs.similarity, чтобы оценить сходство между вашими немаркированными документами и пользовательским тегом.

model.docvecs.similarity(document_id,'TARGET')

А затем просто отсортируйте это.n_similarity и most_similar Не думаю, что они подойдут для того, что вы хотите сделать.

60 000 документов - это не очень много для Doc2Vec, но, возможно, вам повезет.

0 голосов
/ 08 октября 2018

n_similarity выглядит как функция, которую вы хотите, но, похоже, она работает только с образцами в обучающем наборе.

Поскольку у вас есть только 700 документов для перекрестной проверки, использование sklearn не должно вызывать проблем с производительностью,Просто получите векторы ваших 700 документов и используйте sklearn.metrics.pairwise.cosine_simility , а затем найдите наиболее близкое соответствие.Затем вы можете найти те, которые имеют наибольшее сходство (например, используя `np.argmax).Некоторый непроверенный код, иллюстрирующий это:

from sklearn.metrics.pairwise import cosine_similarity

reference_vectors = ... # your vectors to the 700 documents
new_vector = ... # inferred as per your last example
similarity_matrix = cosine_similarity([new_vector], reference_vectors)
most_similar_indices = np.argmax(similarity_matrix, axis=-1)

Это также можно изменить, чтобы реализовать такой метод, как n_similarity для ряда невидимых документов.

...