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

    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.

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *