Pipeline para el Procesamiento del Lenguaje Natural (NPL) a través de la librería spaCy
Autor/a
Mario Camacho
Fecha de publicación
25 agosto 2024
Fecha de modificación
27 agosto 2024
Resumen
La aplicación de nuevas fuentes de Inteligencia Artificial en el lenguaje humano está en auge desde la aparición de las IA Generativas de texto. Es por ello que se necesita tener un pipeline con los primeros pasos de NPL que debemos mantener en la resolución de problemas de mayor complejidad.
1 Preproceso
1.1 Ingesta del documento
Leemos el libro El Quijote.
Código
# Enviar una solicitud GET a la URLresponse = requests.get("https://www.gutenberg.org/cache/epub/2000/pg2000.txt")# Verificar si la solicitud fue exitosaif response.status_code ==200: quijote = response.text# print("Éxito al leer el texto.")else:print("Error al leer el texto.")
Nos ocupamos únicamente de los primeros seis capítulos de la primera parte de El Quijote.
Código
### Inicio del primer capítulo# Palabra objetivopalabra_start ="Primera parte del ingenioso hidalgo don Quijote de la Mancha"# Expresión regular para capturar todo lo que va antes de un patrón de búsquedapatron = re.compile(rf"{palabra_start}\s*(.*)", re.DOTALL)coincidencia = patron.search(quijote)if coincidencia: quijote = coincidencia.group(1) # 0 incluye la palabra del search, 1 no lo incluye console.print("[bold]Inicio del primer capítulo:\n\n[/bold]", quijote[:251])# print("Inicio del texto:\n\n", quijote[:251])else: console.print("[bold]Inicio del texto:\n\n[/bold]", quijote[:251])### Inicio del sépimo capítulo (y final del sexto)palabra_end ="Capítulo VII"# patron = re.compile(rf"(.*)\b{re.escape(palabra_end)}\b", re.DOTALL) # .* es codicioso ("greedy"): captura la mayor cantidad posible de caracteres antes de la coincidir con la palabra, captura hasta la última aparición de la palabra buscadapatron = re.compile(rf"(.*?)\b{re.escape(palabra_end)}\b", re.DOTALL) # .* es no codicioso ("lazy"): captura la menor cantidad posible de caracteres y evitar que el resto del texto cooincida, se detiene en la primera coincidenciacoincidencia = patron.search(quijote)if coincidencia: quijote = coincidencia.group(0) console.print("[bold]Final del sexto capítulo:\n\n[/bold]", quijote[-231:]) quijote = coincidencia.group(1) # Elimino el patrón de búsquedaelse: console.print("[bold]Final del texto:\n\n[/bold]", quijote[-231:])
Inicio del primer capítulo:
Capítulo primero. Que trata de la condición y ejercicio del famoso hidalgo
don Quijote de la Mancha
En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha mucho
tiempo que vivía un hidalgo de los de lanza en astillero, adarga antigua
Final del sexto capítulo:
o el cura en oyendo el nombre— si tal libro hubiera
mandado quemar; porque su autor fue uno de los famosos poetas del mundo, no
sólo de España, y fue felicísimo en la tradución de algunas fábulas de
Ovidio.
Capítulo VII
1.2 Carga del modelo
1.2.1 spaCy
What’s spaCy? spaCy es una biblioteca gratuita de código abierto para el procesamiento avanzado del lenguaje natural en Python.
La librería spaCy se basa en modelos de aprendizaje automático que se entrenaron con grandes cantidades de datos de texto etiquetados.
Descarga y carga del modelo de lenguaje a través de la librería spaCy:
# !python -m spacy download es_core_news_md
import spacynlp = spacy.load("es_core_news_md")
1.3 Fragmentación de la información
Podemos dividir el texto en párrafos.
Código
for parrafo inlist(nlp(quijote).sents)[:3]: # No es necesario pasarlo a una lista, solo para coger un número de ejemplos console.print("[blue]\nSiguiente párrafo:\n\n[/blue]", parrafo)#print(parrafo)
Siguiente párrafo:
Capítulo primero.
Siguiente párrafo:
Que trata de la condición y ejercicio del famoso hidalgo
don Quijote de la Mancha
En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha mucho
tiempo que vivía un hidalgo de los de lanza en astillero, adarga antigua,
rocín flaco y galgo corredor.
Siguiente párrafo:
Una olla de algo más vaca que carnero,
salpicón las más noches, duelos y quebrantos los sábados, lantejas los
viernes, algún palomino de añadidura los domingos, consumían las tres
partes de su hacienda.
Y los párrafos en palabras.
Código
for parrafo inlist(nlp(quijote).sents)[1:2]: console.print("[blue]\nSiguiente párrafo:\n[/blue]")# print(colored("\nSiguiente párrafo:\n",'blue'))for palabra in parrafo[:5]:print(palabra)
[Capítulo primero.,
Que trata de la condición y ejercicio del famoso hidalgo
don Quijote de la Mancha
En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha mucho
tiempo que vivía un hidalgo de los de lanza en astillero, adarga antigua,
rocín flaco y galgo corredor.,
Una olla de algo más vaca que carnero,
salpicón las más noches, duelos y quebrantos los sábados, lantejas los
viernes, algún palomino de añadidura los domingos, consumían las tres
partes de su hacienda.]
Etiqueta las palabras de un texto determinado según sus respectivos tipos de palabras, como sustantivos, adjetivos, adverbios y verbos.
El etiquetado POS es el proceso de identificar la categoría gramatical (como verbo, sustantivo, adjetivo, etc.) de cada palabra en una oración.
Las etiquetas que spaCy utiliza se basan en el trabajo realizado por Universal Dependencies, un repositorio común que se puede utilizar para entrenar modelos como spaCy. La página de Dependencias universales tiene información sobre los corpus disponibles para cada idioma.
propiedades = ['text', 'lang_', 'pos_', 'is_digit', 'is_lower', 'is_upper', 'is_sent_start', 'is_sent_end','like_email', 'like_url', # Espero no encontrar ninguna de estas etiquetas en El Quijote'sentiment', 'sent']
ejemplo_02 = nlp(re.sub(r'[^\w\s]', '', text))[:15]# Encabezadoprint(f'{"text":<12}{"lemma_":<12}{"pos":<12}{"pos_":<12}{"tag_":<12}{"dep_":<12}{"shape_":<12}{"is_alpha":<12}{"is_stop":<12}')print("="*12*9)# Loop que imprime los datos en formato de tablafor token in ejemplo_02:print(f'{token.text:<12}{token.lemma_:<11}{token.pos:<11}{token.pos_:<11}{token.tag_:<11}{token.dep_:<12}'f'{token.shape_:<11}{token.is_alpha:<11}{token.is_stop:<11}')
text lemma_ pos pos_ tag_ dep_ shape_ is_alpha is_stop
============================================================================================================
Capítulo Capítulo 96 PROPN PROPN nsubj Xxxxx 1 0
primero primero 84 ADJ ADJ advmod xxxx 1 1
Que Que 98 SCONJ SCONJ nsubj Xxx 1 1
trata tratar 100 VERB VERB acl xxxx 1 1
de de 85 ADP ADP case xx 1 1
la el 90 DET DET det xx 1 1
condición condición 92 NOUN NOUN obj xxxx 1 0
y y 89 CCONJ CCONJ cc x 1 1
ejercicio ejercicio 92 NOUN NOUN conj xxxx 1 0
del del 85 ADP ADP case xxx 1 1
famoso famoso 84 ADJ ADJ amod xxxx 1 0
hidalgo hidalgo 92 NOUN NOUN nmod xxxx 1 0
103 SPACE SPACE dep
0 0
don don 92 NOUN NOUN appos xxx 1 0
Quijote Quijote 96 PROPN PROPN flat Xxxxx 1 0
NER es el proceso de identificar entidades nombradas (como nombres de personas, lugares, organizaciones, etc.) en un texto. La biblioteca spaCy es particularmente útil para esta tarea.
Cada modelo de la librería spaCy tiene sus propias entidades, que se encuentran en la sección Label Scheme de la documentación del modelo. Para modelo cargado las entidades se almacenan con las etiqetas LOC, ORG, PER y MISC. (lugares, organizacoines, personas y un comodín para las tres anteriores)
Todas las entidades nombradas se encuentran en la propiedad document.ents.
documento = nlp(text)
Código
for named_entity inlist(documento.ents)[:10]:print(named_entity, named_entity.label_)
Que trata de la condición MISC
hidalgo PER
la Mancha LOC
Una olla de algo más vaca MISC
El resto della MISC
Tenía en su casa una MISC
Frisaba LOC
Quieren PER
Quijada PER
Quesada LOC
2.5.1 Búsqueda de una entidad en el documento
Podemos encontrar una entidad dentro de su propio contexto.
Que trata de la condición y ejercicio del famoso hidalgo don Quijote de la Mancha En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga antigua, rocín flaco y galgo corredor.
Resultado 2.
Tipo de entidad: PER
Contexto:
El labrador estaba admirado oyendo aquellos disparates; y, quitándole la visera, que ya estaba hecha pedazos de los palos, le limpió el rostro, que le tenía cubierto de polvo; y apenas le hubo limpiado, cuando le conoció y le dijo: — Señor Quijana —que así se debía de llamar cuando él tenía juicio y no había pasado de hidalgo sosegado a caballero andante—, ¿quién ha puesto a vuestra merced desta suerte? Pero él seguía con su romance a cuanto le preguntaba.
Resultado 3.
Tipo de entidad: PER
Contexto:
A esto respondió el labrador: — Mire vuestra merced, señor, pecador de mí, que yo no soy don Rodrigo de Narváez, ni el marqués de Mantua, sino Pedro Alonso, su vecino; ni vuestra merced es Valdovinos, ni Abindarráez, sino el honrado hidalgo del señor Quijana.
Usamos dos modelos distintos. Cada uno cuenta con sus propias entidades identificadas en el Label Scheme de cada modelo.
Visualizamos el texto María se fue en 2020 al río Guadiana a pescar peces coloridos mientras Mario iban a por bebida al supermercado Mercado. como ejemplo.
El primer modelo, es_core_news_md, el que hemos estado usando hasta ahora. Con cuatro entidades NER: LOC, MISC, ORG y PER.
María se fue
PERSON
en
2020
DATE
al río Guadiana
PERSON
a pescar peces coloridos mientras
Mario
PERSON
iban a por bebida
al supermercado Mercado
PERSON
.
2.5.3 Selección de un tipo de entidad
Podemos identificar el tipo de entidades que queremos buscar.