Un parseo de dependencias devuelve las dependencias que se dan entre los tokens de una oración. Estas dependencias suelen darse entre pares de tokens.
Aquí definimos un algoritmo basado en transiciones para parsear dependencias. Proponemos una serie de reglas simples para analizar de manera sencilla oraciones con estructura simple.
from nltk.stem import SnowballStemmer
#Genera un stemmer para simplificar los tokens
stemmer = SnowballStemmer('spanish')
Definimos un parser que considera las relaciones entre sustantivos, verbos y determinantes. Se asumen las siguientes reglas:
#Categoría de tokens
Nouns = ['gat','perr', 'niñ', 'sop']
Verbs = ['corr', 'jueg', 'com', 'salt']
Dets = ['el', 'la', 'un', 'las', 'los', 'unos']
def parse(sentence):
"""
Función para parseo de dependencias a partir de reglas simples basadas en
relaciones de sustantivos, verbos y determinantes.
Arguments
---------
sentence : list
Lista de tokens para parsear.
Returns
-------
dependencies : list
Lista de dependencias entre pares de palabras.
"""
#Inicializa el stack
stack = ['root']
#Guarda tokens en buffer
buffer = sentence.split()
#Guarda las dependencias
dependencies = []
#Agrega primer token del buffer a stack
new_token = buffer.pop(0)
stack.append(new_token)
#Criterio de finalización
final = False
while final == False:
#Obtiene tokens en tope de stack
w1 = stack[-1]
w2 = stack[-2]
#Realiza stemming de los tokens
s1 = stemmer.stem(w1)
s2 = stemmer.stem(w2)
#Regla LeftArrow para dependencia DET
if s1 in Nouns and s2 in Dets:
dependencies.append('{} <--DET {}'.format(w2,w1))
stack.remove(w2)
#Regla LeftArrow para dependencia NSUBJ
elif s1 in Verbs and s2 in Nouns:
dependencies.append('{} <--NSUBJ {}'.format(w2,w1))
stack.remove(w2)
#Regla RightArrow para dependencia OBJ
elif s1 in Nouns and s2 in Verbs:
dependencies.append('{} DOBJ--> {}'.format(w2,w1))
stack.remove(w1)
#Shift
else:
try:
#Intenta obtener elemento del buffer
new_token = buffer.pop(0)
stack.append(new_token)
except:
#Si no lo logra detiene el algoritmo
final = True
return dependencies
Aplicamos el algoritmo a un ejemplo simple:
sentence = 'la niña come la sopa'
print(parse(sentence))
['la <--DET niña', 'niña <--NSUBJ come', 'la <--DET sopa', 'come DOBJ--> sopa']
Las dependencias que se dan son simples, y se pierden relaciones complejas; por ejemplo, oraciones como 'la sopa come la niña' asume que 'la sopa' es sujeto. Para lidiar con estos casos podría ampliarse las categorías de las palabras e incluir categorías como 'Sustantivo animado'.