¿Cómo hacer un árbol a partir de la salida de un analizador de dependencia?

Estoy intentando hacer un árbol (diccionario nested) a partir de la salida del analizador de dependencias. La frase es “Le disparé a un elefante mientras dormía”. Puedo obtener la salida como se describe en el enlace: ¿Cómo hago el análisis de dependencias en NLTK?

nsubj(shot-2, I-1) det(elephant-4, an-3) dobj(shot-2, elephant-4) prep(shot-2, in-5) poss(sleep-7, my-6) pobj(in-5, sleep-7) 

Para convertir esta lista de tuplas en un diccionario nested, utilicé el siguiente enlace: ¿Cómo convertir la lista de tuplas de python en árbol?

 def build_tree(list_of_tuples): all_nodes = {n[2]:((n[0], n[1]),{}) for n in list_of_tuples} root = {} print all_nodes for item in list_of_tuples: rel, gov,dep = item if gov is not 'ROOT': all_nodes[gov][1][dep] = all_nodes[dep] else: root[dep] = all_nodes[dep] return root 

Esto da la salida de la siguiente manera:

 {'shot': (('ROOT', 'ROOT'), {'I': (('nsubj', 'shot'), {}), 'elephant': (('dobj', 'shot'), {'an': (('det', 'elephant'), {})}), 'sleep': (('nmod', 'shot'), {'in': (('case', 'sleep'), {}), 'my': (('nmod:poss', 'sleep'), {})})})} 

Para encontrar la ruta de la raíz a la hoja, utilicé el siguiente enlace: Regresar la raíz a una hoja específica de un árbol de diccionario nested

[Hacer el árbol y encontrar la ruta son dos cosas separadas] El segundo objective es encontrar la ruta del nodo de la raíz a la hoja como hecho. Devuelva la raíz a la hoja específica de un árbol de diccionario nested . Pero quiero obtener la raíz a la hoja (ruta de relación de dependencia) Entonces, por ejemplo, cuando llamaré recurse_category (categorías, ‘an’) donde categorías es la estructura de árbol anidada y ‘an’ es la palabra en el árbol , Debería obtener ROOT-nsubj-dobj (relación de dependencia hasta la raíz) como salida.

Esto convierte la salida a la forma del diccionario nested. Te mantendré informado si puedo encontrar el camino también. Tal vez esto, es útil.

 list_of_tuples = [('ROOT','ROOT', 'shot'),('nsubj','shot', 'I'),('det','elephant', 'an'),('dobj','shot', 'elephant'),('case','sleep', 'in'),('nmod:poss','sleep', 'my'),('nmod','shot', 'sleep')] nodes={} for i in list_of_tuples: rel,parent,child=i nodes[child]={'Name':child,'Relationship':rel} forest=[] for i in list_of_tuples: rel,parent,child=i node=nodes[child] if parent=='ROOT':# this should be the Root Node forest.append(node) else: parent=nodes[parent] if not 'children' in parent: parent['children']=[] children=parent['children'] children.append(node) print forest 

La salida es un diccionario nested,

[{'Name': 'shot', 'Relationship': 'ROOT', 'children': [{'Name': 'I', 'Relationship': 'nsubj'}, {'Name': 'elephant', 'Relationship': 'dobj', 'children': [{'Name': 'an', 'Relationship': 'det'}]}, {'Name': 'sleep', 'Relationship': 'nmod', 'children': [{'Name': 'in', 'Relationship': 'case'}, {'Name': 'my', 'Relationship': 'nmod:poss'}]}]}]

La siguiente función puede ayudarlo a encontrar la ruta de raíz a hoja:

 def recurse_category(categories,to_find): for category in categories: if category['Name'] == to_find: return True, [category['Relationship']] if 'children' in category: found, path = recurse_category(category['children'], to_find) if found: return True, [category['Relationship']] + path return False, [] 

En primer lugar, si solo está usando el modelo pre-entrenado para el analizador de dependencia Stanford CoreNLP, debe usar el CoreNLPDependencyParser de nltk.parse.corenlp y evitar usar la antigua interfaz nltk.parse.stanford .

Ver Stanford Parser y NLTK

Después de descargar y ejecutar el servidor Java en la terminal, en Python:

 >>> from nltk.parse.corenlp import CoreNLPDependencyParser >>> dep_parser = CoreNLPDependencyParser(url='http://localhost:9000') >>> sent = "I shot an elephant with a banana .".split() >>> parses = list(dep_parser.parse(sent)) >>> type(parses[0])  

Ahora vemos que los análisis son del tipo DependencyGraph de nltk.parse.dependencygraph https://github.com/nltk/nltk/blob/develop/nltk/parse/dependencygraph.py#L36

Para convertir DependencyGraph en un objeto nltk.tree.Tree simplemente haciendo DependencyGraph.tree() :

 >>> parses[0].tree() Tree('shot', ['I', Tree('elephant', ['an']), Tree('banana', ['with', 'a']), '.']) >>> parses[0].tree().pretty_print() shot _________|____________ | | elephant banana | | | _____|_____ I . an with a 

Para convertirlo en el formato de paréntesis entre corchetes:

 >>> print(parses[0].tree()) (shot I (elephant an) (banana with a) .) 

Si buscas trillizos de dependencia:

 >>> [(governor, dep, dependent) for governor, dep, dependent in parses[0].triples()] [(('shot', 'VBD'), 'nsubj', ('I', 'PRP')), (('shot', 'VBD'), 'dobj', ('elephant', 'NN')), (('elephant', 'NN'), 'det', ('an', 'DT')), (('shot', 'VBD'), 'nmod', ('banana', 'NN')), (('banana', 'NN'), 'case', ('with', 'IN')), (('banana', 'NN'), 'det', ('a', 'DT')), (('shot', 'VBD'), 'punct', ('.', '.'))] >>> for governor, dep, dependent in parses[0].triples(): ... print(governor, dep, dependent) ... ('shot', 'VBD') nsubj ('I', 'PRP') ('shot', 'VBD') dobj ('elephant', 'NN') ('elephant', 'NN') det ('an', 'DT') ('shot', 'VBD') nmod ('banana', 'NN') ('banana', 'NN') case ('with', 'IN') ('banana', 'NN') det ('a', 'DT') ('shot', 'VBD') punct ('.', '.') 

En formato CONLL:

 >>> print(parses[0].to_conll(style=10)) 1 II PRP PRP _ 2 nsubj _ _ 2 shot shoot VBD VBD _ 0 ROOT _ _ 3 an a DT DT _ 4 det _ _ 4 elephant elephant NN NN _ 2 dobj _ _ 5 with with IN IN _ 7 case _ _ 6 aa DT DT _ 7 det _ _ 7 banana banana NN NN _ 2 nmod _ _ 8 . . . . _ 2 punct _ _