Análisis exploratorio de textos

Representar visualmente el contenido de un documento de texto es una de las tareas más importantes en el campo de la minería de texto (también llamado análisis exploratorio de texto). Como científico de datos o especialista en PNL, no solo exploramos el contenido de los documentos desde diferentes aspectos y en diferentes niveles de detalle, sino que también resumimos un solo documento, mostramos palabras y temas, detectamos eventos y creamos escenarios.

Sin embargo, existen discrepancias entre los Visualización de datos datos no estructurados (texto) y estructurados. Por ejemplo, muchas visualizaciones de texto no representan el texto directamente, representan una salida de un modelo de lenguaje (recuento de palabras, longitud de caracteres, secuencias de palabras, etc.).

En este artículo, usaremos el conjunto de datos de Womens Clothing E-Commerce Reviews e intentaremos explorar y visualizar tanto como sea posible, usando la biblioteca de gráficos Python de Plotly y la biblioteca de visualización Bokeh. No solo exploraremos datos textuales, sino que también visualizaremos características numéricas y categóricas. 

análisis exploratorio de texto

Después de una breve inspección de los datos, encontramos que hay una serie de preprocesamiento de datos que debemos realizar.

análisis exploratorio de texto análisis exploratorio de texto

Elimina la función "Título".
Elimine las líneas donde faltaba "Revisar texto".
Limpie la columna "Texto de revisión".
Usar TextBlob para calcular la polaridad del sentimiento que está en el rango de [-1,1] donde 1 significa sentimiento positivo y -1 significa sentimiento negativo.
Cree una nueva función durante la duración del examen.
Cree una nueva función para el recuento de palabras del examen.

Para obtener una vista previa de si el puntaje de polaridad de sentimiento está funcionando, seleccionamos al azar 5 reseñas con el puntaje de polaridad de sentimiento más alto (1):

print('5 reseñas aleatorias con la polaridad de sentimiento positivo más alta: \n')
cl = df.loc[df.polaridad == 1, ['Revisar texto']].muestra(5).valores
para c en cl:
imprimir (c [0])
análisis exploratorio de texto análisis exploratorio de texto

Luego seleccione al azar 5 reseñas con la puntuación de polaridad de sentimiento más neutral (cero):

print('5 reseñas aleatorias con la polaridad de sentimiento más neutral (cero):\n')
cl = df.loc[df.polaridad == 0, ['Revisar texto']].muestra(5).valores
para c en cl:
imprimir (c [0])
análisis exploratorio de texto análisis exploratorio de texto

Solo hubo 2 reseñas con la puntuación de polaridad de sentimiento más negativa:

print('2 reseñas con la polaridad más negativa: \n')
cl = df.loc[df.polaridad == -0.97500000000000009, ['Revisar texto']].muestra(2).valores
para c en cl:
imprimir (c [0])
análisis exploratorio de texto análisis exploratorio de texto

Parece funcionar

Visualización univariante

La visualización de una sola variable o univariante es el tipo más simple de visualización que consiste en observaciones sobre una sola característica o atributo. La visualización univariada incluye un histograma, gráficos de barras y gráficos de líneas.

análisis exploratorio de texto análisis exploratorio de texto

La gran mayoría de los puntajes de polaridad de sentimiento están por encima de cero, lo que significa que la mayoría de ellos son bastante positivos.

análisis exploratorio de texto análisis exploratorio de texto

Las notas están alineadas con la puntuación de polaridad, es decir, la mayoría de las notas son bastante altas en 4 o 5 rangos.

Es posible hacer lo mismo con la edad de los revisores, la cantidad de caracteres por reseña y la cantidad de palabras por reseña, pero este no es el corazón de este tutorial.

 

Los n-gramas

Ahora que llegamos a la función que nos interesa, antes de explorar esta función, necesitamos extraer las funciones de N-Gram. Los N-gramas se utilizan para describir la cantidad de palabras utilizadas como puntos de observación, por ejemplo, unigrama significa una sola palabra, bigrama significa una oración de 2 palabras y trigrama significa una oración de 3 palabras. Para hacer esto, usamos la función CountVectorizer de scikit-learn.

Para hacer análisis de unigramas, es muy importante limpiar el texto de palabras vacías.

 definitivamente get_top_n_words(cuerpo, no=Ninguna):
 con = ContarVectorizador(Para las palabras = 'inglés').adaptar(cuerpo)
 bolsa_de_palabras = con.transformar(cuerpo)
 suma_palabras = bolsa_de_palabras.suma(eje=0)
 palabras_freq = [(palabra, suma_palabras[0, idx]) por palabra, idx en con.vocabulario_.elementos()]
 palabras_freq =ordenado(palabras_freq, llave = lambda X: X[1], reverso=Verdadero)
 regreso palabras_freq[:no]
 Palabras comunes = get_top_n_words(d.f.['Texto de revisión'], 20)
 por palabra, frecuencia en Palabras comunes:
 impresión(palabra, frecuencia)
 df2 = p.d..Marco de datos(Palabras comunes, columnas = ['Texto de revisión' , 'contar'])
 df2.agrupar por('Texto de revisión').suma()['contar'].ordenar_valores(ascendente=Falso).trama(
 tipo='bar', yTítulo='Contar', color de linea=negro, título='Las 20 palabras principales en revisión después de eliminar las palabras vacías')
análisis exploratorio de texto análisis exploratorio de texto
Hagamos lo mismo para estudiar los bigramas.
 definitivamente get_top_n_bigrama(cuerpo, no=Ninguna):
 con = ContarVectorizador(rango_ngram=(2, 2), Para las palabras='inglés').adaptar(cuerpo)
 bolsa_de_palabras = con.transformar(cuerpo)
 suma_palabras = bolsa_de_palabras.suma(eje=0)
 palabras_freq = [(palabra, suma_palabras[0, idx]) por palabra, idx en con.vocabulario_.elementos()]
 palabras_freq =ordenado(palabras_freq, llave = lambda X: X[1], reverso=Verdadero)
 regreso palabras_freq[:no]
 Palabras comunes = get_top_n_bigrama(d.f.['Texto de revisión'], 20)
 por palabra, frecuencia en Palabras comunes:
 impresión(palabra, frecuencia)
 df4 = p.d..Marco de datos(Palabras comunes, columnas = ['Texto de revisión' , 'contar'])
 df4.agrupar por('Texto de revisión').suma()['contar'].ordenar_valores(ascendente=Falso).trama(
 tipo='bar', yTítulo='Contar', color de linea=negro, título="Los 20 mejores bigramas en revisión después de eliminar las palabras vacías")
análisis exploratorio de texto análisis exploratorio de texto
Y así enseguida.
 

Parte del discurso

El etiquetado de partes del discurso (POS) es un proceso de asignación de partes del discurso a cada palabra, como sustantivo, verbo, adjetivo, etc.

gota = TextBlob(calle(d.f.['Texto de revisión']))
 pos_df = p.d..Marco de datos(gota.etiquetas, columnas = ['palabra' , 'pos'])
 pos_df = pos_df.posición.value_counts()[:20]
 pos_df.trama(
 tipo='bar',
 xTítulo='POS',
 yTítulo='contar',
 título='Las 20 principales etiquetas de parte del discurso para el corpus de reseñas')
análisis exploratorio de texto análisis exploratorio de texto

Análisis por clase

El gráfico de caja se utiliza para comparar la puntuación de polaridad de opinión, la calificación y la longitud del texto de revisión de cada departamento o división de la tienda de comercio electrónico.

El puntaje de polaridad de sentimiento más alto lo lograron los seis departamentos excepto el departamento de Tendencias, y el puntaje de polaridad de sentimiento más bajo lo logró el departamento de Tops. Y el departamento de tendencias tiene la puntuación de polaridad media más baja. Si recuerda, el departamento de tendencias tiene la menor cantidad de revisiones. Esto explica por qué no tiene una variedad tan amplia de distribución de puntajes como otros departamentos.

análisis exploratorio de texto análisis exploratorio de texto

Con la excepción del departamento de Tendencias, la calificación mediana para todos los demás departamentos fue de 5. En general, las calificaciones son altas y el sentimiento es positivo en este conjunto de datos de revisión.

análisis exploratorio de texto análisis exploratorio de texto

Y así enseguida.

Análisis bivariado

La visualización bivariada es un tipo de visualización que consta de dos características a la vez. Describe la asociación o relación entre dos características.

Veamos el análisis de sentimiento basado en si la persona recomienda o no el producto.

x1 = d.f..ubicación[d.f.['IND recomendado'] == 1, 'polaridad']
 x0 = d.f..ubicación[d.f.['IND recomendado'] == 0, 'polaridad']
  
 rastro1 = Vamos.Histograma(
 X=x0, nombre='No recomendado',
 opacidad=0.75
 )
 rastro2 = Vamos.Histograma(
 X=x1, nombre = 'Recomendado',
 opacidad=0.75
 )
  
 datos = [rastro1, rastro2]
 diseño = Vamos.diseño(barman='cubrir', título='Distribución de la polaridad de Sentimiento de las revisiones basadas en la Recomendación')
 higo = Vamos.figura(datos=datos, diseño=diseño)
  
 trama(higo, Nombre del archivo='histograma superpuesto')
análisis exploratorio de texto análisis exploratorio de texto
También es posible representar el análisis de sentimiento y la calificación en un diagrama 2D de densidad (no es interesante hacer esto para variables binarias).
rastro1 = Vamos.Dispersión(
 X=d.f.['polaridad'], y=d.f.['Clasificación'], Moda='marcadores', nombre='puntos',
 marcador=decir(color='rgb(102,0,0)', Talla=2, opacidad=0.4)
 )
 rastro2 = Vamos.Histograma2dContorno(
 X=d.f.['polaridad'], y=d.f.['Clasificación'], nombre='densidad', contornos=20,
 escala de colores='Caliente', escala inversa=Verdadero, escala de exhibición=Falso
 )
 rastro3 = Vamos.Histograma(
 X=d.f.['polaridad'], nombre='Densidad de polaridad de sentimiento',
 marcador=decir(color='rgb(102,0,0)'),
 eje y='y2'
 )
 rastro4 = Vamos.Histograma(
 y=d.f.['Clasificación'], nombre='Densidad de calificación', marcador=decir(color='rgb(102,0,0)'),
 eje x='x2'
 )
 datos = [rastro1, rastro2, rastro3, rastro4]
  
 diseño = Vamos.diseño(
 Mostrar leyenda=Falso,
 tamaño automático=Falso,
 ancho=600,
 altura=550,
 eje x=decir(
 dominio=[0, 0.85],
 Mostrar cuadrícula=Falso,
 línea cero=Falso
 ),
 eje y=decir(
 dominio=[0, 0.85],
 Mostrar cuadrícula=Falso,
 línea cero=Falso
 ),
 margen=decir(
 t=50
 ),
 modo flotante='más cercano',
 ganga=0,
 xaxis2=decir(
 dominio=[0.85, 1],
 Mostrar cuadrícula=Falso,
 línea cero=Falso
 ),
 yaxis2=decir(
 dominio=[0.85, 1],
 Mostrar cuadrícula=Falso,
 línea cero=Falso
 )
 )
  
 higo = Vamos.figura(datos=datos, diseño=diseño)
 trama(higo, Nombre del archivo='2dhistogram-2d-density-plot-subplots')
análisis exploratorio de texto análisis exploratorio de texto
 

modelado de contenido

Finalmente, queremos explorar el algoritmo de modelado de temas para este conjunto de datos, para ver si brindaría beneficios y encajaría con lo que estamos haciendo para nuestra funcionalidad de texto de revisión.

Experimentaremos con la técnica de análisis semántico latente (LSA) en el modelado de temas.

  • Generación de nuestra matriz de términos del documento a partir del texto de revisión a una matriz de características TF-IDF.
  • El modelo LSA reemplaza los conteos sin procesar en la matriz de términos del documento con un puntaje TF-IDF.
  • Realice la reducción de dimensionalidad en la matriz de términos del documento utilizando un SVD truncado.
  • Como el número de departamentos es 6, establecemos n_topics=6.
  • Tomar el argmax de cada texto de revisión en esta matriz de temas arrojará los temas predichos de cada texto de revisión en los datos. Luego podemos ordenarlos por número de cada tema.
  • Para comprender mejor cada tema, encontraremos las tres palabras más frecuentes en cada tema.
datos_reindexados = d.f.['Texto de revisión']
 tfidf_vectorizador = TfidfVectorizer(Para las palabras='inglés', use_idf=Verdadero, suave_idf=Verdadero)
 datos_reindexados = datos_reindexados.valores
 document_term_matrix = tfidf_vectorizador.encajar_transformar(datos_reindexados)
 n_temas = 6
 modelo_lsa = TruncadoSVD(n_componentes=n_temas)
 lsa_topic_matrix = modelo_lsa.encajar_transformar(document_term_matrix)
  
 definitivamente obtener_claves(matriz_temática):
  ''
  devuelve una lista de enteros del tema predicho
  categorías para una matriz de tema dada
   ''
 llaves = matriz_temática.argmax(eje=1).lista()
 regreso llaves
  
 definitivamente llaves_a_cuentas(llaves):
  ''
  devuelve una tupla de categorías de temas y sus
  magnitudes que acompañan a una lista dada de claves
   ''
 contar_pares = Encimera(llaves).elementos()
 categorías = [par[0] por par en contar_pares]
 cuenta = [par[1] por par en contar_pares]
 regreso (categorías, cuenta)
  
 lsa_keys = obtener_claves(lsa_topic_matrix)
 lsa_categories, lsa_cuenta = llaves_a_cuentas(lsa_keys)
  
 definitivamente get_top_n_words(no, llaves, document_term_matrix, tfidf_vectorizador):
  ''
  devuelve una lista de cadenas n_topic, donde cada cadena contiene los n más comunes
  palabras en una categoría predicha, en orden
   ''
 top_word_indices = []
 por hilo en ordenado(n_temas):
 temp_vector_sum = 0
 por I en ordenado(después(llaves)):
 tejo llaves[I] == hilo:
 temp_vector_sum += document_term_matrix[I]
 temp_vector_sum = temp_vector_sum.matriz()
 top_n_word_indices = notario público..dar la vuelta(notario público..clasificación(temp_vector_sum)[0][no:],0)
 top_word_indices.adjuntar(top_n_word_indices)
 top_words = []
 por hilo en top_word_indices:
 palabras_temáticas = []
 por índice en hilo:
 vector_palabra_temp = notario público..ceros((1,document_term_matrix.forma[1]))
 vector_palabra_temp[:,índice] = 1
 la palabra = tfidf_vectorizador.transformada_inversa(vector_palabra_temp)[0][0]
 palabras_temáticas.adjuntar(la palabra.codificar('asci').descodificar('utf-8'))
 top_words.adjuntar( » « .unirse(palabras_temáticas))
 regreso top_words
  
 top_n_palabras_lsa = get_top_n_words(3, lsa_keys, document_term_matrix, tfidf_vectorizador)
  
 por I en ordenado(después(top_n_palabras_lsa)):
 impresión("Tema{}:" .formato(I+1), top_n_palabras_lsa[I])
análisis exploratorio de texto análisis exploratorio de texto
top_3_words = get_top_n_words(3, lsa_keys, document_term_matrix, tfidf_vectorizer)
etiquetas = ['Tema {}: \n'.format(i) + top_3_words[i] para i en lsa_categories]
higo, hacha = plt.subplots(figsize=(16,8))
ax.bar(lsa_categories, lsa_counts);
ax.set_xticks(lsa_categories);
ax.set_xticklabels(etiquetas);
ax.set_ylabel('Número de texto de revisión');
ax.set_title('Recuentos de temas de LSA');
plt.mostrar();
análisis exploratorio de texto análisis exploratorio de texto
 

Al observar las palabras más frecuentes en cada tema, tenemos la sensación de que es posible que no alcancemos ningún grado de separación entre las categorías de temas. En otras palabras, no podíamos separar los textos de los exámenes por departamento usando técnicas de modelado de temas.

Las técnicas de modelado temático tienen una serie de limitaciones importantes. Para empezar, el término "tema" es algo ambiguo, y tal vez ahora esté claro que los modelos de temas no producirán una clasificación de texto muy matizada para nuestros datos.