Подтвердить что ты не робот

Как получить дерево зависимостей с помощью spaCy?

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

4b9b3361

Ответ 1

Оказывается, дерево доступно через токены в документе.

Вы хотите найти корень дерева, вы можете просто пойти по документу:

def find_root(docu):
    for token in docu:
        if token.head is token:
            return token

Чтобы затем перемещаться по дереву, маркеры имеют API для получения через дочерние элементы

Ответ 2

Если кто-то хочет легко просмотреть дерево зависимостей, созданное spacy, одним из решений было бы преобразовать его в nltk.tree.Tree и использовать метод nltk.tree.Tree.pretty_print. Вот пример:

import spacy
from nltk import Tree


en_nlp = spacy.load('en')

doc = en_nlp("The quick brown fox jumps over the lazy dog.")

def to_nltk_tree(node):
    if node.n_lefts + node.n_rights > 0:
        return Tree(node.orth_, [to_nltk_tree(child) for child in node.children])
    else:
        return node.orth_


[to_nltk_tree(sent.root).pretty_print() for sent in doc.sents]

Вывод:

                jumps                  
  ________________|____________         
 |    |     |     |    |      over     
 |    |     |     |    |       |        
 |    |     |     |    |      dog      
 |    |     |     |    |    ___|____    
The quick brown  fox   .  the      lazy

Изменить: Для изменения представления маркера вы можете сделать это:

def tok_format(tok):
    return "_".join([tok.orth_, tok.tag_])


def to_nltk_tree(node):
    if node.n_lefts + node.n_rights > 0:
        return Tree(tok_format(node), [to_nltk_tree(child) for child in node.children])
    else:
        return tok_format(node)

Результат:

                         jumps_VBZ                           
   __________________________|___________________             
  |       |        |         |      |         over_IN        
  |       |        |         |      |            |            
  |       |        |         |      |          dog_NN        
  |       |        |         |      |     _______|_______     
The_DT quick_JJ brown_JJ   fox_NN  ._. the_DT         lazy_JJ

Ответ 3

Дерево не является само по себе; вы просто перемещаете его через отношения между токенами. Вот почему документы говорят о навигации по дереву, но не "получают" его.

Сначала давайте проанализировать текст, чтобы получить объект Doc:

>>> import spacy
>>> nlp = spacy.load('en')
>>> doc = nlp('First, I wrote some sentences. Then spaCy parsed them. Hooray!')

Doc является Sequence Token:

>>> doc[0]
First
>>> doc[1]
,
>>> doc[2]
I
>>> doc[3]
wrote

Но у него нет ни одного корневого токена. Мы проанализировали текст, состоящий из трех предложений, поэтому есть три разных дерева, каждый из которых имеет свой собственный корень. Если мы хотим начать наш синтаксический анализ из корня каждого предложения, это поможет сначала получить предложения как отдельные объекты. К счастью, Doc предоставляет их нам через свойство .sents:

>>> sentences = list(doc.sents)
>>> for sentence in sentences:
...     print(sentence)
... 
First, I wrote some sentences.
Then spaCy parsed them.
Hooray!

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

>>> for sentence in sentences:
...     print(sentence.root)
... 
wrote
parsed
Hooray

При обнаружении найденного корневого маркера мы можем перемещаться по дереву через свойство .children каждого токена. Например, можно найти предмет и объект глагола в первом предложении. Свойство .dep_ каждого дочернего токена описывает его связь с его родителем; например, dep_ of 'nsubj' означает, что токен является номинальным субъектом его родителя.

>>> root_token = sentences[0].root
>>> for child in root_token.children:
...     if child.dep_ == 'nsubj':
...         subj = child
...     if child.dep_ == 'dobj':
...         obj = child
... 
>>> subj
I
>>> obj
sentences

Мы также можем продолжать спускаться по дереву, просматривая один из этих детей-токенов:

>>> list(obj.children)
[some]

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

Ответ 4

Мне также нужно было сделать это ниже полного кода:

import sys
def showTree(sent):
    def __showTree(token):
        sys.stdout.write("{")
        [__showTree(t) for t in token.lefts]
        sys.stdout.write("%s->%s(%s)" % (token,token.dep_,token.tag_))
        [__showTree(t) for t in token.rights]
        sys.stdout.write("}")
    return __showTree(sent.root)

И если вам нужен интервал для терминала:

def showTree(sent):
    def __showTree(token, level):
        tab = "\t" * level
        sys.stdout.write("\n%s{" % (tab))
        [__showTree(t, level+1) for t in token.lefts]
        sys.stdout.write("\n%s\t%s [%s] (%s)" % (tab,token,token.dep_,token.tag_))
        [__showTree(t, level+1) for t in token.rights]
        sys.stdout.write("\n%s}" % (tab))
    return __showTree(sent.root, 1)

Ответ 5

У меня еще недостаточно знаний о разборе. Однако результат моего исследования литературы привел к тому, что spaCy имеет алгоритм синтаксического анализа зависимостей сдвига. Это анализирует вопрос/предложение, в результате чего дерево синтаксического анализа. Чтобы визуализировать это, вы можете использовать DisplaCy, комбинацию CSS и Javascript, работает с Python и Cython. Кроме того, вы можете проанализировать использование библиотеки SpaCy и импортировать набор инструментов Natural Language Toolkit (NLTK). Надеюсь, что это поможет