Как я могу улучшить косинусное сходство двух документов (предложений) в модели doc2vec?

Я создаю приложение чата НЛП на Python, используя gensim библиотеку через doc2vec модель. У меня есть жестко закодированные документы и дан набор обучающих примеров. Я тестирую модель, задавая вопрос пользователю, а затем нахожу наиболее похожие документы в качестве первого шага. В данном случае мой тестовый вопрос - это точная копия документа из обучающего примера.

import gensim
from gensim import models
sentence = models.doc2vec.LabeledSentence(words=[u'sampling',u'what',u'is',u'tell',u'me',u'about'],tags=["SENT_0"])
sentence1 = models.doc2vec.LabeledSentence(words=[u'eligibility',u'what',u'is',u'my',u'limit',u'how',u'much',u'can',u'I',u'claim'],tags=["SENT_1"])
sentence2 = models.doc2vec.LabeledSentence(words=[u'eligibility',u'I',u'am',u'retiring',u'how',u'much',u'can',u'claim',u'have', u'resigned'],tags=["SENT_2"])
sentence3 = models.doc2vec.LabeledSentence(words=[u'what',u'is',u'my',u'eligibility',u'post',u'my',u'promotion'],tags=["SENT_3"])
sentence4 = models.doc2vec.LabeledSentence(words=[u'what',u'is', u'my',u'eligibility' u'post',u'my',u'promotion'], tags=["SENT_4"])
sentences = [sentence, sentence1, sentence2, sentence3, sentence4]
class LabeledLineSentence(object):
    def __init__(self, filename):
        self.filename = filename
    def __iter__(self):
        for uid, line in enumerate(open(filename)):
            yield LabeledSentence(words=line.split(), labels=['SENT_%s' % uid])
model = models.Doc2Vec(alpha=0.03, min_alpha=.025, min_count=2)
model.build_vocab(sentences)
for epoch in range(30):
    model.train(sentences, total_examples=model.corpus_count, epochs = model.iter)
    model.alpha -= 0.002  # decrease the learning rate`
    model.min_alpha = model.alpha  # fix the learning rate, no decay
model.save("my_model.doc2vec")
model_loaded = models.Doc2Vec.load('my_model.doc2vec')
print (model_loaded.docvecs.most_similar(["SENT_4"]))

Результат:

[('SENT_1', 0.043695494532585144), ('SENT_2', 0.0017897281795740128), ('SENT_0', -0.018954679369926453), ('SENT_3', -0.08253869414329529)]

Сходство SENT_4 и SENT_3 составляет только -0.08253869414329529, когда должно быть 1, поскольку они абсолютно одинаковы. Как мне улучшить эту точность? Есть ли какой-то конкретный способ подготовки документов, и я что-то упускаю?


person Kshitiz    schedule 16.06.2017    source источник
comment
Прежде всего, SENT_4 и SENT_3 не совсем то же самое. посмотри на слово продвижение   -  person Qaisar Rajput    schedule 16.06.2017
comment
После исправления: [('SENT_1', 0,043695494532585144), ('SENT_2', 0,0017897281795740128), ('SENT_0', -0.018954679369926453), ('SENT_3', -0.08253869414329529)]   -  person Kshitiz    schedule 16.06.2017


Ответы (1)


Word2Vec / Doc2Vec не работают с примерами игрушечного размера (такими как несколько текстов, короткие тексты и несколько слов в целом). Многие из желаемых свойств надежно достигаются только с обучающими наборами из миллионов слов или десятков тысяч документов.

В частности, имея всего 5 примеров и всего лишь дюжину или два слова, но 100-мерных векторов моделирования, обучение не заставляет делать главное, что делает слова-векторы / doc-векторы полезными: сжимать представления в плотные вложения, где похожие элементы необходимо постепенно подталкивать друг к другу в векторном пространстве, потому что нет способа сохранить все исходные вариации в поисковой таблице типа гигантского. Имея больше измерений, чем вариация корпуса, ваши идентичные токены SENT_3 и SENT_4 могут принимать совершенно разные документы-векторы, и модель все еще достаточно велика, чтобы хорошо выполнять свою обучающую задачу (по сути, `` переобучать '') без желаемого конечного состояния. подобных текстов, имеющих похожие векторы, принудительно.

Иногда вы можете выжать немного больше смысла из небольших наборов данных с помощью большего количества обучающих итераций и гораздо меньшей модели (с точки зрения вектора size), но на самом деле: этим векторам нужны большие и разнообразные наборы данных, чтобы стать значимыми.

Это главная проблема. Некоторые другие неэффективности или ошибки в вашем примере кода:

  • В вашем коде не используется класс LabeledLineSentence, поэтому нет необходимости включать его здесь - это неуместный шаблон. (Кроме того, TaggedDocument является предпочтительным именем для класса документов _6 _ + _ 7_ в последних версиях gensim, а не LabeledSentence.)

  • Ваше индивидуальное управление alpha и min_alpha вряд ли сделает что-нибудь полезное. Лучше всего оставить их по умолчанию, если у вас уже что-то не работает, вы хорошо понимаете алгоритм, а затем хотите попробовать тонкие оптимизации.

  • train() будет выполнять свои собственные итерации, поэтому вам не нужно вызывать его много раз во внешнем цикле. (Этот код в том виде, в котором он был написан, делает в своем первом цикле 5 model.iter итераций при alpha значениях, постепенно убывающих от 0,03 до 0,025, затем 5 итераций при фиксированной альфа 0,028, затем еще 5 при 0,026, затем еще 27 наборов по 5 итераций при уменьшении альфа, заканчиваются на 30-м цикле с фиксированным альфа -0,028. Это бессмысленное конечное значение - скорость обучения никогда не должна быть отрицательной - в конце бессмысленной прогрессии. Даже с большим набором данных эти 150 итераций примерно половина происходят в отрицательные alpha значения, скорее всего, дадут странные результаты.)

person gojomo    schedule 16.06.2017