Breaking

Post Top Ad

Your Ad Spot

viernes, 14 de junio de 2019

Python para PNL: Modelado de temas

Este es el sexto artículo de mi serie de artículos sobre Python para PNL. En mi artículo anterior , hablé sobre cómo realizar un análisis de sentimiento de los datos de Twitter utilizando la biblioteca Scikit-Learn de Python. En este artículo, estudiaremos el modelado de temas, que es otra aplicación muy importante de la PNL. Veremos cómo hacer el modelado de temas con Python.

¿Qué es el modelado de temas?

El modelado de temas es una técnica no supervisada que intenta analizar grandes volúmenes de datos de texto agrupando los documentos en grupos. En el caso del modelado de temas, los datos de texto no tienen ninguna etiqueta adjunta. Más bien, el modelado de temas intenta agrupar los documentos en grupos en función de características similares.
Un ejemplo típico de modelado de temas es agrupar una gran cantidad de artículos periodísticos que pertenecen a la misma categoría. En otras palabras, agrupar documentos que tienen el mismo tema. Es importante mencionar aquí que es extremadamente difícil evaluar el desempeño del modelado de temas ya que no hay respuestas correctas. Depende del usuario encontrar características similares entre los documentos de un grupo y asignarle una etiqueta o tema apropiado.
Dos enfoques se utilizan principalmente para el modelado de temas: asignación de direccionamiento latente y factorización de matriz no negativa . En las siguientes secciones, revisaremos brevemente estos dos enfoques y veremos cómo se pueden aplicar al modelado de temas en Python.

Asignación de Dirichlet Latente (LDA)

La LDA se basa en dos supuestos generales:
  • Los documentos que tienen palabras similares generalmente tienen el mismo tema.
  • Los documentos que tienen grupos de palabras que suelen aparecer juntos suelen tener el mismo tema.
Estas suposiciones tienen sentido porque los documentos que tienen el mismo tema, por ejemplo, los temas de negocios tendrán palabras como "economía", "ganancia", "mercado de valores", "pérdida", etc. La segunda suposición establece que si estos las palabras suelen aparecer juntas en varios documentos, esos documentos pueden pertenecer a la misma categoría.
Matemáticamente, los dos supuestos anteriores se pueden representar como:
  • Los documentos son distribuciones de probabilidad sobre temas latentes.
  • Los temas son distribuciones de probabilidad sobre palabras.

LDA para modelado de temas en Python

En esta sección veremos cómo se puede usar Python para implementar LDA para el modelado de temas. El conjunto de datos se puede descargar desde el Kaggle .
El conjunto de datos contiene opiniones de usuarios para diferentes productos en la categoría de alimentos. Utilizaremos LDA para agrupar las opiniones de los usuarios en 5 categorías.
El primer paso, como siempre, es importar el conjunto de datos junto con las bibliotecas requeridas. Ejecute el siguiente script para hacerlo:
import pandas as pd  
import numpy as np

reviews_datasets = pd.read_csv(r'E:\Datasets\Reviews.csv')  
reviews_datasets = reviews_datasets.head(20000)  
reviews_datasets.dropna()  
En el script anterior, importamos el conjunto de datos utilizando el read_csvmétodo de la biblioteca de pandas . El conjunto de datos original contiene alrededor de 500k revisiones. Sin embargo, debido a las limitaciones de memoria, realizaré LDA solo en los primeros 20k registros. En el script anterior, filtramos las primeras 20k filas y luego eliminamos los valores nulos del conjunto de datos.
A continuación, imprimimos las primeras cinco filas del conjunto de datos utilizando la head()función para inspeccionar nuestros datos:
reviews_datasets.head()  
En la salida, verás los siguientes datos:
Aplicaremos LDA en la columna "Texto" ya que contiene las revisiones, el resto de las columnas se ignorarán.
Veamos la revisión número 350.
reviews_datasets['Text'][350]  
En la salida, verá el siguiente texto de revisión:
'These chocolate covered espresso beans are wonderful!  The chocolate is very dark and rich and the "bean" inside is a very delightful blend of flavors with just enough caffine to really give it a zing.'  
Antes de poder aplicar LDA, debemos crear un vocabulario de todas las palabras en nuestros datos. Recuerde que del artículo anterior, podríamos hacerlo con la ayuda de un vectorizador de conteo. Mira el siguiente script:
from sklearn.feature_extraction.text import CountVectorizer

count_vect = CountVectorizer(max_df=0.8, min_df=2, stop_words='english')  
doc_term_matrix = count_vect.fit_transform(reviews_datasets['Text'].values.astype('U'))  
En el script anterior, usamos la CountVectorizerclase del sklearn.feature_extraction.textmódulo para crear una matriz de términos de documento. Especificamos incluir solo aquellas palabras que aparecen en menos del 80% del documento y aparecen en al menos 2 documentos. También eliminamos todas las palabras vacías ya que realmente no contribuyen al modelado de temas.
Ahora veamos nuestra matriz de términos de documentos:
doc_term_matrix  
Salida:
<20000x14546 sparse matrix of type '<class 'numpy.int64'>'  
with 594703 stored elements in Compressed Sparse Row format>  
Cada uno de los 20k documentos se representa como 14546 vector dimensional, lo que significa que nuestro vocabulario tiene 14546 palabras.
A continuación, usaremos LDA para crear temas junto con la distribución de probabilidad para cada palabra en nuestro vocabulario para cada tema. Ejecuta el siguiente script:
from sklearn.decomposition import LatentDirichletAllocation

LDA = LatentDirichletAllocation(n_components=5, random_state=42)  
LDA.fit(doc_term_matrix)  
En el script anterior, usamos la LatentDirichletAllocationclase de la sklearn.decompositionbiblioteca para realizar LDA en nuestra matriz de términos de documentos. El parámetro n_componentsespecifica la cantidad de categorías o temas en los que queremos que se divida nuestro texto. El parámetro random_state(también conocido como la semilla ) se establece en 42 para que obtenga los resultados similares a los míos.
Vamos a buscar palabras de nuestro vocabulario al azar. Sabemos que el vectorizador de conteo contiene todas las palabras en nuestro vocabulario. Podemos usar el get_feature_names()método y pasarle el ID de la palabra que queremos obtener.
El siguiente script obtiene aleatoriamente 10 palabras de nuestro vocabulario:
import random

for i in range(10):  
    random_id = random.randint(0,len(count_vect.get_feature_names()))
    print(count_vect.get_feature_names()[random_id])
La salida se ve así:
bribe  
tarragon  
qualifies  
prepare  
hangs  
noted  
churning  
breeds  
zon  
chunkier  
Encontremos 10 palabras con la probabilidad más alta para el primer tema. Para obtener el primer tema, puede usar el components_atributo y pasar un índice de 0 como el valor:
first_topic = LDA.components_[0]  
El primer tema contiene las probabilidades de 14546 palabras para el tema 1. Para ordenar los índices según los valores de probabilidad, podemos usar la argsort()función. Una vez ordenadas, las 10 palabras con las probabilidades más altas ahora pertenecerán a los últimos 10 índices de la matriz. La siguiente secuencia de comandos devuelve los índices de las 10 palabras con las probabilidades más altas:
top_topic_words = first_topic.argsort()[-10:]  
Salida:
array([14106,  5892,  7088,  4290, 12596,  5771,  5187, 12888,  7498,  
       12921], dtype=int64)
Estos índices se pueden usar para recuperar el valor de las palabras del count_vectobjeto, que se puede hacer de la siguiente manera:
for i in top_topic_words:  
    print(count_vect.get_feature_names()[i])
En la salida, deberías ver las siguientes palabras:
water  
great  
just  
drink  
sugar  
good  
flavor  
taste  
like  
tea  
Las palabras muestran que el primer tema podría ser sobre el té.
Imprimamos las 10 palabras con las probabilidades más altas para los cinco temas:
for i,topic in enumerate(LDA.components_):  
    print(f'Top 10 words for topic #{i}:')
    print([count_vect.get_feature_names()[i] for i in topic.argsort()[-10:]])
    print('\n')
La salida se ve así:
Top 10 words for topic #0:  
['water', 'great', 'just', 'drink', 'sugar', 'good', 'flavor', 'taste', 'like', 'tea']


Top 10 words for topic #1:  
['br', 'chips', 'love', 'flavor', 'chocolate', 'just', 'great', 'taste', 'good', 'like']


Top 10 words for topic #2:  
['just', 'drink', 'orange', 'sugar', 'soda', 'water', 'like', 'juice', 'product', 'br']


Top 10 words for topic #3:  
['gluten', 'eat', 'free', 'product', 'like', 'dogs', 'treats', 'dog', 'br', 'food']


Top 10 words for topic #4:  
['cups', 'price', 'great', 'like', 'amazon', 'good', 'br', 'product', 'cup', 'coffee']
La salida muestra que el segundo tema puede contener comentarios sobre chocolates, etc. De manera similar, el tercer tema podría contener comentarios sobre sodas o jugos. Puedes ver que hay algunas palabras comunes en todas las categorías. Esto se debe a que hay pocas palabras que se utilizan para casi todos los temas. Por ejemplo, "bueno", "grande", "me gusta", etc.
Como paso final, agregaremos una columna al marco de datos original que almacenará el tema para el texto. Para hacerlo, podemos usar el LDA.transform()método y pasarlo a nuestra matriz de términos de documentos. Este método asignará la probabilidad de todos los temas a cada documento. Mira el siguiente código:
topic_values = LDA.transform(doc_term_matrix)  
topic_values.shape  
En la salida, verá (20000, 5) lo que significa que cada uno de los documentos tiene 5 columnas, donde cada columna corresponde al valor de probabilidad de un tema en particular. Para encontrar el índice de temas con el valor máximo, podemos llamar al argmax()método y pasar 1 como el valor para el parámetro del eje.
La siguiente secuencia de comandos agrega una nueva columna para el tema en el marco de datos y asigna el valor del tema a cada fila de la columna:
reviews_datasets['Topic'] = topic_values.argmax(axis=1)  
Veamos ahora cómo se ve el conjunto de datos:
reviews_datasets.head()  
Salida:
Puede ver una nueva columna para el tema en la salida.

Factorización de matriz no negativa (FNM)

En la sección anterior, vimos cómo se puede usar LDA para el modelado de temas. En esta sección, veremos cómo se puede usar la factorización de matriz no negativa para el modelado de temas.
La factorización matricial no negativa también es una técnica de aprendizaje supervisado que realiza el agrupamiento así como la reducción de la dimensionalidad. Se puede usar en combinación con el esquema TF-IDF para realizar el modelado de temas. En esta sección, veremos cómo se puede usar Python para realizar la factorización de matriz no negativa para el modelado de temas.

NMF para modelado de temas en Python

En esta sección, realizaremos el modelado de temas en el mismo conjunto de datos que usamos en la última sección. Verás que los pasos también son bastante similares.
Comenzamos importando el conjunto de datos:
import pandas as pd  
import numpy as np

reviews_datasets = pd.read_csv(r'E:\Datasets\Reviews.csv')  
reviews_datasets = reviews_datasets.head(20000)  
reviews_datasets.dropna()  
En la sección anterior usamos el vectorizador de conteo, pero en esta sección usaremos el vectorizador TFIDF ya que NMF funciona con TFIDF. Crearemos una matriz de términos de documento con TFIDF. Mira el siguiente script:
from sklearn.feature_extraction.text import TfidfVectorizer

tfidf_vect = TfidfVectorizer(max_df=0.8, min_df=2, stop_words='english')  
doc_term_matrix = tfidf_vect.fit_transform(reviews_datasets['Text'].values.astype('U'))  
Una vez que se genera la matriz de términos del documento, podemos crear una matriz de probabilidad que contenga probabilidades de todas las palabras en el vocabulario para todos los temas. Para ello, podemos utilizar la NMFclase del sklearn.decompositionmódulo. Mira el siguiente script:
from sklearn.decomposition import NMF

nmf = NMF(n_components=5, random_state=42)  
nmf.fit(doc_term_matrix )  
Como hicimos en la sección anterior, obtengamos al azar 10 palabras de nuestro vocabulario:
import random

for i in range(10):  
    random_id = random.randint(0,len(tfidf_vect.get_feature_names()))
    print(tfidf_vect.get_feature_names()[random_id])
En la salida, verás las siguientes palabras:
safest  
pith  
ache  
formula  
fussy  
frontier  
burps  
speaker  
responsibility  
dive  
A continuación, recuperaremos el vector de probabilidad de palabras para el primer tema y recuperaremos los índices de las diez palabras con las probabilidades más altas:
first_topic = nmf.components_[0]  
top_topic_words = first_topic.argsort()[-10:]  
Estos índices ahora se pueden pasar al tfidf_vectobjeto para recuperar las palabras reales. Mira el siguiente script:
for i in top_topic_words:  
    print(tfidf_vect.get_feature_names()[i])
La salida se ve así:
really  
chocolate  
love  
flavor  
just  
product  
taste  
great  
good  
like  
Las palabras para el tema 1 muestran que el tema 1 podría contener revisiones para los chocolates. Ahora vamos a imprimir las diez palabras con las probabilidades más altas para cada uno de los temas:
for i,topic in enumerate(nmf.components_):  
    print(f'Top 10 words for topic #{i}:')
    print([tfidf_vect.get_feature_names()[i] for i in topic.argsort()[-10:]])
    print('\n')
La salida de la secuencia de comandos anterior se ve así:
Top 10 words for topic #0:  
['really', 'chocolate', 'love', 'flavor', 'just', 'product', 'taste', 'great', 'good', 'like']


Top 10 words for topic #1:  
['like', 'keurig', 'roast', 'flavor', 'blend', 'bold', 'strong', 'cups', 'cup', 'coffee']


Top 10 words for topic #2:  
['com', 'amazon', 'orange', 'switch', 'water', 'drink', 'soda', 'sugar', 'juice', 'br']


Top 10 words for topic #3:  
['bags', 'flavor', 'drink', 'iced', 'earl', 'loose', 'grey', 'teas', 'green', 'tea']


Top 10 words for topic #4:  
['old', 'love', 'cat', 'eat', 'treat', 'loves', 'dogs', 'food', 'treats', 'dog']
Las palabras para el tema 1 muestran que este tema contiene comentarios sobre el café. Del mismo modo, las palabras para el tema 2 muestran que contiene reseñas sobre sodas y jugos. El tema 3 nuevamente contiene reseñas sobre bebidas. Finalmente, el tema 4 puede contener comentarios sobre alimentos de animales, ya que contiene palabras como "gato", "perro", "tratar", etc.
La siguiente secuencia de comandos agrega los temas al conjunto de datos y muestra las primeras cinco filas:
topic_values = nmf.transform(doc_term_matrix)  
reviews_datasets['Topic'] = topic_values.argmax(axis=1)  
reviews_datasets.head()  
La salida del código anterior se ve así:
Como puede ver, se ha asignado un tema a cada revisión, que se generó utilizando el método NMF.

Conclusión

El modelado de temas es una de las áreas de investigación más buscadas en la PNL. Se utiliza para agrupar grandes volúmenes de datos de texto sin etiquetar. En este artículo, se han explicado dos enfoques para el modelado de temas. En este artículo vimos cómo la asignación de direccionamiento latente y la factorización de matriz no negativa se pueden usar para el modelado de temas con la ayuda de las bibliotecas de Python.

No hay comentarios.:

Publicar un comentario

Dejanos tu comentario para seguir mejorando!

Post Top Ad

Your Ad Spot

Páginas