Как лучше всего сопоставить похожие n-граммы?

Вопрос или проблема

Я пытаюсь сопоставить похожие n-граммы, используя Wordnet и синсеты. Например: старший брат и старший брат или сестра должны соответствовать одной сущности.

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

Мне интересно, существуют ли лучшие методы реализации этого?

Для 1-граммы:

from nltk.corpus import wordnet as wn
from nltk.stem import WordNetLemmatizer
l = WordNetLemmatizer()

older="older"
elder="elder"
older_lemma = l.lemmatize(older, pos=wn.ADJ)
elder_lemma = l.lemmatize(elder, pos=wn.ADJ)


for syn in wn.synsets(older_lemma):
    if elder_lemma in syn.lemma_names():
        print(syn)

В идеале я хотел бы расширить это до n-грамм и ищу лучший способ сделать это.

Правка: я не ищу решения на основе векторов.

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

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

Для расширения сравнения схожести на несколько слов или предложений, вы можете обратить внимание на расстояние между словами после обучения модели word2vec.

Недостаток вышеуказанного подхода заключается в том, что вам нужен большой текстовый корпус для обучения модели word2vec. Вы можете использовать что-то специфическое для вашей области или использовать открытые наборы данных (новостные статьи, книги Project Gutenberg, дампы Википедии).

Лучшее решение – это определенно использование векторов слов.

  • Создайте свои собственные с помощью слоев Embedding() в Keras, например: возможно, это мощное, но, возможно, медленное решение.
  • Создайте свои собственные с помощью библиотеки gensim: очень быстро и просто, я бы выбрал это.
  • Скачайте предобученные векторы Glove от Google и примените их сразу: быстрое применение, но весь файл предобученных векторов очень большой.

Как только вы обучите векторы, вы можете представить каждую n-грамму в виде вектора эмбеддингов слов с формой:

( количество слов в n-грамме , размер вектора )

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

  • . – . – . – . –

ПРАВКА:

Еще одно быстрое решение, которое вы можете сделать прямо в gensim, это обучить doc2vec с нуля. Таким образом, вы немедленно получите вектор эмбеддинга для всего документа (т.е. n-граммы). Я никогда не пробовал doc2vec на небольших кусках текста, таких как n-граммы, но, возможно, стоит попробовать. В gensim это всего лишь несколько строк кода.

Ответ или решение

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

1. Использование Wordnet для n-грамм

Первый шаг к решению этой задачи – это анализ отдельных слов в n-граммах с использованием Wordnet. Вы можете взять каждое слово в n-грамме, найти его леммы и извлечь синсеты. Затем, для каждого синсета, вы можете проверять другие н-граммы на наличие схожих лемм. Однако, как вы и отметили, этот подход становится громоздким на большом объеме данных и при большом количестве n-грамм.

2. Ограничение количества проверок с помощью предварительного фильтра

Чтобы избежать проверки каждой комбинации, можно реализовать предфильтр. Разработайте свой собственный алгоритм, который оценит схожесть двух слов по их морфологическим и семантическим характеристикам, до того как углубляться в синсеты. Например, проверка длины строки, количество схожих букв, или использование метрик расстояния, таких как расстояние Левенштейна, могут помочь исключить явно несопоставимые пары до более глубокой проверки через Wordnet.

3. Использование семантического анализа

Семантический анализ может включать в себя использование лемматизации и синонимов для оптимизации работы с n-граммами. Например, преобразуйте каждую из n-грамм в набор его лемм и создайте для каждой граммы список её синонимов. Затем сопоставляйте эти списки между собой. Это сократит количество синсетов, которые необходимо проверять.

4. Использование моделей word embeddings

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

5. Реализация алгоритма

Для реализации выше описанных стратегий вы можете использовать библиотеки такие как NLTK и Gensim. Например, алгоритм для получения n-грамм может выглядеть следующим образом:

from nltk import ngrams
from nltk.corpus import wordnet as wn
from nltk.stem import WordNetLemmatizer

def get_synsets(phrase):
    lemmatizer = WordNetLemmatizer()
    lemmas = [lemmatizer.lemmatize(word) for word in phrase.split()]
    synsets = []
    for lemma in lemmas:
        synsets.extend(wn.synsets(lemma))
    return synsets

def compare_phrases(phrase1, phrase2):
    synsets1 = get_synsets(phrase1)
    synsets2 = get_synsets(phrase2)

    for syn1 in synsets1:
        for syn2 in synsets2:
            if syn1.wup_similarity(syn2) > 0.8:  # Пример порогового значения
                return True
    return False

result = compare_phrases("старший брат", "старший сиблинг")

Заключение

Таким образом, для поддержания высокой производительности и точности в сопоставлении n-грамм, лучше всего начать с предварительной фильтрации с использованием различных семантических и морфологических характеристик, а затем применять более сложные алгоритмы к тем парам, которые прошли первый фильтр. Рассмотрите возможность использования word embeddings для еще более эффективного сравнения, если ваши ограничения будут ослаблены в будущем.

Оцените материал
Добавить комментарий

Капча загружается...