Resumen de texto con NLTK en Python

Mientras escribo este artículo, 1.907.223.370 sitios web están activos en Internet y se envían 2.722.460 correos electrónicos por segundo. Esta es una cantidad increíblemente grande...

Introducción

Mientras escribo este artículo, 1.907.223.370 sitios web están activos en Internet y se envían 2.722.460 correos electrónicos por segundo. Esta es una cantidad increíblemente grande de datos. Es imposible que un usuario obtenga información a partir de volúmenes de datos tan grandes. Además, una gran parte de estos datos son redundantes o no contienen mucha información útil. La forma más eficiente de obtener acceso a las partes más importantes de los datos, sin tener que filtrar datos redundantes e insignificantes, es resumir los datos de manera que contengan únicamente información no redundante y útil. Los datos pueden estar en cualquier forma, como audio, video, imágenes y texto. En este artículo, veremos cómo podemos usar técnicas de resumen automático de texto para resumir datos de texto.

El resumen de texto es un subdominio de Procesamiento natural del lenguaje (NLP) que se ocupa de extraer resúmenes de grandes fragmentos de texto. Hay dos tipos principales de técnicas utilizadas para resumir textos: técnicas basadas en PNL y técnicas basadas en aprendizaje profundo. En este artículo, veremos una técnica simple basada en NLP para resumir texto. No utilizaremos ninguna biblioteca de aprendizaje automático en este artículo. Más bien, simplemente usaremos Biblioteca NLTK de Python para resumir los artículos de Wikipedia.

Pasos de resumen de texto

Explicaré los pasos involucrados en el resumen de texto utilizando técnicas de PNL con la ayuda de un ejemplo.

El siguiente es un párrafo de uno de los famosos discursos de Denzel Washington en la 48.ª edición de los NAACP Image Awards:

Entonces, sigue trabajando. Sigue esforzándote. No rendirse nunca. Cáete siete veces, levántate ocho. La facilidad es una amenaza mayor para el progreso que las dificultades. La facilidad es una amenaza mayor para el progreso que las dificultades. Así que sigue moviéndote, sigue creciendo, sigue aprendiendo. Nos vemos en el trabajo.

Podemos ver en el párrafo anterior que básicamente está motivando a otros a trabajar duro y nunca darse por vencidos. Para resumir el párrafo anterior utilizando técnicas basadas en PNL, debemos seguir una serie de pasos, que se describirán en las siguientes secciones.

Convertir párrafos en oraciones

Primero necesitamos convertir todo el párrafo en oraciones. La forma más común de convertir párrafos en oraciones es dividir el párrafo cada vez que se encuentre un punto. Entonces, si dividimos el párrafo en discusión en oraciones, obtenemos las siguientes oraciones:

  1. Así que sigue trabajando
  2. Sigue esforzándote
  3. Nunca te rindas
  4. Caerse siete veces, levantarse ocho
  5. La facilidad es una mayor amenaza para el progreso que las dificultades
  6. La facilidad es una mayor amenaza para el progreso que las dificultades
  7. Así que sigue moviéndote, sigue creciendo, sigue aprendiendo
  8. Nos vemos en el trabajo

Preprocesamiento de texto {#preprocesamiento de texto}

Después de convertir el párrafo en oraciones, debemos eliminar todos los caracteres especiales, detener las palabras y los números de todas las oraciones. Después del preprocesamiento, obtenemos las siguientes oraciones:

  1. seguir trabajando
  2. sigue esforzándote
  3. nunca dar
  4. cae siete veces consigue ocho
  5. aliviar mayores dificultades de progreso de amenazas
  6. aliviar mayores dificultades de progreso de amenazas
  7. sigue moviéndote sigue creciendo sigue aprendiendo
  8. ver trabajo

Tokenización de las oraciones {#tokenización de las oraciones}

Necesitamos tokenizar todas las oraciones para obtener todas las palabras que existen en las oraciones. Después de tokenizar las oraciones, obtenemos una lista de las siguientes palabras:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
['keep',
 'working',
 'keep',
 'striving',
 'never',
 'give',
 'fall',
 'seven',
 'time',
 'get',
 'eight',
 'ease',
 'greater',
 'threat',
 'progress',
 'hardship',
 'ease',
 'greater',
 'threat',
 'progress',
 'hardship',
 'keep',
 'moving',
 'keep',
 'growing',
 'keep',
 'learning',
 'see',
 'work']

Buscar frecuencia ponderada de ocurrencia

A continuación, debemos encontrar la frecuencia ponderada de aparición de todas las palabras. Podemos encontrar la frecuencia ponderada de cada palabra dividiendo su frecuencia por la frecuencia de la palabra que aparece más. La siguiente tabla contiene las frecuencias ponderadas para cada palabra:

Palabra Frecuencia Frecuencia ponderada


facilidad 2 0.40 ocho 1 0.20 caída 1 0.20 obtener 1 0.20 dar 1 0.20 mayor 2 0.40 creciendo 1 0.20 dificultad 2 0.40 mantener 5 1.00 aprendizaje 1 0.20 moviendo 1 0.20 nunca 1 0.20 progreso 2 0.40 ver 1 0.20 siete 1 0.20 esforzándose 1 0.20 amenaza 2 0.40 tiempo 1 0.20 trabajo 1 0.20 trabajando 1 0.20

Dado que la palabra "mantener" tiene la frecuencia más alta de 5, la frecuencia ponderada de todas las palabras se ha calculado dividiendo su número de apariciones por 5.

Reemplazar palabras por frecuencia ponderada en oraciones originales {#reemplazar palabras por frecuencia ponderada en oraciones originales}

El paso final es reemplazar la frecuencia ponderada en lugar de las palabras correspondientes en oraciones originales y encontrar su suma. Es importante mencionar que la frecuencia ponderada de las palabras eliminadas durante el preprocesamiento (palabras vacías, puntuación, dígitos, etc.) será cero y, por lo tanto, no es necesario agregarlas, como se menciona a continuación:

Suma de oraciones de frecuencias ponderadas


Entonces, sigue trabajando 1 + 0.20 = 1.20 Sigue esforzándote 1 + 0,20 = 1,20 Nunca te rindas 0,20 + 0,20 = 0,40 Caerse siete veces, levantarse ocho 0,20 + 0,20 + 0,20 + 0,20 + 0,20 = 1,0 La facilidad es una amenaza mayor para el progreso que las dificultades 0,40 + 0,40 + 0,40 + 0,40 + 0,40 = 2,0 La facilidad es una amenaza mayor para el progreso que las dificultades 0,40 + 0,40 + 0,40 + 0,40 + 0,40 = 2,0 Entonces, sigue moviéndote, sigue creciendo, sigue aprendiendo 1 + 0.20 + 1 + 0.20 + 1 + 0.20 = 3.60 Nos vemos en el trabajo 0,20 + 0,20 = 0,40

Ordenar oraciones en orden descendente de suma

El paso final es ordenar las oraciones en orden inverso a su suma. Las oraciones con mayor frecuencia resumen el texto. Por ejemplo, mire la oración con la suma más alta de frecuencias ponderadas:

Entonces, sigue moviéndote, sigue creciendo, sigue aprendiendo

Puedes juzgar fácilmente de qué se trata el párrafo. De manera similar, puede agregar la oración con la segunda suma más alta de frecuencias ponderadas para tener un resumen más informativo. Echa un vistazo a las siguientes oraciones:

Entonces, sigue moviéndote, sigue creciendo, sigue aprendiendo. La facilidad es una amenaza mayor para el progreso que las dificultades.

Estas dos oraciones dan un resumen bastante bueno de lo que se dijo en el párrafo.

Resumen de artículos de Wikipedia

Ahora sabemos cómo funciona el proceso de resumen de texto utilizando una técnica de PNL muy simple. En esta sección, usaremos la biblioteca NLTK de Python para resumir un artículo de Wikipedia.

Obtención de artículos de Wikipedia {#obtención de artículos de wikipedia}

Antes de que podamos resumir los artículos de Wikipedia, debemos obtenerlos de la web. Para ello utilizaremos un par de bibliotecas. La primera biblioteca que necesitamos descargar es hermosa sopa que es una utilidad de Python muy útil para el web scraping. Ejecute el siguiente comando en el símbolo del sistema para descargar la utilidad Beautiful Soup.

1
$ pip install beautifulsoup4

Otra biblioteca importante que necesitamos para analizar XML y HTML es la biblioteca lxml. Ejecute el siguiente comando en el símbolo del sistema para descargar lxml:

1
$ pip install lxml

Ahora permite que un poco de código de Python extraiga datos de la web. El artículo que vamos a raspar es el artículo de Wikipedia sobre Inteligencia artificial. Ejecute el siguiente script:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import bs4 as bs
import urllib.request
import re

scraped_data = urllib.request.urlopen('https://en.wikipedia.org/wiki/Artificial_intelligence')
article = scraped_data.read()

parsed_article = bs.BeautifulSoup(article,'lxml')

paragraphs = parsed_article.find_all('p')

article_text = ""

for p in paragraphs:
    article_text += p.text

En el script anterior, primero importamos las bibliotecas importantes necesarias para extraer los datos de la web. Luego usamos la función urlopen de la utilidad urllib.request para raspar los datos. A continuación, debemos llamar a la función read en el objeto devuelto por la función urlopen para leer los datos. Para analizar los datos, usamos el objeto BeautifulSoup y le pasamos el objeto de datos extraídos, es decir, article y el analizador lxml.

En los artículos de Wikipedia, todo el texto del artículo se incluye dentro de las etiquetas <p>. Para recuperar el texto, debemos llamar a la función find_all en el objeto devuelto por BeautifulSoup. El nombre de la etiqueta se pasa como parámetro a la función. La función find_all devuelve todos los párrafos del artículo en forma de lista. Todos los párrafos se han combinado para recrear el artículo.

Una vez que se raspa el artículo, debemos hacer un preprocesamiento.

Preprocesamiento

El primer paso de preprocesamiento es eliminar las referencias del artículo. Wikipedia, las referencias están entre corchetes. La siguiente secuencia de comandos elimina los corchetes y reemplaza los múltiples espacios resultantes por un solo espacio. Echa un vistazo al guión a continuación:

1
2
3
# Removing Square Brackets and Extra Spaces
article_text = re.sub(r'\[[0-9]*\]', ' ', article_text)
article_text = re.sub(r'\s+', ' ', article_text)

El objeto article_text contiene texto sin corchetes. Sin embargo, no queremos eliminar nada más del artículo ya que este es el artículo original. No eliminaremos otros números, signos de puntuación y caracteres especiales de este texto, ya que usaremos este texto para crear resúmenes y las frecuencias de palabras ponderadas se reemplazarán en este artículo.

Para limpiar el texto y calcular las frecuencias ponderadas, crearemos otro objeto. Echa un vistazo al siguiente script:

1
2
3
# Removing special characters and digits
formatted_article_text = re.sub('[^a-zA-Z]', ' ', article_text )
formatted_article_text = re.sub(r'\s+', ' ', formatted_article_text)

Ahora tenemos dos objetos article_text, que contiene el artículo original y formatted_article_text, que contiene el artículo formateado. Usaremos formatted_article_text para crear histogramas de frecuencia ponderada para las palabras y reemplazaremos estas frecuencias ponderadas con las palabras en el objeto article_text.

Conversión de texto en oraciones

En este punto hemos preprocesado los datos. A continuación, necesitamos tokenizar el artículo en oraciones. Usaremos el objeto article_text para convertir el artículo en una oración, ya que contiene puntos. El texto_artículo_formateado no contiene ningún signo de puntuación y, por lo tanto, no se puede convertir en oraciones usando el punto como parámetro.

El siguiente script realiza la tokenización de oraciones:

1
sentence_list = nltk.sent_tokenize(article_text)

Buscar frecuencia ponderada de ocurrencia

Para encontrar la frecuencia de aparición de cada palabra, usamos la variable formatted_article_text. Usamos esta variable para encontrar la frecuencia de ocurrencia ya que no contiene puntuación, dígitos u otros caracteres especiales. Echa un vistazo al siguiente script:

1
2
3
4
5
6
7
8
9
stopwords = nltk.corpus.stopwords.words('english')

word_frequencies = {}
for word in nltk.word_tokenize(formatted_article_text):
    if word not in stopwords:
        if word not in word_frequencies.keys():
            word_frequencies[word] = 1
        else:
            word_frequencies[word] += 1

En el script anterior, primero almacenamos todas las palabras vacías en inglés de la biblioteca nltk en una variable stopwords. A continuación, recorremos todas las oraciones y luego las palabras correspondientes para verificar primero si son palabras vacías. Si no, procedemos a verificar si las palabras existen en el diccionario word_frequency, es decir, word_frequencies, o no. Si la palabra se encuentra por primera vez, se agrega al diccionario como clave y su valor se establece en 1. De lo contrario, si la palabra ya existe en el diccionario, su valor simplemente se actualiza en 1.

Finalmente, para encontrar la frecuencia ponderada, simplemente podemos dividir el número de apariciones de todas las palabras por la frecuencia de la palabra que más aparece, como se muestra a continuación:

1
2
3
4
maximum_frequncy = max(word_frequencies.values())

for word in word_frequencies.keys():
    word_frequencies[word] = (word_frequencies[word]/maximum_frequncy)

Cálculo de puntuaciones de oraciones

Ahora hemos calculado las frecuencias ponderadas para todas las palabras. Ahora es el momento de calcular las puntuaciones de cada oración sumando las frecuencias ponderadas de las palabras que aparecen en esa oración en particular. El siguiente script calcula las puntuaciones de las oraciones:

1
2
3
4
5
6
7
8
9
sentence_scores = {}
for sent in sentence_list:
    for word in nltk.word_tokenize(sent.lower()):
        if word in word_frequencies.keys():
            if len(sent.split(' ')) < 30:
                if sent not in sentence_scores.keys():
                    sentence_scores[sent] = word_frequencies[word]
                else:
                    sentence_scores[sent] += word_frequencies[word]

En el script anterior, primero creamos un diccionario sentence_scores vacío. Las claves de este diccionario serán las propias frases y los valores serán las puntuaciones correspondientes de las frases. A continuación, recorremos cada oración en sentence_list y convertimos la oración en palabras.

Luego verificamos si la palabra existe en el diccionario word_frequencies. Esta comprobación se realiza desde que creamos la lista sentence_list a partir del objeto article_text; por otro lado, las frecuencias de las palabras se calcularon utilizando el objeto formatted_article_text, que no contiene palabras vacías, números, etc.

No queremos oraciones muy largas en el resumen, por lo tanto, calculamos el puntaje solo para oraciones con menos de 30 palabras (aunque puede modificar este parámetro para su propio caso de uso). A continuación, comprobamos si la frase existe en el diccionario sentence_scores o no. Si la oración no existe, la agregamos al diccionario sentence_scores como clave y le asignamos la frecuencia ponderada de la primera palabra de la oración, como su valor. Por el contrario, si la oración existe en el diccionario, simplemente sumamos la frecuencia ponderada de la palabra al valor existente.

Obtener el resumen

Ahora tenemos el diccionario sentence_scores que contiene frases con su puntuación correspondiente. Para resumir el artículo, podemos tomar las N oraciones principales con las puntuaciones más altas. El siguiente script recupera las 7 oraciones principales y las imprime en la pantalla.

1
2
3
4
5
import heapq
summary_sentences = heapq.nlargest(7, sentence_scores, key=sentence_scores.get)

summary = ' '.join(summary_sentences)
print(summary)

En el script anterior, usamos la biblioteca heapq y llamamos a su función nlargest para recuperar las 7 oraciones principales con las puntuaciones más altas.

El resumen de salida se ve así:

La inteligencia artificial (IA), a veces llamada inteligencia artificial, es la inteligencia demostrada por las máquinas, en contraste con la inteligencia natural que muestran los humanos y otros animales. En la IA se utilizan muchas herramientas, incluidas versiones de búsqueda y optimización matemática, redes neuronales artificiales y métodos basados ​​en estadísticas, probabilidad y economía. Los problemas tradicionales (u objetivos) de la investigación de la IA incluyen el razonamiento, la representación del conocimiento, la planificación, el aprendizaje, el procesamiento del lenguaje natural, la percepción y la capacidad de mover y manipular objetos. Cuando se hizo posible el acceso a las computadoras digitales a mediados de la década de 1950, la investigación de la IA comenzó a explorar la posibilidad de que la inteligencia humana pudiera reducirse a la manipulación de símbolos. Una propuesta para lidiar con esto es garantizar que la primera IA generalmente inteligente sea 'Friendly AI', y luego podrá controlar las IA desarrolladas posteriormente. Hoy en día, la gran mayoría de los investigadores actuales de IA trabajan en aplicaciones manejables de "IA estrecha" (como el diagnóstico médico o la navegación de automóviles). El aprendizaje automático, un concepto fundamental de la investigación de IA desde el inicio del campo, es el estudio de algoritmos informáticos que mejoran automáticamente a través de la experiencia.

Recuerde, dado que los artículos de Wikipedia se actualizan con frecuencia, es posible que obtenga resultados diferentes según el tiempo de ejecución del script.

Yendo más lejos: proyecto de extremo a extremo portátil

¿Tu naturaleza inquisitiva te hace querer ir más allá? Recomendamos consultar nuestro Proyecto guiado: ["Subtítulos de imágenes con CNN y Transformers con Keras"](https://wikihtp.com/courses/image-captioning-with-cnns-and -transformadores-con-keras/#cta){target="_blank"}.

En este proyecto guiado, aprenderá a crear un modelo de subtítulos de imágenes, que acepta una imagen como entrada y produce un subtítulo de texto como salida.

Aprenderás a:

  • Preprocesar texto
  • Vectorizar la entrada de texto fácilmente
  • Trabaje con la API tf.data y cree conjuntos de datos de alto rendimiento
  • Cree Transformers desde cero con TensorFlow/Keras y KerasNLP: la adición horizontal oficial a Keras para crear modelos NLP de última generación
  • Cree arquitecturas híbridas donde la salida de una red se codifica para otra

¿Cómo enmarcamos los subtítulos de las imágenes? La mayoría lo considera un ejemplo de aprendizaje profundo generativo, porque estamos enseñando a una red a generar descripciones. Sin embargo, me gusta verlo como una instancia de traducción automática neuronal: estamos traduciendo las características visuales de una imagen en palabras. A través de la traducción, estamos generando una nueva representación de esa imagen, en lugar de simplemente generar un nuevo significado. Verlo como traducción, y solo por generación de extensión, enfoca la tarea bajo una luz diferente y la hace un poco más intuitiva.

Enmarcar el problema como uno de traducción hace que sea más fácil averiguar qué arquitectura querremos usar. Los transformadores solo de codificador son excelentes para comprender el texto (análisis de opinión, clasificación, etc.) porque los codificadores codifican representaciones significativas. Los modelos de solo decodificador son excelentes para la generación (como GPT-3), ya que los decodificadores pueden inferir representaciones significativas en otra secuencia con el mismo significado. La traducción generalmente se realiza mediante una arquitectura de codificador-decodificador, donde los codificadores codifican una representación significativa de una oración (o imagen, en nuestro caso) y los decodificadores aprenden a convertir esta secuencia en otra representación significativa que es más interpretable para nosotros (como una oración).

Conclusión

Este artículo explica el proceso de resumen de texto con la ayuda de la biblioteca Python NLTK. El proceso de extracción de artículos utilizando la biblioteca BeautifulSoap también se ha cubierto brevemente en el artículo. Le recomendaré que raspe cualquier otro artículo de Wikipedia y vea si puede obtener un buen resumen del artículo o no.