láminas para la clase de hoy

Transcripción

láminas para la clase de hoy
Curso de procesamiento del
lenguaje natural
César Antonio Aguilar
Facultad de Letras
19/10/2016
[email protected]
Análisis de frases con NLTK (1)
Como hemos señalado en clases anteriores, el análisis sintáctico de un texto
es una tarea que podemos emprender usando y combinando criterios
lingüísticos y estadísticos, creando así métodos híbridos eficaces.
2
Análisis de frases con NLTK (2)
Ahora, como hemos señalado también antes, existen dos tipos de objetos
sintácticos que podemos analizar: frases y oraciones. Los métodos y técnicas
que se ocupan para hacer análisis de frase se les agrupa usualmente con el
término chunking (literalmente, trozado o partición de oraciones en frases):
3
Análisis de frases con NLTK (3)
La partición de una oración en frases es parte de un criterio jerárquico
sencillo de deducir: lo que queremos identificar son combinaciones de
palabras que, gramaticalmente, cumplan un rol como núcleo de una frase, o
como modificador ligado a dicho núcleo. Los mejores candidatos son las
frases nominales (NPs):
4
Implementando un chunker (1)
Veamos ahora cómo podemos programar un analizador de frases con NLTK,
importando las siguientes librerías:
import nltk, re, os
Una vez hecho esto, podemos analizar la siguiente oración, la cual cuenta
con etiquetas morfosintácticas:
sentence01 = [("the", "DT"), ("little", "JJ"), ("yellow",
"JJ"), ("dog", "NN"), ("barked", "VBD"), ("at", "IN"),
("the", "DT"), ("cat", "NN")]
5
Implementando un chunker (2)
Ahora, escribamos el siguiente código:
grammar01 = "NP: {<DT>?<JJ>*<NN>}”
cp = nltk.RegexpParser(grammar01)
result01 = cp.parse(sentence01)
print (result01)
result01.draw()
¿Qué obtenemos con esto?:
1. Una estructura arbórea, en donde se indica con paréntesis cuáles son las
frases que cumplen con el patrón que establecimos en nuestra gramática.
2. El gráfico de un árbol sintáctico, el cual representa la estructura sintáctica
de nuestra oración.
6
Implementando un chunker (3)
El resultado es:
7
Implementando un chunker (4)
Si observan, nuestra gramática es una secuencia de etiquetas con
expresiones regulares, las cuales simplemente indican aquí:
1. Busca toda secuencia que inicie con un determinante (o DT), más
cualquier otra palabra subsecuente.
2. A esta cadena se debe ligar un adjetivo (o JJ), el cual puede tener
una recurrencia de 0 a infinito.
3. Finalmente, a esta secuencia se liga un nombre común (o NN).
Las reglas y patrones que podamos construir con nuestras
gramáticas pueden ser tan simples o complejos como lo creamos
conveniente. Veamos el siguiente ejemplo:
8
Implementando un chunker (5)
sentence02 = [("Rapunzel", "NNP"), ("let", "VBD"), ("down", "RP"),
("her", "PP$"), ("long", "JJ"), ("golden", "JJ"), ("hair", "NN")]
Nuestra gramática va a ser la siguiente:
grammar02 = r”””
NP: {<DT|PP\$>?<JJ>*<NN>} # Frases que tengan determinante/posesivo,
adjetivo y nombre
{<NNP>+}
# Frases con nombres propios
”””
cp = nltk.RegexpParser(grammar02)
result02 = cp.parse(sentence02)
print (result02)
result02.draw()
Y el resultado es:
9
Implementando un chunker (6)
10
Implementando un chunker (7)
Las frases anteriores, claro
está, son ejemplos
simples.
¿Qué pasa con secuencias
más complejas? Veamos:
Text01 = '''
he PRP B-NP
accepted VBD B-VP
the DT B-NP
position NN I-NP
of IN B-PP
vice NN B-NP
chairman NN I-NP
of IN B-PP
Carlyle NNP B-NP
Group NNP I-NP
,,O
a DT B-NP
merchant NN I-NP
banking NN I-NP
concern NN I-NP
..O
'''
11
Implementando un chunker (8)
Apliquen ahora la siguiente instrucción:
nltk.chunk.conllstr2tree(Text01, chunk_types=['NP']).draw()
Y el resultado es:
12
Implementando un chunker (9)
Como lo hemos comentado antes, NLTK cuenta con una serie de corpus
etiquetados que podemos aprovechar para hacer varias tareas. Una de ellas
es justo la detección de frases empleando estas técnicas de chunking. Por
ejemplo, tratemos de identificar frases que sigan la secuencia Verbo + TO +
Verbo en el Brown Corpus.
Para ello, requerimos de una gramática, así como importar el Brown Corpus
a nuestro intérprete:
cp = nltk.RegexpParser(‘CHUNK: {<V.*> <TO> <V.*>}’)
brown = nltk.corpus.brown
13
Implementando un chunker (10)
Ahora, lo que vamos a hacer es elaborar un ciclo, el cual nos
permita reconocer cuáles son las oraciones que, dentro del
Brown, cumplan con nuestra regla. Una vez que las
detectemos, las agruparemos en un listado que se desplegará
en pantalla. Veamos:
for sent in brown.tagged_sents():
tree = cp.parse(sent)
for subtree in tree.subtrees():
if subtree.label() == 'CHUNK': print (subtree)
14
Implementando un chunker (11)
Y el resultado final, si
confiamos en nuestro
proceso, son frases
verbales que dentro del
Brown sigan el patrón
Verbo + TO + Verbo :
15
Métodos de evaluación (1)
Tras haber hecho una exploración en el Corpus Brown, ahora
pasamos a implementar un método de evaluación estadístico,
con el fin de evaluar si nuestras gramáticas son eficaces o no
para localizar los patrones que buscamos.
Para esta tarea, vamos a ocupar un corpus etiquetado llamado
CoNLL 2000, el cual está seccionado en frases. Así, requerimos
de esta instrucción:
from nltk.corpus import conll2000
Métodos de evaluación (2)
Veamos un fragmento del CoNLL 2000, usando esta
instrucción:
print(conll2000.chunked_sents('train.txt')[99])
El resultado es:
Métodos de evaluación (3)
Una vez que hemos visto parte del contenido del CoNLL 2000,
implementemos el siguiente ciclo:
cp = nltk.RegexpParser("")
test_sents = conll2000.chunked_sents('test.txt',
chunk_types=['NP'])
print (cp.evaluate(test_sents))
El resultado lo vemos en la siguiente lámina:
Métodos de evaluación (4)
Pregunta: ¿por qué nos da como resultado cero? ¿Qué es lo
que estamos buscando en este corpus?
Métodos de evaluación (5)
La razón por la cual no nos presenta ningún resultado es
porque no hemos definido una gramática. Probemos con la
siguiente regla:
grammar = r"NP: {<[CDJNP].*>+}"
La regla que acabos de escribir nos permite localizar frases
nominales que estén conformadas por un número cardinal (CD),
un determinante (DT), un adjetivo (JJ) y nombre (NN).
Ahora, unamos esta gramática con nuestro código anterior, y
obtenemos:
Métodos de evaluación (6)
Nuestro código es:
grammar = r"NP: {<[CDJNP].*>+}"
test_sents = conll2000.chunked_sents('test.txt’,
chunk_types=['NP’])
cp = nltk.RegexpParser(grammar)
print (cp.evaluate(test_sents))
Métodos de evaluación (7)
Las medidas que hemos generado indican lo siguiente:
1. El índice IOB indica el total de palabras que fueron
excluidas de nuestra gramática, porque no forman parte de la
estructura de una frase nominal.
2. El índice de Precision nos muestra el total de patrones que
mejor encuadran con nuestra regla sobre constitución de una
FN.
3. El índice de Recall indica el total de candidatos a FN que
hay en nuestro corpus.
4. El índice F-Measure establece un ajuste entre Precision y
Recall.
NLTK para el español: esto es lo que hay (1)
Siendo demasiado francos, si bien NLTK cuenta con un corpus en español,
las colecciones de árboles sintácticos llamadas CESS Treebanks (que son
derivados del proyecto Freeling), en español y catalán, estos recursos no
permiten todavía desarrollar un proceso de etiquetado de nuevos
documentos, como pasa con el corpus Brown. Las razones son varias:
1. Los corpus CESS están diseñados para mostrar resultados respecto a las
consultas que hagamos en ellos, pero no permiten implementar algún
proceso de aprendizaje para un etiquetador en español.
2. Todavía no se ha desarrollado algún método en NLTK para entrenar un
etiquetador en español.
3. No hay un corpus etiquetado de referencia en español, el cual sea de libre
uso, y pueda formar parte de las librerías de NLTK.
4. No hay criterios unificados sobre el proceso de etiquetado de palabras en
español.
NLTK para el español: esto es lo que hay (2)
Si probamos la demo que ofrece Freeling en línea, podemos ver que
se cuentan con algunos recursos para el etiquetado de oraciones,
p.e.:
Incluso podemos graficar árboles sintácticos con cierto grado de
complejidad, digamos un parseo basado en gramática de
dependencias. Veamos la siguiente lámina:
NLTK para el español: esto es lo que hay (3)
NLTK para el español: esto es lo que hay (4)
Esto último sí podemos hacerlo desde NLTK: lanzar consultas al
corpus CESS en español, mostrar sus resultados, e incluso generar
árboles sintácticos con las oraciones que hay en tal corpus. Así, si
ocupan la instrucción:
from nltk.corpus import cess_esp
nltk.corpus.cess_esp.words()
Nos muestra el ejemplo de una oración:
['El', 'grupo', 'estatal', 'Electricit\xe9_de_France', ...]
NLTK para el español: esto es lo que hay (5)
Las etiquetas que ocupa este corpus son una variante del sistema de
anotación EAGLES,el cual ustedes ya conocen. Si escriben:
nltk.corpus.cess_esp.tagged_words()
Nos arroja como resultado:
[('El', 'da0ms0'), ('grupo', 'ncms000'), ...]
Finalmente, podemos generar un esquema arbóreo, seleccionado
alguna de las oraciones que cuenta este corpus. Usemos esta
instrucción, y veamos el resultado en la siguiente lámina:
Tree01 = nltk.corpus.cess_esp.parsed_sents()[1].draw()
NLTK para el español: esto es lo que hay (6)
A manera de comentario final: hay muchas cosas por hacer todavía
respecto al uso de NLTK para el procesamiento de corpus, pero lo
importante es que hay soluciones. ¿Qué posibles vías creen que puedan
ser útiles para aprovechar estos recursos para el análisis de textos en
español?
Gracias por su atención
Blog del curso:
http://cesaraguilar.weebly.com/curso-deprocesamiento-del-lenguaje-natural.html

Documentos relacionados

Diapositiva 1 - Inicio

Diapositiva 1 - Inicio En esta clase, vamos a tratar de hacer algunos ejercicios mínimos con algunas herramientas disponibles para análisis de corpus lingüísticos, en concreto las suites de herramientas Jaguar (IULAUPF),...

Más detalles