Curso de procesamiento del lenguaje natural -...

26
César Antonio Aguilar Facultad de Letras 04/11/2015 Curso de procesamiento del lenguaje natural [email protected]

Transcript of Curso de procesamiento del lenguaje natural -...

César Antonio Aguilar

Facultad de Letras

04/11/2015

Curso de procesamiento del

lenguaje natural

[email protected]

2

Solución de la Tarea I (1)

Como quedamos en la clase pasada, vamos a revisar la tarea pasada, en

donde realizamos un análisis de dos corpus diferentes de medicina. Así,

empecemos con lo básico: cargar nuestro corpus, y convertirlo en una

lista de palabras. Veamos:

Comprobamos:

type(corpus_medicina01)

len(corpus_medicina01)

Importando archivo:

corpus_medicina01 =

open(‘C://Anaconda3/Corpus_Pruebas/corpus_medicina_grupo

_a_01.txt’, encoding=‘utf-8’).read()

3

Solución de la Tarea I (2)

¿Por qué dimos una instrucción diferente esta vez? Básicamente, porque

el primer corpus tiene un problema de codificación, ya que viene en un

formato distinto a UTF-8. Por ello, fue necesario emplear la función

encoding. Aplicándola, ¿qué resultado obtenemos?:

4

Solución de la Tarea I (3)

Una vez fijada nuestra cadena de caracteres, ahora vamos a generar una

lista de tokens:

Comprobamos:

tokens_medicina01 = nltk.word_tokenize(corpus_medicina01)

type(tokens_medicina01)

len(tokens_medicina01)

5

Solución de la Tarea I (4)

Tras crear nuestra lista de tokens, podemos generar una colección de

textos con la siguiente instrucción:

text_medicine01 = nltk.Text(tokens_medicina01)

Comprobamos:

type(text_medicina01)

len(text_medicina01)

6

Solución de la Tarea I (5)

La siguiente fase de la tarea consistía en hacer una búsqueda de

concordancias, considerando 5 términos: analysis, disease, disorder, test

y treatment. Veamos el primer caso:

7

Solución de la Tarea I (6)

Ahora revisemos qué palabras se vinculan a analysis en un contexto

similar:

8

Solución de la Tarea I (6)

Finalmente, creamos un gráfico de dispersión con los 5 términos

considerados:

9

Solución de la Tarea I (7)

Completado el siguiente gráfico, pasamos a la siguiente parte, que era

crear un corpus etiquetado. La instrucción para hacerlo es:

tags_medicina01 = nltk.pos_tag(tokens_medicina01)

Comprobamos:

type(tags_medicina01)

len(tags_medicina01)

tags_medicina01[0:200]

10

Implementando un chunker (1)

Una vez hecho esto, podemos analizar la siguiente oración, la cual cuenta

con etiquetas morfosintácticas:

import nltk, re, os

Lo que hemos visto con la tarea nos sirve muy bien para empezar a usar

chunkers que nos ayuden a reconocer patrones sintácticos. Veamos un

ejemplo, importando primero las siguientes librerías:

sentence01 = [("the", "DT"), ("little", "JJ"), ("yellow",

"JJ"), ("dog", "NN"), ("barked", "VBD"), ("at", "IN"),

("the", "DT"), ("cat", "NN")]

11

Implementando un chunker (2)

¿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.

grammar01 = "NP: {<DT>?<JJ>*<NN>}”

cp = nltk.RegexpParser(grammar01)

result01 = cp.parse(sentence01)

print (result01)

result01.draw()

Ahora, escribamos el siguiente código:

12

Implementando un chunker (3)

El resultado es:

13

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:

Implementando un chunker (4)

14

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()

sentence02 = [("Rapunzel", "NNP"), ("let", "VBD"), ("down", "RP"),

("her", "PP$"), ("long", "JJ"), ("golden", "JJ"), ("hair", "NN")]

Y el resultado es:

Nuestra gramática va a ser la siguiente:

Implementando un chunker (5)

15

Implementando un chunker (6)

16

Implementando un chunker (7)

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

17

Implementando un chunker (8)

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)

18

Implementando un chunker (9)

Y el resultado final, si

confiamos en nuestro

proceso, son frases

verbales que dentro del

Brown sigan el patrón

Verbo + TO + Verbo :

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

El resultado es:

print(conll2000.chunked_sents('train.txt')[99])

Veamos un fragmento del CoNLL 2000, usando esta

instrucción:

Métodos de evaluación (2)

El resultado lo vemos en la siguiente lámina:

cp = nltk.RegexpParser("")

test_sents = conll2000.chunked_sents('test.txt',

chunk_types=['NP'])

print (cp.evaluate(test_sents))

Una vez que hemos visto parte del contenido del CoNLL 2000,

implementemos el siguiente ciclo:

Métodos de evaluación (3)

Pregunta: ¿por qué nos da como resultado cero? ¿Qué es lo

que estamos buscando en este corpus?

Métodos de evaluación (4)

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:

grammar = r"NP: {<[CDJNP].*>+}"

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:

Métodos de evaluación (5)

grammar = r"NP: {<[CDJNP].*>+}"

test_sents = conll2000.chunked_sents('test.txt’,

chunk_types=['NP’])

cp = nltk.RegexpParser(grammar)

print (cp.evaluate(test_sents))

Nuestro código es:

Métodos de evaluación (6)

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.

Métodos de evaluación (7)

Blog del curso:

http://cesaraguilar.weebly.com/curso-de-

procesamiento-del-lenguaje-natural.html

Gracias por su atención