-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathunidad3_topic-modeling.Rmd
256 lines (173 loc) · 20.4 KB
/
unidad3_topic-modeling.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
---
title: "Unidad 3 - Topic Modeling"
author: "Nidia Hernández"
output:
html_document:
df_print: paged
---
```{css, echo=FALSE}
body {
padding-bottom: 52px;
}
```
<h6>[email protected]</h6>
<hr align="left" style="width:40%">
En esta guía vamos a:
* definir brevemente el _topic modeling_ a través de un estudio de caso
* poner en práctica herramientas de modelado de tópicos en un corpus de textos histórico-literarios
## Introducción
El _topic modeling_ es un método estadístico de organización de grandes corpus en el que un algoritmo recibe datos no etiquetados para agruparlos según patrones comunes subyacentes. Si bien esta técnica fue concebida para la gestión de colecciones textuales, tiene aplicaciones en diversos campos, tales como la genética de poblaciones y el procesamiento de imágenes por IA.
En el ámbito del procesamiento de textos en particular, el _topic modeling_ es utilizado para detectar los tópicos^[Algunas aclaraciones sobre la terminología típica asociada a esta técnica: utilizamos el término _colección_ para denominar al conjunto de textos con el que vamos a trabajar y _documento_ para referirnos a cada uno de los textos. Los resultados a obtener son _tópicos_ o temas.] presentes en una colección textual, los documentos que responden a cada tópico así como las palabras que lo representan. En otras palabras, esta técnica nos permite acceder rápidamente al contenido de un gran dataset de textos y organizar los textos en grupos de acuerdo a su temática.
<img src="https://upload.wikimedia.org/wikipedia/commons/6/6e/Topic_detection_in_a_document-word_matrix.gif" alt="matriz término-documento animada"/>
*Figura 1. Detección de tópicos en una matriz de términos por documento. Cada columna corresponde a un documento y cada fila a una palabra; las celdas muestran la frecuencia de una palabra de un documento (más oscura, mayor frecuencia). Fuente: Christoph Carl Kling, via Wikimedia Commons, CC-BY-SA-4.0*
Un buen ejemplo de _topic modeling_ aplicado a las humanidades es el trabajo del proyecto [WhatEvery1Says](https://we1s.ucsb.edu/), que se sirve de esta técnica de macroanálisis para estudiar la representación de las disciplinas de humanidades en el discurso público de Estados Unidos a lo largo de 20 años. Gracias al _topic modeling_, este proyecto ha podido explorar 21 colecciones textuales integradas por 83 000 artículos periodísticos, 21 000 artículos de diarios universitarios, 800 000 tweets y 124 000 posts de Reddit y agrupar los textos por temáticas como "la crisis de las humanidades", "el valor de las humanidades", "las humanidades y las ciencias en los medios", "el financiamiento de las humanidades", entre otros.
<iframe src="http://harbor.english.ucsb.edu:10002/collections/20190620_2238_us-humanities-all-no-reddit/topic-bubbles/topics25/" name="visualización topic bubbles interactiva" loading="eager" width="100%" height="600" style="border: 1px solid #ccc; border-radius: 4px; display: block; padding: 9.5px; margin: 0 0 10px;"></iframe>
*Figura 2. Detección de tópicos del proyecto [WhatEvery1Says](https://we1s.ucsb.edu/) para la colección de artículos de [medios de los EEUU entre 1989-2019](http://harbor.english.ucsb.edu:10002/collections/20190620_2238_us-humanities-all-no-reddit/). Hacer click sobre los tópicos para abrir una nube de palabras interactiva.*
La visualización interactiva de arriba representa 25 tópicos detectados en una colección de más de 83 mil artículos periodísticos de grandes medios de Estados Unidos (New York Times, Washington Post, Los Angeles Times, Chicago Tribune, entre otros). Los círculos más grandes representan tópicos con mayor peso. En las nubes de palabras asociadas, podemos ver las principales palabras que componen cada tópico y, si clickeamos en el círculo turquesa de abajo a la derecha, podremos acceder a un gráfico de los principales periódicos en los que se publicaron los artículos analizados así como los títulos de los artículos más representativos del tópico.
Si clickeamos en el tópico 17, por ejemplo, podremos ver palabras relacionadas con eventos universitarios (estudiantes, campus, conferencia, evento, discusión, charla, etc.) y, si consultamos las fuentes de los artículos, encontraremos periódicos universitarios (The Stanford Daily, Campus Carrier y publicaciones de otras universidades). Al acceder a los principales documentos de este tópico, econtraremos, efectivamente, títulos como "College of DuPage Hosts 'What is Gender?' Panel Discussion Nov. 8", "Race: A Campus Dialogue" o "Festival of Books and Arts at UTPA". Entre los demás tópicos, podremos encontrar temas relacionados de manera más directa (escritura académica, tópico 4) o más indirecta (política internacional, tópico 16).
Para comprender mejor el funcionamiento de este método estadístico de lectura distante, comenzaremos por aplicarlo a un caso donde ya conocemos la respuesta de antemano: buscaremos agrupar temáticamente un corpus de tres textos^[Aplicamos _topic modeling_ en un corpus reducido únicamente a fines pedagógicos. El interés real de esta técnica radica en la exploración de colecciones de un número elevado de textos.] (para reproducir los pasos de la guía, descargar el corpus vía [campus](https://campusvirtual.uces.edu.ar/mod/folder/view.php?id=333749)) y veremos si el algoritmo de _topic modeling_ es capaz de distinguir correctamente tres grupos. Utilizaremos los txt correspondientes a [_Relación de las cosas sucedidas en el Río de la Plata_](http://hdlab.space/Relacion-de-las-cosas-sucedidas/) de Pero Hernández, [_Relación de un viaje al Río de la Plata_](http://hdlab.space/Relacion-de-un-viaje/) de Acarette du Biscay y [_La Argentina Manuscrita_](http://hdlab.space/La-Argentina-Manuscrita/) de Ruy Díaz de Guzmán, relatos histórico-literarios sobre la conquista y colonización del Río de la Plata. Estos textos se encuentran disponibles en edición digital y forman parte de la biblioteca digital de HDCAICYT LAB <http://hdlab.space/biblioteca-digital/>.
## Implementación
### Preparación de los datos de entrada
Existen diversos paquetes y algoritmos para realizar _topic modeling_ en R, tales como [mallet](https://cran.r-project.org/package=mallet), [lda](https://cran.r-project.org/package=lda) y [topicmodels](https://cran.r-project.org/package=topicmodels). En esta práctica vamos a servirnos de este último.
Para comenzar, vamos a cargar varios paquetes necesarios para la experimentación. Algunos de ellos (`topicmodels`, `tm` y `scales`) no fueron utilizados antes en nuestras prácticas, por lo que vas a tener que instalarlos con `install.packages()`. Si la instalación de `topicmodels` emite un mensaje de error, abrí una terminal y ejecutá `sudo apt install libgsl-dev` en Linux o `brew install gsl` en MacOS.
```{r message=FALSE, warning=FALSE}
library(tidyverse)
library(tidytext)
library(tm)
library(topicmodels)
library(scales)
```
A continuación, cargamos el corpus en una tibble de dos columnas, **texto** y **documento**, y asignamos a la primera el contenido textual de cada archivo del corpus y a la segunda el nombre de cada archivo. Luego tokenizamos, limpiamos el corpus (filtrando stopwords, eliminando números y palabras de un solo caracter) y calculamos las ocurrencias de cada palabra en cada documento:
```{r message=FALSE, warning=FALSE}
path_archivos <-
list.files("corpus-tp", pattern = "\\.txt$", full.names = TRUE) # Modificar de acuerdo al nombre de la carpeta donde se encuentra nuestro corpus
coleccion <- tibble(texto = character(),
documento = character())
for (path in path_archivos) {
lineas <- read_lines(path)
temporal <- tibble(texto = lineas,
documento = basename(path))
coleccion <- bind_rows(coleccion, temporal)
}
stopwords_es <-
get_stopwords("spa") %>%
rename(palabra = word)
coleccion <-
coleccion %>%
unnest_tokens(palabra, texto) %>%
anti_join(stopwords_es) %>%
filter(!str_detect(palabra, "[0-9]+")) %>% # elimina números
filter(nchar(palabra) > 1) %>% # elimina palabras como "ó", "á", "é"
count(documento, palabra, sort = TRUE) # cuenta ocurrencias de cada palabra en su documento
```
Es muy importante señalar que en esta etapa de preparación de datos de entrada o preprocesamiento, podemos combinar tratamientos vistos en las unidades anteriores --como generar ngrams o filtrar por clase de palabra-- o técnicas de NLP más sofisticadas --como [identificación de Named Entities](https://es.wikipedia.org/wiki/Reconocimiento_de_entidades_nombradas)-- que pueden beneficiar enormemente la calidad de los resultados para la interpretación humana.
La preparación mínima requerida para esta experiencia de _topic modeling_ consiste en un dataframe con el nombre de cada documento, las palabras de cada documento y la frecuencia de cada palabra en cada documento:
```{r}
coleccion
```
El paquete `topicmodels` requiere los datos de entrada en un formato particular conocido como `DocumentTermMatrix` (Matrices de Términos por Documento; en la Unidad de [Introducción al Análisis Textual](hdlab.space/Estilometria-con-R/unidad2_analisis-textual.html), vimos ejemplos de este tipo de matrices en las [tablas de tipos de frecuencias](http://hdlab.space/Estilometria-con-R/unidad2_analisis-textual.html#frecuencia-absoluta-frecuencia-relativa-y-tf.idf)). Podemos transformar nuestro dataframe `coleccion` en un objeto `DocumentTermMatrix` gracias a la función `cast_dtm()`.
```{r message=FALSE, warning=FALSE}
coleccion_dtm <-
coleccion %>%
cast_dtm(documento, palabra, n)
```
Ahora que los datos están en el formato adecuado, podemos pasar a la etapa de aprendizaje automático.
### Entrenamiento con LDA
Una vez que transformamos el corpus al formato requerido por `topicmodels`, podemos someter los datos al algoritmo de extracción de tópicos. En esta práctica veremos cómo implementar LDA (siglas de _Latent Dirichlet Allocation_), uno de los métodos más populares de _topic modeling_, desarrollado por David Blei en 2012^[Blei, D. M. (2012). Probabilistic topic models. _Communications of the ACM_, 55(4), 77–84. https://doi.org/10.1145/2133806.2133826]. Obtendremos como resultado modelos de tópicos (_topic models_). La cantidad de tópicos en un modelo varía en función del corpus, sin embargo, en este ejercicio ya sabemos que queremos encontrar 3 tópicos (uno por cada texto de nuestro corpus), de manera que en la función de entrenamiento fijaremos `k = 3`. En una experiencia real de _topic modeling_ es necesario probar diferentes valores de k y evaluar cuál arroja resultados más coherentes^[Para un ejemplo de evaluación de _topic modeling_ con distintos valores de k, consultar https://github.com/nidiah/Topic-modeling-gestion-datos/blob/main/experiencias_informes.ipynb (en Python)].
En primer lugar, creamos el modelo de tres tópicos sobre el corpus bajo análisis (este paso será breve, pero en un corpus más grande y/o con un valor más elevado de k, el entrenamiento puede tomar bastante tiempo):
```{r}
coleccion_lda <- LDA(coleccion_dtm, k = 3, control = list(seed = 42))
coleccion_lda
```
La generación de modelos con LDA involucra muchos procesos aleatorios^[Para una introducción a los fundamentos matemáticos de LDA, consultar https://www.youtube.com/watch?v=T05t-SqKArY], por eso, si queremos poder reproducir y comparar resultados generados por este algoritmo, debemos "plantar una semilla" que permita controlar la variación; para eso establecemos el parámetro `control = list(seed = 42)`.
El resto del análisis involucra explorar e interpretar los tópicos resultantes.
## Análisis de resultados
### Palabras en cada tópico
Veamos las primeras diez palabras más representativas de cada uno de los tres tópicos generados:
```{r}
terms(coleccion_lda, 10) %>% as_tibble
```
En esta técnica, cada tópico es una colección de palabras con "pesos" asociados. Las palabras que mejor definen al tópico (las asociadas con mayor probabilidad al tópico) aparecen primero en la lista. Nada impide que tópicos diferentes compartan palabras, pero la combinación de muchas palabras y probabilidades diferencia a los tópicos entre sí.
A partir de nuestro conocimiento previo de los textos, observamos que el tópico 2 presenta palabras muy representativas de la _Relación de las cosas sucedidas_ de Pero Hernández (la relación da cuenta del enfrentamiento entre Domingo de Irala y el Gobernador, Álvar Núñez) y el tópico 1 muestra palabras como "capitán" y "pedro", muy caractrísticas de _La Argentina Manuscrita_ de Ruy Díaz (el texto relata la fundación de Asunción realizada por uno de los capitanes de Pedro de Mendoza). Es importante señalar que encontramos palabras repetidas entre tópicos ("río", "indios", "plata"), lo cual es lógico si tenemos en cuenta que los textos seleccionados tocan temas en común ya que todos tratan sobre la colonización de zona del Río de la Plata a fines del siglo XVI - principios del siglo XVII. Aquí se evidencia la flexibilidad de la técnica, que permite encontrar solapamiento entre tópicos, como sucede en las colecciones textuales reales.
Ahora que ya conocemos los datos de salida de un modelado LDA, veremos cómo usarlos para generar gráficos. El paquete `tidytext` permite extraer las probabilidades por palabra dentro de cada tópico, a las que llama "betas". Exploremos, por ejemplo, las palabras de mayor peso en el tópico 2:
```{r}
topicos_coleccion <-
tidy(coleccion_lda, matrix = "beta") %>% # Esta línea puede requerir instalar el paquete reshape2
arrange(topic, desc(beta))
topicos_coleccion %>%
filter(topic == 2)
```
Los valores absolutos de probabilidad no importan tanto como sus relaciones. Usualmente, son números muy pequeños^[Para anular la notación científica, podés agregar `options("scipen" = 100, "digits" = 4)` a tu script.] que provienen de alguna transformación de la frecuencias de la palabra en el documento. En este caso, no nos importa que `gobernador` tenga un valor de 0.02, sino que es el mayor valor observado para este tópico o que es mayor que el valor de `oficiales`.
Vamos a graficar las primeras diez palabras que definen a cada tópico con sus pesos asignados.
```{r}
top_terms <- topicos_coleccion %>%
group_by(topic) %>%
top_n(10, beta) %>%
ungroup() %>%
arrange(topic, -beta)
top_terms %>%
mutate(term = reorder(term, beta)) %>%
ggplot(aes(term, beta, fill = factor(topic))) +
geom_col(show.legend = FALSE) +
facet_wrap(vars(topic), scales = "free") +
coord_flip() +
ggtitle("Principales palabras de cada tópico")
```
## Tópicos en cada documento
Como señalamos más arriba, nuestro conocimiento previo de los textos nos permite inferir rápidamente que el tópico
2 tiene una fuerte asociación al texto de Pero Hernández. Podemos confirmar esto con el valor de "gamma" que la técnica calcula para cada tópico y documento. En el caso bajo análisis, los tres tópicos encontrados distinguen fuertemente a los tres textos, como podemos ver en los valores de gamma redondeados:
```{r}
coleccion_gamma <- tidy(coleccion_lda, matrix = "gamma")
coleccion_gamma %>%
mutate(gamma = factor(round(gamma))) %>%
ggplot() +
aes(x = topic, y = document, fill = gamma) +
geom_tile() +
scale_fill_manual(values = c("Grey", "SeaGreen")) +
ggtitle("Principales tópicos en cada documento")
```
Los resultados son, en este caso, categóricos: un texto pertenece a un tópico (color verde) o no pertenece a un tópico (color gris). En experiencias de modelado real, los documentos pueden asociarse a más de un tópico (un texto puede tratar acerca de la fundación de una ciudad **y** del enfrentamiento entre dos personajes). Esta ambigüedad sería representada en el gráfico por un gradiente de color, como en la animación presentada al inicio de la guía.
## Visualización interactiva de tópicos
La complejidad de los resultados del _topic modeling_ habilita visualizaciones más dinámicas que las que realizamos hasta el momento con ggplot. Existe una amplia variedad de visualizaciones interactivas, que pueden combinar desde burbujas de tópicos hasta nubes de palabras, lollypop charts y/o diagramas de flujo, entre otras posiblidades (ver [video](https://vimeo.com/437987253) de [TopicBubbles](https://github.com/sihwapark/topic-bubbles) de Sihwa Park o la [demo online](http://agoldst.github.io/dfr-browser/demo/) de [dfr-browser](http://agoldst.github.io/dfr-browser/) de Andrew Goldstone).
Aquí veremos cómo generar un una visualización interactiva con [LDAvis](https://github.com/cpsievert/LDAvis) una herramienta creada por Carson Sievert y Kenneth E. Shirley que combina un gráfico de barras volteado con representación de distancias de tópicos en coordenadas cartesianas. Comenzamos por cargar la librería `LDAvis` y sus dependencias:
```{r message=FALSE, warning=FALSE}
library(tsne)
library(LDAvis)
```
Adaptamos nuestro modelo de tópicos y nuestra matriz de documentos a los formatos requeridos por el paquete:
```{r message=FALSE, warning=FALSE}
terminos_y_topicos <- posterior(coleccion_lda)
coleccion_dtm <- as.matrix(coleccion_dtm)
```
Y generamos la visualización con el siguiente código:
```{r message=FALSE, warning=FALSE}
svd_tsne <- function(x) tsne(svd(x)$u)
json <- createJSON(
phi = terminos_y_topicos$terms,
theta = terminos_y_topicos$topics,
doc.length = rowSums(coleccion_dtm),
vocab = colnames(coleccion_dtm),
term.frequency = colSums(coleccion_dtm),
mds.method = svd_tsne,
plot.opts = list(xlab="", ylab="")
)
serVis(json, out.dir = "LDAvis") # Guarda el resultado en el directorio "LDAvis"
```
El resultado quedará guardado como un html en el directorio indicado en `out.dir`.
Deslizá el cursor sobre los círculos y usá los controles de la parte superior para modificar los gráficos:
<iframe src="LDAvis/index.html" width="100%" height="800px" style="border:none;"></iframe>
El gráfico de barras de la derecha indica la frecuencia de una palabra en la colección (en azul) y en cada tópico (en rojo). En las coordenadas cartesianas situadas a la izquierda, se representa la distancia entre los tópicos. En el caso analizado, los tópicos son bien ortogonales pero en el caso de haber similitudes entre los tópicos, los círculos aparecerían superpuestos. El tamaño de los círculos indica, por otra parte, el peso del tópico en la colección; así, el tópico asociado al documento más extenso, _La Argentina Manuscrita_ (tópico 1), es más importante. La relación entre los tópicos y las palabras que los conforman está ilustrada de manera interactiva: al deslizar el cursor sobre el círculo de cada tópico, el gráfico de barras cambia para mostrar la lista de palabras de ese tópico.
Esta ha sido una pequeña introducción a la técnica realizada con un minicorpus de tres textos donde ya sabíamos la respuesta. El verdadero interés del _topic modeling_ se vuelve evidente al aplicarlo a colecciones más amplias para **descubrir** los tópicos. Te invitamos a experimentar con la práctica que se encuentra al final de la guía.
## Bibliografía
* Maier, D., Waldherr, A., Miltner, P., Wiedemann, G., Niekler, A., Keinert, A., Pfetsch, B., Heyer, G., Reber, U., Häussler, T., Schmid-Petri, H., & Adam, S. (2018). Applying LDA Topic Modeling in Communication Research: Toward a Valid and Reliable Methodology. Communication Methods and Measures, 12(2–3), 93–118. https://doi.org/10.1080/19312458.2018.1430754
* Mohr, J. W., & Bogdanov, P. (2013). Introduction—Topic models: What they are and why they matter. Poetics, 41(6), 545–569. https://doi.org/10.1016/j.poetic.2013.10.001
* Silge, J., & Robinson, D. (2017). Topic modeling. En _Text mining with R: A tidy approach_. O'Reilly Media. Disponible en línea: https://www.tidytextmining.com/topicmodeling.html
* Underwood, T. (2012) Topic modeling made just simple enough. The Stone and the Shell. (2012, abril 7). https://tedunderwood.com/2012/04/07/topic-modeling-made-just-simple-enough/
----
## Práctica
* Leer los txt de los discursos presidenciales utilizados en las prácticas anteriores (u otro corpus de tu interés).
* Tokenizarlos, limpiarlos y guardarlos en un dataframe.
* Transformar el dataframe en una DTM (DocumentTermMatrix).
* Extraer los tópicos de los discursos presidenciales transformados en DTM con LDA. Probar distintos valores de k hasta encontrar tópicos relevantes. Modificar la limpieza de ser necesario.
* Graficar las primeras 7 palabras de cada tópico con ggplot
* Compartir y comentar los resultados en el [foro](https://campusvirtual.uces.edu.ar/mod/forum/view.php?id=333750).