Python para PNL: Creación de un modelo de bolsa de palabras desde cero

P

Este es el decimotercer artículo de mi serie de artículos sobre Python para PNL. En el artículo anterior, vimos cómo crear un chatbot simple basado en reglas que usa similitud de coseno Entre los TF-IDF vectores de las palabras en el corpus y la entrada del usuario, para generar una respuesta. El modelo TF-IDF se utilizó básicamente para convertir palabras en números.

En este artículo, estudiaremos otro modelo muy útil que convierte texto en números, es decir, la Bolsa de palabras (BOW).

Dado que la mayoría de los algoritmos estadísticos, por ejemplo, el Machine Learning y las técnicas de aprendizaje profundo, funcionan con datos numéricos, por lo que tenemos que convertir el texto en números. Existen varios enfoques a este respecto. Sin embargo, los más famosos son Bag of Words, TF-IDF y word2vec. Aunque existen varias bibliotecas, como Scikit-Learn y NLTK, que pueden implementar estas técnicas en una línea de código, es importante comprender el principio de funcionamiento detrás de estas técnicas de incrustación de palabras. La mejor forma de hacerlo es implementar estas técnicas desde cero en Python y esto es lo que vamos a hacer hoy.

En este artículo, veremos cómo implementar el enfoque Bag of Words desde cero en Python. En el próximo artículo, veremos cómo implementar el enfoque TF-IDF desde cero en Python.

Antes de codificar, veamos primero la teoría detrás del enfoque de la bolsa de palabras.

La teoría detrás del enfoque de la bolsa de palabras

Para entender el enfoque de la bolsa de palabras, comencemos primero con la ayuda de un ejemplo.

Supongamos que tenemos un corpus con tres oraciones:

  • “Me gusta jugar al fútbol”
  • “¿Saliste a jugar al tenis?”
  • “John y yo jugamos al tenis”

Ahora bien, si tenemos que realizar una clasificación de texto, o cualquier otra tarea, sobre los datos anteriores utilizando técnicas estadísticas, no podemos hacerlo ya que las técnicas estadísticas solo funcionan con números. Por lo tanto, necesitamos convertir estas oraciones en números.

Paso 1: Tokeniza las oraciones

El primer paso en este sentido es convertir las oraciones de nuestro corpus en tokens o palabras individuales. Mire la tabla a continuación:

Oración 1 Oración 2 Oración 3

yoHizoJohn
me gustaUdsy
aVamosyo
jugarfuera dejugar
fútbol americanoatenis
jugar
tenis

Paso 2: crea un diccionario de frecuencia de palabras

El siguiente paso es crear un diccionario que contenga todas las palabras de nuestro corpus como claves y la frecuencia de aparición de las palabras como valores. En otras palabras, necesitamos crear un histograma de las palabras en nuestro corpus. Mira la siguiente tabla:

Frecuencia de palabras

yo2
me gusta1
a2
jugar3
fútbol americano1
Hizo1
Uds1
Vamos1
fuera de1
tenis2
John1
y1

En la tabla anterior, puede ver cada palabra en nuestro corpus junto con su frecuencia de aparición. Por ejemplo, puede ver que dado que la palabra play ocurre tres veces en el corpus (una vez en cada oración) su frecuencia es 3.

En nuestro corpus, solo teníamos tres oraciones, por lo que nos es fácil crear un diccionario que contenga todas las palabras. En los escenarios del mundo real, habrá millones de palabras en el diccionario. Algunas de las palabras tendrán una frecuencia muy pequeña. Las palabras con una frecuencia muy pequeña no son muy útiles, por lo que se eliminan. Una forma de eliminar las palabras con menos frecuencia es ordenar el diccionario de frecuencia de palabras en orden decreciente de frecuencia y luego filtrar las palabras que tienen una frecuencia superior a un cierto umbral.

Ordenemos nuestro diccionario de frecuencia de palabras:

Frecuencia de palabras

jugar3
tenis2
a2
yo2
fútbol americano1
Hizo1
Uds1
Vamos1
fuera de1
me gusta1
John1
y1

Paso 3: Creación del modelo de bolsa de palabras

Para crear el modelo de bolsa de palabras, necesitamos crear una matriz donde las columnas corresponden a las palabras más frecuentes en nuestro diccionario donde las filas corresponden al documento u oraciones.

Supongamos que filtramos las 8 palabras más frecuentes de nuestro diccionario. Entonces, la matriz de frecuencia del documento se verá así:

Jugar al tenis al fútbol ¿Fuiste?

Oración 110111000
Oración 211100111
Oración 311010000

Es importante comprender cómo se crea la matriz anterior. En la matriz anterior, la primera fila corresponde a la primera oración. En el primero, la palabra “jugar” aparece una vez, por lo que agregamos 1 en la primera columna. La palabra en la segunda columna es “Tenis”, no aparece en la primera oración, por lo tanto, agregamos un 0 en la segunda columna para la oración 1. De manera similar, en la segunda oración, las palabras “Jugar” y “Tenis “ocurre una vez, por lo tanto, agregamos 1 en las dos primeras columnas. Sin embargo, en la quinta columna, agregamos un 0, ya que la palabra “Fútbol” no aparece en la segunda oración. De esta manera, todas las celdas de la matriz anterior se rellenan con 0 o 1, dependiendo de la aparición de la palabra. La matriz final corresponde al modelo de la bolsa de palabras.

En cada fila, puede ver la representación numérica de la oración correspondiente. Por ejemplo, la primera fila muestra la representación numérica de la oración 1. Esta representación numérica ahora se puede utilizar como entrada para los modelos estadísticos.

Basta de teoría, implementemos nuestro propio modelo de bolsa de palabras desde cero.

Modelo de Bolsa de Palabras en Python

Lo primero que necesitamos para crear nuestro modelo Bag of Words es un conjunto de datos. En la sección anterior, creamos manualmente un modelo de bolsa de palabras con tres oraciones. Sin embargo, los conjuntos de datos del mundo real son enormes con millones de palabras. La mejor forma de encontrar un corpus aleatorio es Wikipedia.

En el primer paso, rasparemos el artículo de Wikipedia sobre Procesamiento natural del lenguaje. Pero primero, importemos las bibliotecas necesarias:

import nltk  
import numpy as np  
import random  
import string

import bs4 as bs  
import urllib.request  
import re  

Como hicimos en el artículo anterior, usaremos el Beautifulsoup4 biblioteca para analizar los datos de Wikipedia. Además, la biblioteca de expresiones regulares de Python, re, se utilizará para algunas tareas de preprocesamiento en el texto.

A continuación, necesitamos raspar el artículo de Wikipedia sobre el procesamiento del lenguaje natural.

raw_html = urllib.request.urlopen('https://en.wikipedia.org/wiki/Natural_language_processing')  
raw_html = raw_html.read()

article_html = bs.BeautifulSoup(raw_html, 'lxml')

article_paragraphs = article_html.find_all('p')

article_text=""

for para in article_paragraphs:  
    article_text += para.text

En el script anterior, importamos el HTML sin formato para el artículo de Wikipedia. A partir del HTML sin formato, filtramos el texto dentro del texto del párrafo. Finalmente, creamos un corpus completo concatenando todos los párrafos.

El siguiente paso es dividir el corpus en oraciones individuales. Para hacerlo, usaremos el sent_tokenize función de la biblioteca NLTK.

corpus = nltk.sent_tokenize(article_text)

Nuestro texto contiene signos de puntuación. No queremos que las puntuaciones formen parte de nuestro diccionario de frecuencia de palabras. En el siguiente script, primero convertimos nuestro texto a minúsculas y luego eliminamos la puntuación de nuestro texto. Eliminar la puntuación puede resultar en varios espacios vacíos. Eliminaremos los espacios vacíos del texto usando expresiones regulares.

Mira el siguiente guión:

for i in range(len(corpus )):
    corpus [i] = corpus [i].lower()
    corpus [i] = re.sub(r'W',' ',corpus [i])
    corpus [i] = re.sub(r's+',' ',corpus [i])

En el guión anterior, iteramos a través de cada oración en el corpus, convertimos la oración a minúsculas y luego eliminamos la puntuación y los espacios vacíos del texto.

Averigüemos el número de oraciones en nuestro corpus.

print(len(corpus))

La salida muestra 49.

Imprimamos una oración de nuestro corpus:

print(corpus[30])

Salida:

in the 2010s representation learning and deep neural network style machine learning methods became widespread in natural language processing due in part to a flurry of results showing that such techniques 4 5 can achieve state of the art results in many natural language tasks for example in language modeling 6 parsing 7 8 and many others 

Puede ver que el texto no contiene ningún carácter especial o varios espacios vacíos.

Ahora tenemos nuestro propio corpus. El siguiente paso es tokenizar las oraciones en el corpus y crear un diccionario que contenga palabras y sus frecuencias correspondientes en el corpus. Mira el siguiente guión:

wordfreq = {}
for sentence in corpus:
    tokens = nltk.word_tokenize(sentence)
    for token in tokens:
        if token not in wordfreq.keys():
            wordfreq[token] = 1
        else:
            wordfreq[token] += 1

En el script anterior creamos un diccionario llamado wordfreq. A continuación, iteramos a través de cada oración del corpus. La oración se convierte en palabras. A continuación, iteramos a través de cada palabra de la oración. Si la palabra no existe en el wordfreq diccionario, agregaremos la palabra como clave y estableceremos el valor de la palabra como 1. De lo contrario, si la palabra ya existe en el diccionario, simplemente incrementaremos el número de claves en 1.

Si está ejecutando lo anterior en el Spyder editor como yo, puede ir al explorador de variables a la derecha y hacer clic wordfreq variable. Debería ver un diccionario como este:

Puede ver las palabras en la columna “Clave” y su frecuencia de aparición en la columna “Valor”.

Como dije en la sección de teoría, dependiendo de la tarea en cuestión, no todas las palabras son útiles. En grandes corpora, puedes tener millones de palabras. Podemos filtrar las palabras que aparecen con más frecuencia. Nuestro corpus tiene 535 palabras en total. Filtremos hasta las 200 palabras más frecuentes. Para hacerlo, podemos hacer uso de Python heap biblioteca.

Mira el siguiente guión:

import heapq
most_freq = heapq.nlargest(200, wordfreq, key=wordfreq.get)

Ahora nuestro most_freq La lista contiene 200 palabras que aparecen con mayor frecuencia junto con su frecuencia de aparición.

El último paso es convertir las oraciones de nuestro corpus en su correspondiente representación vectorial. La idea es sencilla, para cada palabra en el most_freq diccionario si la palabra existe en la oración, se agregará un 1 para la palabra, de lo contrario se agregará 0.

sentence_vectors = []
for sentence in corpus:
    sentence_tokens = nltk.word_tokenize(sentence)
    sent_vec = []
    for token in most_freq:
        if token in sentence_tokens:
            sent_vec.append(1)
        else:
            sent_vec.append(0)
    sentence_vectors.append(sent_vec)

En el script de arriba creamos una lista vacía sentence_vectors que almacenará vectores para todas las oraciones en el corpus. Luego, iteramos a través de cada oración en el corpus y creamos una lista vacía sent_vec para las oraciones individuales. Del mismo modo, también tokenizamos la oración. A continuación, iteramos a través de cada palabra en el most_freq lista y verifica si la palabra existe en las fichas de la oración. Si la palabra es parte de la oración, se agrega 1 al vector de oración individual sent_vec, de lo contrario se agrega 0. Finalmente, el vector de oración se agrega a la lista sentence_vectors que contiene vectores para todas las oraciones. Básicamente, esto sentence_vectors es nuestro modelo de bolsa de palabras.

Sin embargo, el modelo de la bolsa de palabras que vimos en la sección de teoría tenía la forma de una matriz. Nuestro modelo tiene la forma de una lista de listas. Podemos convertir nuestro modelo en forma de matriz usando este script:

sentence_vectors = np.asarray(sentence_vectors)

Básicamente, en el siguiente script, convertimos nuestra lista en una matriz numérica bidimensional usando asarray función. Ahora si abre el sentence_vectors variable en el explorador de variables del editor de Spyder, debería ver la siguiente matriz:

Puede ver el modelo de Bolsa de palabras que contiene 0 y 1.

Conclusión

El modelo Bag of Words es uno de los tres enfoques de inserción de palabras más utilizados, siendo TF-IDF y Word2Vec los otros dos.

En este artículo, vimos cómo implementar el enfoque de Bolsa de palabras desde cero en Python. La teoría del enfoque se ha explicado junto con el código práctico para implementar el enfoque. En el próximo artículo, veremos cómo implementar el enfoque TF-IDF desde cero en Python.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad