Posterior a de nuestra extensa búsqueda de datos dimos con la respuesta este apuro que tienen ciertos lectores. Te dejamos la solución y deseamos que te resulte de gran ayuda.
Solución:
En caso de que alguien quiera ver fácilmente el árbol de dependencias producido por spacy, una solución sería convertirlo en un nltk.tree.Tree
y usa el nltk.tree.Tree.pretty_print
método. Aquí hay un ejemplo:
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]
Producción:
jumps
________________|____________
| | | | | over
| | | | | |
| | | | | dog
| | | | | ___|____
The quick brown fox . the lazy
Editar: Para cambiar la representación del token, puede hacer esto:
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)
Lo que resulta en:
jumps_VBZ
__________________________|___________________
| | | | | over_IN
| | | | | |
| | | | | dog_NN
| | | | | _______|_______
The_DT quick_JJ brown_JJ fox_NN ._. the_DT lazy_JJ
El árbol no es un objeto en sí mismo; simplemente navega a través de las relaciones entre tokens. Es por eso que los documentos hablan de navegar por el árbol, pero no de ‘obtenerlo’.
Primero, analicemos un poco de texto para obtener una Doc
objeto:
>>> import spacy
>>> nlp = spacy.load('en_core_web_sm')
>>> doc = nlp('First, I wrote some sentences. Then spaCy parsed them. Hooray!')
doc
es un Sequence
de Token
objetos:
>>> doc[0]
First
>>> doc[1]
,
>>> doc[2]
I
>>> doc[3]
wrote
Pero no tiene un solo token raíz. Analizamos un texto compuesto por tres oraciones, por lo que hay tres árboles distintos, cada uno con su propia raíz. Si queremos comenzar nuestro análisis desde la raíz de cada oración, ayudará obtener las oraciones como objetos distintos, primero. Afortunadamente, doc
nos las expone a través de la .sents
propiedad:
>>> sentences = list(doc.sents)
>>> for sentence in sentences:
... print(sentence)
...
First, I wrote some sentences.
Then spaCy parsed them.
Hooray!
Cada una de estas oraciones es una Span
con un .root
propiedad que apunta a su token raíz. Por lo general, el token raíz será el verbo principal de la oración (aunque esto puede no ser así). true para estructuras de oraciones inusuales, como oraciones sin verbo):
>>> for sentence in sentences:
... print(sentence.root)
...
wrote
parsed
Hooray
Con el token raíz encontrado, podemos navegar hacia abajo en el árbol a través de la .children
propiedad de cada token. Por ejemplo, busquemos el sujeto y el objeto del verbo en la primera oración. los .dep_
la propiedad de cada token hijo describe su relación con su padre; por ejemplo un dep_
de 'nsubj'
significa que un token es el sujeto nominal de su padre.
>>> 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
También podemos seguir bajando por el árbol viendo uno de los hijos de estos tokens:
>>> list(obj.children)
[some]
Por lo tanto, con las propiedades anteriores, puede navegar por todo el árbol. Si desea visualizar algunos árboles de dependencia para oraciones de ejemplo que lo ayuden a comprender la estructura, le recomiendo jugar con displaCy.
Puede usar la biblioteca a continuación para ver su árbol de dependencias, ¡lo encontró extremadamente útil!
import spacy
from spacy import displacy
nlp = spacy.load('en')
doc = nlp(u'This is a sentence.')
displacy.serve(doc, style='dep')
Puede abrirlo con su navegador, y se ve así:
Para generar un archivo SVG:
from pathlib import Path
output_path = Path("yourpath/.svg")
svg = displacy.render(doc, style='dep')
with output_path.open("w", encoding="utf-8") as fh:
fh.write(svg)