Un significado más profundo: modelado de temas en Python

Publicado: 2022-03-11

Las computadoras y los procesadores que las alimentan están diseñados para trabajar con números. Por el contrario, el lenguaje cotidiano de los correos electrónicos y las publicaciones en las redes sociales tiene una estructura flexible que no se presta al cálculo.

Ahí es donde entra en juego el procesamiento del lenguaje natural (NLP). NLP es una rama de la informática que se superpone con la lingüística mediante la aplicación de técnicas computacionales (es decir, inteligencia artificial) para analizar el lenguaje natural y el habla. El modelado de temas se centra en comprender de qué temas trata un texto determinado. El modelado de temas permite a los desarrolladores implementar funciones útiles como detectar noticias de última hora en las redes sociales, recomendar mensajes personalizados, detectar usuarios falsos y caracterizar el flujo de información.

¿Cómo pueden los desarrolladores convencer a las computadoras centradas en el cálculo para que entiendan las comunicaciones humanas en esos niveles de sofisticación?

Una bolsa de palabras

Para responder a esa pregunta, necesitamos ser capaces de describir un texto matemáticamente. Comenzaremos nuestro tutorial de Python de modelado de temas con el método más simple: bolsa de palabras.

Este método representa un texto como un conjunto de palabras. Por ejemplo, la oración This is an example se puede describir como un conjunto de palabras usando la frecuencia con la que aparecen esas palabras:

 {"an": 1, "example": 1, "is": 1, "this": 1}

Observe cómo este método ignora el orden de las palabras. Toma estos ejemplos:

  • “Me gusta Star Wars pero no me gusta Harry Potter”.
  • “Me gusta Harry Potter pero no me gusta Star Wars”.

Estos sentimientos están representados por las mismas palabras, pero tienen significados opuestos. Sin embargo, a los efectos de analizar los temas de los textos, estas diferencias no importan. En ambos casos, estamos hablando de gustos por Harry Potter y Star Wars, independientemente de cuáles sean esos gustos. Como tal, el orden de las palabras es irrelevante.

Cuando tenemos múltiples textos y buscamos entender las diferencias entre ellos, necesitamos una representación matemática para todo nuestro corpus que considere cada texto por separado. Para ello podemos utilizar una matriz, en la que cada columna representa una palabra o término y cada fila representa un texto. Una posible representación de un corpus consiste en anotar en cada celda la frecuencia con la que se usa una determinada palabra (columna) en un determinado texto (fila).

En nuestro ejemplo, el corpus se compone de dos oraciones (las filas de nuestra matriz):

 ["I like Harry Potter", "I like Star Wars"]

Enumeramos las palabras de este corpus en el orden en que las encontramos: I , like , Harry , Potter , Star , Wars . Estos corresponden a nuestras columnas de matriz.

Los valores en la matriz representan el número de veces que se usa una palabra dada en cada frase:

 [[1,1,1,1,0,0], [1,1,0,0,1,1]] 

La imagen muestra dos líneas de texto a la izquierda: Me gusta Harry Potter y me gusta Star Wars. Luego, este texto se convierte en una bolsa de palabras en el centro, con cada palabra seguida de la cantidad de veces que se usó esa palabra: "Me gusta Harry Potter" se convierte en "{I: 1, me gusta: 1, Harry: 1, Potter : 1, Star: 0, Wars: 0}" y "I like Star Wars" se convierte en "{I: 1, like: 1, Harry: 0, Potter: 0, Star: 1, Wars: 1}" A la derecha , estos números se organizan en una representación matricial: el primero se convierte en la fila "1 1 1 1 0 0" y el segundo se convierte en "1 1 0 0 1 1".
Texto transformado en una representación matricial

Tenga en cuenta que el tamaño de la matriz se determina multiplicando la cantidad de textos por la cantidad de palabras diferentes que aparecen en al menos un texto. Este último suele ser innecesariamente grande y puede reducirse. Por ejemplo, una matriz puede contener dos columnas para verbos conjugados, como "jugar" y "jugar", independientemente de que su significado sea similar.

Pero podrían faltar columnas que describan nuevos conceptos. Por ejemplo, "clásica" y "música" tienen significados individuales, pero cuando se combinan, "música clásica", tienen otro significado.

Debido a estos problemas, es necesario preprocesar el texto para obtener buenos resultados.

Modelos de agrupamiento de temas y preprocesamiento

Para obtener los mejores resultados, es necesario utilizar varias técnicas de preprocesamiento. Estos son algunos de los más utilizados:

  1. Letras minusculas. Escribe todas las palabras en minúsculas. Escribe todas las palabras en minúsculas. El significado de una palabra no cambia independientemente de su posición en la oración.
  2. n -gramos. Considere todos los grupos de n palabras seguidas como nuevos términos, llamados n-gramas . De esta forma, casos como “casa blanca” se tendrán en cuenta y se añadirán a la lista de vocabulario.
  3. Derivación. Identificar prefijos y sufijos de palabras para aislarlas de su raíz. De esta manera, palabras como "jugar", "jugar" o "jugador" se representan con la palabra "jugar". Stemming puede ser útil para reducir el número de palabras en la lista de vocabulario conservando su significado, pero ralentiza considerablemente el preprocesamiento porque debe aplicarse a cada palabra del corpus.
  4. Para las palabras. No tomar en cuenta grupos de palabras carentes de significado o utilidad. Estos incluyen artículos y preposiciones, pero también pueden incluir palabras que no son útiles para nuestro estudio de caso específico, como ciertos verbos comunes.
  5. Frecuencia de término–frecuencia de documento inversa (tf–idf). Use el coeficiente de tf–idf en lugar de anotar la frecuencia de cada palabra dentro de cada celda de la matriz. Se compone de dos números, multiplicados:
    • tf—la frecuencia de un término o palabra dada en un texto, y
    • idf: el logaritmo del número total de documentos dividido por el número de documentos que contienen ese término dado.

    tf–idf es una medida de la frecuencia con la que se usa una palabra en el corpus. Para poder subdividir las palabras en grupos, es importante comprender no solo qué palabras aparecen en cada texto, sino también qué palabras aparecen con frecuencia en un texto pero no en todos los demás.

La siguiente figura muestra algunos ejemplos simples de estas técnicas de preprocesamiento donde se modifica el texto original del corpus para generar una lista de palabras relevante y manejable.

La técnica de las "letras minúsculas" transforma la frase "La Casa Blanca". en una lista de palabras: "el", "blanco", "casa". La técnica de los "n-gramas" la transforma en una lista más larga: "la", "blanca", "casa", "la blanca", "casa blanca". La técnica de "derivación" transforma la oración "El jugador de fútbol jugó un buen partido". en esta lista: "el", "fútbol", "juego", "un", "bueno", "juego". La técnica de las "palabras vacías" lo transforma en una lista más corta: "fútbol", "jugar", "bien", "juego".
Ejemplos de técnicas de preprocesamiento de texto

Ahora demostraremos cómo aplicar algunas de estas técnicas en Python. Una vez que tenemos nuestro corpus representado matemáticamente, necesitamos identificar los temas que se están discutiendo aplicando algoritmos de aprendizaje automático no supervisados. En este caso, "no supervisado" significa que el algoritmo no tiene ninguna etiqueta de tema predefinida, como "ciencia ficción", para aplicar a su salida.

Para agrupar nuestro corpus, podemos elegir entre varios algoritmos, incluida la factorización de matriz no negativa (NMF), el análisis de componentes principales dispersos (PCA disperso) y la asignación de dirichlet latente (LDA). Nos centraremos en LDA porque es ampliamente utilizado por la comunidad científica debido a sus buenos resultados en redes sociales, ciencias médicas, ciencias políticas e ingeniería de software.

LDA es un modelo de descomposición de temas no supervisada: agrupa textos en función de las palabras que contienen y la probabilidad de que una palabra pertenezca a un tema determinado. El algoritmo LDA genera la distribución de palabras del tema. Con esta información, podemos definir los temas principales en función de las palabras que probablemente se asocien con ellos. Una vez que hemos identificado los temas principales y sus palabras asociadas, podemos saber qué tema o temas se aplican a cada texto.

Considere el siguiente corpus compuesto por cinco oraciones cortas (todas tomadas de los titulares del New York Times ):

 corpus = [ "Rafael Nadal Joins Roger Federer in Missing US Open", "Rafael Nadal Is Out of the Australian Open", "Biden Announces Virus Measures", "Biden's Virus Plans Meet Reality", "Where Biden's Virus Plan Stands"]

El algoritmo debe identificar claramente un tema relacionado con la política y el coronavirus, y otro relacionado con Nadal y el tenis.

Aplicando la estrategia en Python

Para poder detectar los temas, debemos importar las bibliotecas necesarias. Python tiene algunas bibliotecas útiles para NLP y aprendizaje automático, incluidas NLTK y Scikit-learn (sklearn).

 from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfTransformer from sklearn.decomposition import LatentDirichletAllocation as LDA from nltk.corpus import stopwords

Usando CountVectorizer() , generamos la matriz que denota la frecuencia de las palabras de cada texto usando CountVectorizer() . Tenga en cuenta que CountVectorizer permite el preprocesamiento si incluye parámetros como stop_words para incluir las palabras vacías, ngram_range para incluir n -grams o lowercase lowercase=True para convertir todos los caracteres a minúsculas.

 count_vect = CountVectorizer(stop_words=stopwords.words('english'), lowercase=True) x_counts = count_vect.fit_transform(corpus) x_counts.todense() matrix([[0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0], [1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1]], dtype=int64)

Para definir el vocabulario de nuestro corpus, simplemente podemos usar el atributo .get_feature_names() :

 count_vect.get_feature_names() ['announces', 'australian', 'biden', 'federer', 'joins', 'measures', 'meet', 'missing', 'nadal', 'open', 'plan', 'plans', 'rafael', 'reality', 'roger', 'stands', 'virus']

Luego, realizamos los cálculos tf-idf con la función sklearn:

 tfidf_transformer = TfidfTransformer() x_tfidf = tfidf_transformer.fit_transform(x_counts)

Para realizar la descomposición LDA, tenemos que definir el número de temas. En este caso simple, sabemos que hay dos temas o “dimensiones”. Pero en los casos generales, este es un hiperparámetro que necesita algunos ajustes, lo que podría hacerse usando algoritmos como la búsqueda aleatoria o la búsqueda en cuadrícula:

 dimension = 2 lda = LDA(n_components = dimension) lda_array = lda.fit_transform(x_tfidf) lda_array array([[0.8516198 , 0.1483802 ], [0.82359501, 0.17640499], [0.18072751, 0.81927249], [0.1695452 , 0.8304548 ], [0.18072805, 0.81927195]])

LDA es un método probabilístico. Aquí podemos ver la probabilidad de que cada uno de los cinco titulares pertenezcan a cada uno de los dos temas. Podemos ver que los dos primeros textos tienen mayor probabilidad de pertenecer al primer tema y los siguientes tres al segundo tema, como era de esperar.

Finalmente, si queremos entender de qué se tratan estos dos temas, podemos ver las palabras más importantes de cada tema:

 components = [lda.components_[i] for i in range(len(lda.components_))] features = count_vect.get_feature_names() important_words = [sorted(features, key = lambda x: components[j][features.index(x)], reverse = True)[:3] for j in range(len(components))] important_words [['open', 'nadal', 'rafael'], ['virus', 'biden', 'measures']]

Como era de esperar, LDA asignó correctamente palabras relacionadas con torneos de tenis y Nadal al primer tema y palabras relacionadas con Biden y virus al segundo tema.

Análisis a gran escala y casos de uso del mundo real

En este documento se puede ver un análisis a gran escala del modelado de temas; Estudié los principales temas noticiosos durante las elecciones presidenciales de EE. UU. de 2016 y observé los temas que algunos medios masivos, como el New York Times y Fox News, incluyeron en su cobertura, como la corrupción y la inmigración. En este artículo, también analicé las correlaciones y causalidades entre el contenido de los medios masivos y los resultados electorales.

El modelado de temas también se usa ampliamente fuera de la academia para descubrir patrones temáticos ocultos presentes en grandes colecciones de textos. Por ejemplo, se puede utilizar en sistemas de recomendación o para determinar de qué hablan los clientes/usuarios en encuestas, formularios de comentarios o en las redes sociales.

El Blog de Ingeniería de Toptal extiende su agradecimiento a Juan Manuel Ortiz de Zárate por revisar los ejemplos de código presentados en este artículo.

Lectura recomendada sobre modelado de temas

Modelado de temas mejorado en Twitter
Albanese, Federico y Esteban Feuerstein. "Modelado de temas mejorado en Twitter a través de la agrupación comunitaria". (20 de diciembre de 2021): arXiv:2201.00690 [cs.IR]

Análisis de Twitter para la salud pública
Paul, Michael y Mark Dredze. “Eres lo que tuiteas: análisis de Twitter para la salud pública”. 3 de agosto de 2021.

Clasificación de la orientación política en Twitter
Cohen, Raviv y Derek Ruths. “Clasificar la orientación política en Twitter: ¡No es fácil!” 3 de agosto de 2021.

Uso de modelos temáticos relacionales para capturar el acoplamiento
Gethers, Malcolm y Denis Poshyvanyk. "Uso de modelos de temas relacionales para capturar el acoplamiento entre clases en sistemas de software orientados a objetos". 25 de octubre de 2010.