Оценка точности doc2vec

Я пытаюсь оценить модель doc2vec на основе кода из здесь. По сути, я хочу знать, что процент предполагаемых документов наиболее похож на сам себя. Это мой текущий код:

    for doc_id, doc in enumerate(cur.execute('SELECT Text FROM Patents')):
        docs += 1
        doc = clean_text(doc)
        inferred_vector = model.infer_vector(doc)
        sims = model.docvecs.most_similar([inferred_vector], topn=len(model.docvecs))
        rank = [docid for docid, sim in sims].index(doc_id)
        ranks.append(rank) 

    counter = collections.Counter(ranks)
    accuracy = counter[0] / docs

Этот код отлично работает с небольшими наборами данных. Однако, поскольку у меня есть огромный файл с миллионами документов, этот код становится слишком медленным, на его вычисление уйдут месяцы. Я профилировал свой код, и большую часть времени занимает следующая строка: sims = model.docvecs.most_similar([inferred_vector], topn=len(model.docvecs)).

Если я не ошибаюсь, это необходимость соотносить каждый документ со всеми остальными документами. Я думаю, что время вычислений может значительно сократиться, если я изменю это на topn=1, поскольку единственное, что я хочу знать, - это сам наиболее похожий документ или нет. При этом каждый документ (т. Е. inferred_vector) измеряется наиболее похожим документом (т. Е. topn=1), а затем я просто смотрю, является он самим собой или нет. Как я мог это реализовать? Любая помощь или идея приветствуются.


person Marlon    schedule 26.07.2020    source источник


Ответы (1)


Чтобы most_similar() возвращал только один наиболее похожий документ, это так же просто, как указать topn=1.

Однако, чтобы узнать, какой из миллионов документов наиболее похож на один целевой вектор, необходимо рассчитать и отсортировать сходство со всеми всеми кандидатами. (Если бы хотя бы один документ был пропущен, он мог бы быть первым!)

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

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

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

Точно так же вы можете просто проверить сходство повторно выведенного вектора с одним вектором в модели для того же идентификатора документа и проверить, достаточно ли они похожи. (Это будет намного быстрее, но также может быть выполнено на случайной выборке документов.) Не существует подходящего волшебного порога для достаточно похожего; вам нужно будет выбрать тот, который, кажется, соответствует вашим другим целям. Например, используя cosine_similarity() scikit-learn для сравнения двух векторов:

from sklearn.metrics.pairwise import cosine_similarity

# ...

    inferred_vector = model.infer_vector(doc_words)
    looked_up_vector = model.dv[doc_id]
    self_similarity = cosine_similarity([inferred_vector], [looked_up_vector])[0]
    # then check that value against some threshold

(Вы должны заключить отдельные векторы в списки в качестве аргументов для cosine_similarity(), а затем получить доступ к 0-му элементу возвращаемого значения, потому что он обычно предназначен для работы с большими списками векторов.)

С помощью этого расчета вы не узнаете, например, некоторые из других хранимых-doc-векторов немного ближе к предполагаемой цели, но это может быть не так уж важно. Документы могут быть действительно похожи! И хотя исходная самопроверка, наиболее близкая к самой себе, потерпит неудачу при наличии серьезных дефектов в обучении, даже хорошо обученная модель, вероятно, будет иметь некоторые случаи, когда естественное дрожание модели предотвращает появление ближайшего к себе для каждого документа. (При большем количестве документов внутри того же количества измерений или определенных корпусах с множеством очень похожих документов это стало бы более распространенным ... но не тревожным индикатором каких-либо проблем с моделью.)

person gojomo    schedule 26.07.2020
comment
Большое спасибо за ответ @gojomo, он очень информативный! Я не уверен, что полностью следую вашему объяснению. Во-первых, как вы думаете, моя идея не поможет с точки зрения повышения производительности? Я провожу несколько тестов, и строка с topn=1 выполняется намного быстрее, чем с topn=len(model.docvecs). У меня вопрос, как в данном случае сравнить это с самим документом. Во-вторых, вы предложили мне проверить сходство повторно выведенного вектора с единственным вектором в модели для того же идентификатора документа. Вы можете привести пример? Опять же, не уверен, что слежу за тобой. - person Marlon; 26.07.2020
comment
Вызов most_similar() не будет происходить заметно быстрее при использовании topn=1, чем topn=20 или topn=10000 - потому что он по-прежнему должен выполнять все те же сравнения и ту же сортировку. Возможно, другие ваши шаги пойдут быстрее, но этот - нет, так как он выполняет такой же объем работы для результатов первого или первого ряда. Я добавил пример кода сравнения двух векторов по косинусоидальности к соответствующей части ответа. - person gojomo; 26.07.2020
comment
Спасибо @gojomo за помощь, и я сожалею о задержке с принятием вашего ответа. - person Marlon; 12.08.2020