Я пытаюсь найти, как получить дерево зависимостей с помощью spaCy, но я не могу найти ничего о том, как получить дерево, только на как перемещение по дереву.
Как получить дерево зависимостей с помощью spaCy?
Ответ 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[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). Надеюсь, что это поможет