Определение того, находится ли слово на пути зависимости двух сущностей с помощью spaCy

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

Например:

'Туманный ‹e1> ridge‹ / e1> восстает из ‹e2> всплеска‹ / e2> »

Я хочу перебрать каждое слово и сказать, находится ли оно на пути зависимости между e1 и e2

Два важных примечания:

-Если вы попытаетесь мне помочь (сначала спасибо), не беспокойтесь о разметке xml с помощью ‹e1> и‹ e2>, меня действительно интересует, как определить, находится ли слово на пути зависимости между любыми двумя заданными словами с помощью spaCy я сам забочусь о том, какие слова

-Поскольку я не эксперт по nlp, меня немного смущает значение слова «на пути зависимости», и мне очень жаль, если оно недостаточно ясно (это слова, которые использовал мой наставник)

заранее спасибо


person Valentin Macé    schedule 09.07.2018    source источник


Ответы (2)


Итак, мое решение было найдено с использованием этот пост

Есть ответ, посвященный spaCy

Моя реализация для поиска пути зависимости между двумя словами в данном предложении:

import networkx as nx
import spacy
enter code here
doc = nlp("Ships carrying equipment for US troops are already waiting off the Turkish coast")
    
def shortest_dependency_path(doc, e1=None, e2=None):
    edges = []
    for token in doc:
        for child in token.children:
            edges.append(('{0}'.format(token),
                          '{0}'.format(child)))
    graph = nx.Graph(edges)
    try:
        shortest_path = nx.shortest_path(graph, source=e1, target=e2)
    except nx.NetworkXNoPath:
        shortest_path = []
    return shortest_path

print(shortest_dependency_path(doc,'Ships','troops'))

Выход:

['Ships', 'carrying', 'for', 'troops']

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

Для своих нужд я просто проверяю каждое слово, если оно находится на пути зависимости (кратчайший путь), созданном

person Valentin Macé    schedule 17.07.2018

Путь зависимости - это способ описания построения предложений в предложении. У SpaCy есть действительно хороший пример в своих документах, здесь, с предложением Apple is looking at buying U.K. startup for $1 billion.

Прошу прощения за отсутствие здесь хорошей визуализации, но давайте проработаем ваш пример:

A misty ridge uprises from the surge.

В spaCy мы следуем их примеру, чтобы получить зависимости:

import spacy
nlp = spacy.load('en_core_web_lg')
doc = nlp("A misty ridge uprises from the surge.")
for chunk in doc.noun_chunks:
    print(chunk.text, chunk.root.text, chunk.root.dep_, chunk.root.head.text)

Так вы получите «пункты», из которых состоит ваше предложение. Ваш результат будет выглядеть так:

Text                  | root.text| root.dep_ | root.head.text
A misty ridge uprises   uprises    ROOT        uprises
the surge               surge      pobj        from

chunk.text - это текст, который составляет ваше предложение о зависимости (обратите внимание, что может быть перекрытие в зависимости от структуры предложения). root.text дает корень (или голову) дерева зависимостей. head дерева является объектом spaCy token и имеет дочерние элементы, по которым вы можете выполнять итерацию, чтобы проверить, находится ли другой токен в дереве зависимостей.

def find_dependencies(doc, word_to_check=None, dep_choice=None):
    """
    word_to_check is the word you'd like to see on the dependency tree
    example, word_to_check="misty"

    dep_choice is the text of the item you'd like the dependency check
    to be against. Example, dep_choice='ridge'
    """
    tokens, texts = [], []

    for tok in doc:
        tokens.append(tok)
        texts.append(tok.text)

    # grabs the index/indices of the token that you are interested in
    indices = [i for i,text in enumerate(texts) if text==dep_choice]

    words_in_path = []

    for i in indices:

        reference = tokens[i]
        child_elements = [t.text for t in reference.get_children()]
        if word_to_check in child_elements:
            words_in_path.append((word_to_check, reference))

    return words_in_path

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

РЕДАКТИРОВАТЬ:

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

# This will give you 'word':<spaCy doc object> key value lookup capability
tokens_lookup = {tok.text:tok for tok in doc}

if "misty" in tokens_lookup.get("ridge").children:
    # Extra logic here
person C.Nivs    schedule 10.07.2018
comment
Сначала спасибо за ваш ответ после того, как попробовали ваш код, и если я хорошо понял, find_dependencies возвращает кортеж, только если word_to_check является дочерним по отношению к dep_choice, и этот кортеж состоит из этих двух аргументов. Однако я не понимаю интереса этой функции к моей проблеме, которая может быть решена чем-то вроде if(word_to_check in dep_choice.children) then ... Я могу что-то упустить, но что я действительно пытаюсь сделать, это, учитывая две сущности в предложении и слово, вернуть true ( соотв. false), если это слово находится на пути dep между этими объектами - person Valentin Macé; 11.07.2018
comment
Может быть, это симптом того, что я не совсем понимаю, чего вы хотите. Если вы просто ищете логический ответ, тогда if(word_to_check in dep_choice.children) then ... может быть всем, что вам нужно. - person C.Nivs; 11.07.2018
comment
Отредактировал свой ответ, чтобы включить то, что, я думаю, вы ищете. Дайте мне знать, если это немного ближе к тому, что вам нужно - person C.Nivs; 11.07.2018
comment
Чтобы прояснить, что мне действительно нужно, предположим, что мы выбрали две сущности в моем примере предложения. Мне нужно сгенерировать путь зависимости между этими объектами, а затем для каждого слова в предложении проверить, является ли слово частью пути зависимости. Итак, спасибо, потому что вы помогли мне уточнить, что я ищу на самом деле только путь между двумя словами, остальное довольно тривиально, я вернусь с моим окончательным решением - person Valentin Macé; 11.07.2018