J'ai essayé de trouver comment obtenir l'arbre de dépendance avec spaCy mais je ne trouve rien sur la façon d'obtenir l'arbre, mais uniquement sur comment naviguer dans l'arbre .
Il s’avère que l’arbre est disponible à travers les jetons dans un document.
Voudriez-vous trouver la racine de l’arbre, vous pouvez simplement consulter le document:
def find_root(docu):
for token in docu:
if token.head is token:
return token
Pour ensuite naviguer dans l’arbre, les jetons ont une API à obtenir à travers les enfants
Au cas où quelqu'un voudrait voir facilement l'arbre de dépendance produit par spacy, une solution consisterait à le convertir en nltk.tree.Tree
et utilisez le nltk.tree.Tree.pretty_print
méthode. Voici un exemple:
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]
Sortie:
jumps
________________|____________
| | | | | over
| | | | | |
| | | | | dog
| | | | | ___|____
The quick brown fox . the lazy
Edit: Pour modifier la représentation du jeton, vous pouvez procéder comme suit:
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)
Ce qui résulte en:
jumps_VBZ
__________________________|___________________
| | | | | over_IN
| | | | | |
| | | | | dog_NN
| | | | | _______|_______
The_DT quick_JJ brown_JJ fox_NN ._. the_DT lazy_JJ
L'arbre n'est pas un objet en soi; vous venez de naviguer via les relations entre les jetons. C'est pourquoi les docs parlent de naviguer dans l'arborescence, mais pas de "l'obtenir".
Commençons par analyser du texte pour obtenir un objet Doc
:
>>> import spacy
>>> nlp = spacy.load('en')
>>> doc = nlp('First, I wrote some sentences. Then spaCy parsed them. Hooray!')
doc
est un Sequence
de Token
objets:
>>> doc[0]
First
>>> doc[1]
,
>>> doc[2]
I
>>> doc[3]
wrote
Mais il n'a pas de jeton racine unique. Nous avons analysé un texte composé de trois phrases. Il existe donc trois arbres distincts, chacun avec sa propre racine. Si nous voulons commencer notre analyse à partir de la racine de chaque phrase, cela aidera d’abord à obtenir les phrases comme objets distincts. Heureusement, doc
nous les expose via le .sents
propriété:
>>> sentences = list(doc.sents)
>>> for sentence in sentences:
... print(sentence)
...
First, I wrote some sentences.
Then spaCy parsed them.
Hooray!
Chacune de ces phrases est un Span
avec un .root
propriété pointant vers son jeton racine. Généralement, le jeton racine sera le verbe principal de la phrase (bien que cela puisse ne pas être vrai pour les structures de phrases inhabituelles, telles que les phrases sans verbe):
>>> for sentence in sentences:
... print(sentence.root)
...
wrote
parsed
Hooray
Avec le jeton racine trouvé, nous pouvons naviguer dans l’arbre via le .children
propriété de chaque jeton. Par exemple, trouvons le sujet et l'objet du verbe dans la première phrase. Le .dep_
propriété de chaque jeton enfant décrit sa relation avec son parent ; par exemple un dep_
de 'nsubj'
_ signifie qu'un jeton est le sujet nominal de son parent.
>>> 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
Nous pouvons également continuer à descendre l'arbre en regardant l'un des enfants de ces jetons:
>>> list(obj.children)
[some]
Ainsi, avec les propriétés ci-dessus, vous pouvez parcourir l’arbre entier. Si vous souhaitez visualiser des arbres de dépendance, par exemple des phrases pour vous aider à comprendre la structure, je vous recommande de jouer avec affichage .
Je ne sais pas s'il s'agit d'un nouvel appel d'API ou quoi, mais il existe une méthode .print_tree () sur la classe Document qui permet de résoudre rapidement ce problème.
https://spacy.io/api/doc#print_tree
Il vide l’arbre de dépendance en JSON. Il traite des racines de phrases multiples et de tout ça:
import spacy
nlp = spacy.load('en')
doc1 = nlp(u'This is the way the world ends. So you say.')
print(doc1.print_tree(light=True))
Le nom print _ tree est un peu impropre, la méthode elle-même n’imprime rien, elle renvoie plutôt une liste de dict, une pour chaque phrase. .
Vous pouvez utiliser la bibliothèque ci-dessous pour afficher votre arbre de dépendances, cela s’est révélé extrêmement utile!
from spacy import displacy
nlp = spacy.load('en')
doc = nlp(u'This is a sentence.')
displacy.serve(doc, style='dep')
Je devais aussi le faire en dessous du code complet:
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)
Et si vous voulez un espacement pour le terminal:
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)