class: center, middle .linea-superior[] .linea-inferior[] <img src="imagenes/logo_portada2.png" width="200" /> ## INE Educa: Clases abiertas de R ## Proyecto Ciencia de Datos ### Agosto 2023 --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Bienvenidos y bienvenidas .center[ <img src="imagenes/bienvenida.png" width="600" /> ] --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Contenidos - Introducción - Tokenización - TF-IDF - *Word embeddings* - Clasificador de sentimientos -- **Objetivo de la clase** Mostrar diferentes herramientas para trabajar con datos de texto **Tendrán la posibilidad de seguir la clase, pero no es necesario** --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Antes de seguir ```r if (!require("quanteda")) install.packages("quanteda") if (!require("tidyverse")) install.packages("tidyverse") if (!require("quanteda.textstats")) install.packages("quanteda.textstats") if (!require("kableExtra")) install.packages("kableExtra") if (!require("word2vec")) install.packages("word2vec") if (!require("reticulate")) install.packages("reticulate") if (!require("tm")) install.packages("tm") ``` Descarguen los archivos que están acá: - [opción 1: google drive](https://drive.google.com/drive/folders/1KQjyE2tKht7OWIZOJ1dyXKedtQdHjyxa?usp=sharing) - [opción 2: one drive](https://inechile.sharepoint.com/:f:/s/cienciadedatos/EtsXv7EPGoRHmv_hstSVCLUBr_ux4i2URQmoNvQh5raG7g?e=Im1tdd) -- ### Ejecuten el código del archivo helpers.R --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Aplicaciones .center[ <img src="imagenes/ejemplos_nlp.png" width="800" /> ] --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Algunos conceptos ## Text mining - minería de texto ## Procesamiento de Lenguage Natural (NLP) ## Analítica textual -- .center[ <img src="https://media.giphy.com/media/UP9ItQNj52DsM3e29m/giphy.gif" width="200" /> ] -- .center[ ## Herramientas para trabajar con texto ] --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Relevancia ### La cantidad de datos de texto crece día a día de manera veloz -- #### Es imposible analizarlo todo de manera manual -- #### Necesitamos herramientas automáticas .pull-left[ <img src="imagenes/logo_twitter.jpg" width="300" /> ] .pull-right[ <img src="imagenes/logo_wiki.png" width="200" /> ] --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Desafíos al trabajar con texto - Es ambiguo - Requiere un contexto - Es flexible -- ```r animal <- "perro" if (animal == "perro") { print("guau") } ``` ``` ## [1] "guau" ``` -- .center[ ### Si el animal es un perro, imprime un ladrido ] -- ### Afortunadamente, contamos con herramientas para trabajar con texto --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Los datos Conjunto de noticias obtenidas de los diarios La Razón y Público de España El archivo está en los links ya señalados: [acá](https://drive.google.com/drive/folders/1KQjyE2tKht7OWIZOJ1dyXKedtQdHjyxa?usp=sharing) o [acá](https://inechile.sharepoint.com/:f:/s/cienciadedatos/EtsXv7EPGoRHmv_hstSVCLUBr_ux4i2URQmoNvQh5raG7g?e=Im1tdd) -- Dos columnas relevantes: 1. cuerpo 2. titular ```r data <- read_csv("data/data_larazon_publico_v2.csv") ``` .center[ <img src="imagenes/ejemplo_dataset.png" width="700" /> ] --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # La herramienta En `R` existen varios paquetes para trabajar con datos de texto - tm - tidytext - stringr - spacyr (wrapper) - text2vec -- .center[ <img src="imagenes/logo_quanteda.png" width="400" /> ] En este [sitio](https://tutorials.quanteda.io/) hay una documentación muy completa --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Creando una matriz de frecuecia (DFM) ### Es útil contar con una representación numérica de los textos -- Nos permite realizar operaciones algebraicas -- **Dos estrategias muy utilizadas**: - Bolsa de palabras (frecuencias brutas, TF-IDF, etc.) - *Word embeddings* (*deep learning*) -- ### Revisaremos ambas durante esta sesión --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # ¿Qué es una DFM? .panelset[ .panel[.panel-name[dfm] Cada texto es descompuesto a partir de las palabras que contiene ```r ejemplo <- data.frame(text = c("Mi gato es un tirano en casa. Él es amo y señor.", "Soy esclavo de mi gato." )) dfm_ejemplo <- ejemplo %>% corpus() %>% dfm() dfm_ejemplo ``` ``` ## Document-feature matrix of: 2 documents, 15 features (40.00% sparse) and 0 docvars. ## features ## docs mi gato es un tirano en casa . él amo ## text1 1 1 2 1 1 1 1 2 1 1 ## text2 1 1 0 0 0 0 0 1 0 0 ## [ reached max_nfeat ... 5 more features ] ``` ] .panel[.panel-name[pasos] Pasos: 1. Definimos cuál será nuestra unidad básica (*token*) 2. Encontramos todos los *tokens* únicos 3. Contamos cuántas veces aparece cada *token* en un texto ### Para nosotros, un *token* será una palabra ] .panel[.panel-name[importante] Cada texto es descrito por un vector que tiene tantas dimensiones como *tokens* tenga nuestro vocabulario **Atención**: Si nuestro vocabulario es muy grande, el manejo de los vectores puede volverse complejo El resultado es una matriz con una gran cantidad de ceros (*sparse matrix*) ] ] --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Creando una matriz de frecuencia (DFM) ```r set.seed(123) corpus <- data %>% select(text = cuerpo) %>% sample_frac(0.2) %>% corpus() dfm <- corpus %>% dfm() ``` **Importante** - *dfm*: Document frequency matrix - Es obligación que la columna con el texto se llame text --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Volvamos a nuestra matriz original ```r dim(dfm) ``` ``` ## [1] 11685 118903 ``` Tenemos 118903 *tokens* distintos -- Reduzcamos un poco el número de *tokens* para facilitar el procesamiento - signos de puntuación - símbolos extraños - palabras poco significativas (*stopwords*) - palabras con menos de 3 caracteres - palabras que aparecen menos de 10 veces ```r set.seed(123) tokens_data <- data %>% select(text = cuerpo) %>% sample_frac(0.2) %>% corpus() %>% * tokens( remove_punct = TRUE, remove_symbols = TRUE) %>% * tokens_select( pattern = stopwords("es"), selection = "remove", min_nchar=3L) dfm2 <- tokens_data %>% dfm() %>% * dfm_trim(min_termfreq = 10) ``` ```r dim(dfm2) ``` ``` ## [1] 11685 23024 ``` --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Exploremos el dataset .pull-left[ ```r largo_textos <- map_int(tokens_data, length) df_largo <- data.frame(largo = largo_textos) df_largo %>% ggplot(aes(x = largo)) + geom_histogram(binwidth = 15) + theme_bw() ``` ![](nlp_files/figure-html/plot_largo-1.png)<!-- --> ] .pull-right[ ```r summary(df_largo$largo) ``` ``` ## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 2 188 290 352 440 5256 ``` ] --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Exploremos el dataset Exploremos las palabras más y menos comunes ```r dfm2 %>% quanteda::topfeatures(n = 10) ``` ``` ## gobierno personas podemos años horas partido españa dos ## 23135 15316 11717 11530 11285 11232 11190 11188 ## madrid así ## 10997 10400 ``` -- ```r dfm2 %>% quanteda::topfeatures(n = 10, decreasing = F) ``` ``` ## palestina israelíes perturbadoras gestoría cautos ## 10 10 10 10 10 ## coordinó exchófer aportara 1968 actuara ## 10 10 10 10 10 ``` --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Exploremos el dataset Nos interesa observar las menciones relativas a la ETA ```r comentarios_eta <- tokens_data %>% kwic( pattern = "eta", window = 7) # << ```
### Retomaremos estos datos al final de la sesión --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Recuperando información Queremos encontrar textos similares a este <table> <thead> <tr> <th style="text-align:left;"> texto </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> agentes de la policía nacional han auxiliado a dos ciudadanas españolas víctimas de violencia de género en el extranjero.una de las mujeres residía en la ciudad palestina de hebrón. casada con un ciudadano palestino desde 2017, vivía recluida junto a su hija de 4 años en casa de sus suegros sufriendo agresiones físicas por parte de su marido y sin libertad de movimientos. en el otro caso, la víctima vivía incomunicada en praga, sin acceso a su teléfono móvil ni a su tarjeta bancaria, sufriendo constantes amenazas de muerte así como de quitarle sus hijos si intentaba escapar de esa situación. la asistencia recibida por parte de los agregados de interior de la policía desplegados en el extranjero ha posibilitado el regreso a españa de las mujeres junto con sus hijos. en el primer caso, se trata de una mujer y su hija menor de 4 años, ambas españolas con residencia en la ciudad palestina de hebrón. la víctima, casada con un ciudadano palestino desde 2017, sufría malos tratos. así lo reveló cuando contactó con el consulado general de españa en jerusalén el pasado 10 de enero manifestó su pretensión de huir a nuestro país con su hija por la situación de reclusión que padecía desde hacía un año en casa de sus suegros, con agresiones físicas por parte de su marido, sin libertad de movimientos y con privación de alimentos y recursos económicos. la mujer había comunicado estos hechos a la policía local de hebrón, si bien no obtuvo una solución a la situación sufrida y tampoco quería denunciarlos pues, aparte de por su integridad, temía que la validez del permiso que su marido le había firmado, autorizándola para viajar a españa con la niña, se viera comprometida y pudieran quitarle a la menor. gracias a las gestiones realizadas por el consulado general de españa en jerusalén con las autoridades israelíes, se consiguieron acelerar y obtener los permisos necesarios para que madre e hija volaran a españa. para ello resultaron imprescindibles las urgentes gestiones realizadas en el ámbito administrativo por los miembros de la diplomacia española en israel, pero también las labores de apoyo y asesoramiento a la víctima, quien ha manifestado su intención de denunciar lo ocurrido ante las autoridades españolas. en otra actuación realizada, en esta ocasión en colaboración con las autoridades de la república checa y con la embajada de españa en ese país, se ha logrado la repatriación de una mujer española que, presuntamente, estaba siendo maltratada por su pareja. junto a ella, también han sido repatriados sus dos hijos, ambos menores de edad. las investigaciones policiales comenzaron cuando se tuvo conocimiento del presunto maltrato sufrido por una mujer, de nacionalidad española, pareja de un individuo checo con el que residía en praga junto a sus dos hijos, de tres y un año de edad. esa información incluía un parte médico en el que constaba que la víctima había sido atendida por una agresión reiterada por parte de su novio, presentando hinchazón en ambos labios, dolores en la cabeza, espalda y piernas. el padre de la víctima, al tener conocimiento de estos hechos, se puso en contacto con la embajada de españa en praga para informarles del maltrato físico y psicológico que estaba viviendo su hija, así como que se encontraba privada de libertad de movimientos. además, les hizo constar que temía por su vida y la de sus nietos. </td> </tr> </tbody> </table> --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # TF-IDF Utilizaremos una metodología llamada TF-IDF para enriquecer la descripción de los textos -- *Term frequency* - *Inverse document frequency* Un *token* es importante cuando: - Aparece muchas veces en un texto - Se repite poco a través de los documentos -- ```r tfidf <- dfm2 %>% dfm_tfidf() ``` ``` ## Document-feature matrix of: 3 documents, 5 features (66.67% sparse) and 0 docvars. ## features ## docs fiscalía anticorrupción expresidentes madrileños alberto ## text1 7.896018 1.664508 2.360059 1.406763 1.254715 ## text2 0 0 0 0 0 ## text3 0 0 0 0 0 ``` --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Recuperando información Utilizamos similitud coseno para comparar todos los ~~vectores~~ textos entre sí La similitud coseno se mueve entre 0 y 1 `\(cos(\theta) = \frac{A \cdot B}{||A|| ||B||} = \frac{\sum_{i=1}^{n}A_i B_i}{\sqrt{\sum_{i=1}^nA_i^2 \cdot \sum_{i=1}^nB_i^2 } }\)` [Aquí](https://en.wikipedia.org/wiki/Cosine_similarity) encontrarán una definición formal -- ```r distancia <- textstat_simil(tfidf, method = "cosine") dim(distancia) ``` ``` ## [1] 11685 11685 ``` ```r distancia[1:5, 1:5] ``` ``` ## 5 x 5 Matrix of class "dspMatrix" ## text1 text2 text3 text4 text5 ## text1 1.000000000 0.005608309 0.016062859 0.01338767 0.007175373 ## text2 0.005608309 1.000000000 0.015767383 0.01669805 0.004827845 ## text3 0.016062859 0.015767383 1.000000000 0.02180083 0.008654448 ## text4 0.013387671 0.016698052 0.021800829 1.00000000 0.029476244 ## text5 0.007175373 0.004827845 0.008654448 0.02947624 1.000000000 ``` --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Recuperando información ```r sort(distancia[3, ], decreasing = T)[2:4] ``` ``` ## text627 text8264 text1328 ## 0.1825487 0.1666291 0.1501620 ``` ```r most_similar <- corpus[627] similar_df <- data.frame(texto = most_similar) ``` -- <table> <thead> <tr> <th style="text-align:left;"> </th> <th style="text-align:left;"> texto </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> text627 </td> <td style="text-align:left;"> rosa, laura, marta y ana. ellas también han sufrido violencia de género. pero hasta hoy han estado silenciadas. son solo un reflejo de las 305.271 mujeres que han sufrido violencia psicológica entre 2015 y 2019. sus dolorosos testimonios no cuentan con un altavoz público, ni tampoco con un respaldo tan mediático y político como el que ha recibido rocío carrasco tras reconocer que había sufrido maltrato psicológico por parte de su ex marido, antonio david flores. síndrome de que no cuentan con apoyo es que hablan con la razón con pseudónimos y, por supuesto, sin ofrecer su imagen. es el miedo y el pánico al que se enfrentan cada día el que las impide fotografiarse. el temor al que su maltratador continúe impidiéndolas vivir dignamente cuando tratan de reconfigurar sus vidas rotas.cultura.rocioterapia malos tratos, malas artes, malas prácticasel caso de rocío carrasco ha abierto, sin embargo, una ventana de esperanza entre las mujeres víctimas de violencia de género. así lo constatan varias asociaciones como ana bella o alma, que reconocen a la razón que desde que se dio a conocer su testimonio no han parado de recibir llamadas de luchadoras que se atreven tímidamente a contar sus vivencias. precisamente el caso de la hija de rocío jurado se ha encontrado con el apoyo de parte de la esfera política. destaca la ministra de igualdad irene montero que la ha dado su apoyo públicamente. sin embargo, miles de mujeres continúan a día de hoy invisibilizadas. esta es la historia de mujeres valientes que se han visto reflejadas en el relato de rocío carrasco, pero careciendo del apoyo social que ella si tiene.el testimonio de rosa es desolador. su maltratador ya ha muerto, nos cuenta. "es un alivio aunque parezca horrible, pero es importante que se vaya ese hijo de puta". "doy gracias a que ha muerto, pero me ha dejado unas cicatrices a mi y a mi hijo de por vida". pero esto no se soluciona con su muerte, porque el maltratador se encarga de que tu vida sea una mierda hasta que te mueres", comenta angustiada. rosa llegó a tratar de suicidarse la primera vez que denunció a su maltratador. incide en la importancia de llamar maltratador a su ex pareja. "es lo que es". antes ya había sufrido malos tratos, incluso con su bebé en sus entrañas. pero lo más duro para ella llegaría una vez que separó. "el problema llega entonces, a los niños no se les considera víctimas y el maltratador tiene derecho a ver a sus hijos. él pegaba a mi hijo y cuando regresaba de casa de su padre me insultaba. mi hijo me llamaba borracha, mala madre... este es el modus operandi de un maltratador", explica. mi hijo está diagnosticado como un enfermo mental y ahora estoy tratando de trabajar con él, de resetearle, pero es muy difícil recuperarle". nos pide que reflejemos que "es importante que la ley cambie para que el maltratador no tenga visitas ni la patria potestad de los hijos. así como que a los hijos de víctimas de violencia machista no se les ponga el adjetivo de enfermos mentales".laura se siente totalmente identificada con el caso de rocío carrasco, pero pide visibilidad para todas. "hay cuarenta mil rocíitos, cuarenta mil lauras, o carmenes...". denuncia el abandono que siente por parte de la justicia. se confiesa desamparada. ella ha sufrido maltrato psicológico y pide conciencia social porque "al igual que hay una economía sumergida, hay un maltrato sumergido. el psicológico no se ve. parece que como no te han dejado la cara morada, nadie te cree". de hecho, asegura que su abogada le quitó de la cabeza esa denuncia por lo difícil que es de demostrar. si durante el matrimonio sufrió este maltrato ahora sufre el económico. "me llegó a decir que para pagarme un sueldo a mí, se quedaba él con la custodia del niño y así le pagaba yo, como si la manutención fuese un dinero para mí y no para el pequeño y para sus necesidades", lamenta. ahora, el supremo ha reconocido el maltrato económico y tiene algo de esperanza. "me debe 50.000 euros en manutención".marta se siente invisibilizada. "no podemos hablar porque no nos apoya nadie". es por eso que el caso de rocío cree que es una ventana. "llevamos sufriendo años y no podemos hablar de esto. no es justo no recibir un euro para mis hijos de mi maltratador ni de las instituciones", dice. "a diferencia de rocío yo no puedo hablar ni contar mi dolor". su marido no la pegaba, pero el maltrato psicológico era constante. "él quería que estuviese encerrada en casa, me decía que ropa me debía poner y hasta me exigió que dejase mi trabajo porque no ganaba mucho dinero". el problema fue cuando dio a luz a su hijo, relata. "cuando nos separamos y le tocaba ir a su casa, le tenía encerrado en su habitación. trató de ponerle en mi contra. me dijo que iba a conseguir que mi hijo me odiase. le manipuló. consiguió que mi propio hijo me denunciara por malos tratos falsos. mi hijo me llamaba puta, mala madre. imagínate cuando la guardia civil me llega y me dice que estaba denunciada por mi hijo. fue el peor día de mi vida", relata.ana se siente agotada y cansada. cree que nadie entiende a las mujeres supervivientes como ella. ha sufrido maltrato físico y psicológico, pero lo peor es la perdida de su hija y la "manipulación" de su ex. lleva seis años sin ver a su hija, a pesar de tener la guarda y custodia y resoluciones de la audiencia provincial que reconocen que el padre tiene que entregarle a su hija.fue maltratada físicamente durante el matrimonio. "mi ex me sacó de la cama a rastras de lso pelos con una mano y en la otra tenía un cuchillo enorme de carnicero. lo hizo delante de mi hija". lo denunció, pero asegura que la jueza no quiso escucharla. pero el peor maltrato, lamenta, es al que ha sometido a su hija. los padres, coinciden todos los testimonios, tratan de hacer daño a las mujeres con sus hijos menores. "envenenó su mente hasta conseguir que me odiara para apartarla completamente de mi vida". pone el punto de atención en ello. denuncia que no existen leyes que "penalicen la manipulación de los padres maltratadores".cuenta, también, cómo transcurrió su matrimonio. tras casarse vio que algo no iba bien. "no podía hablar con nadie por la calle. un hola o un adiós provocaba una discusión enorme. era celoso, controlador y posesivo. no podía depilarme, ni ducharme en casa porque pensaba que me iba a ir con otro hombre. tenía que ducharme en el trabajo. si me lavaba los dientes para ir al médico, decía que me quería ligar al médico y si me arreglaba para ir a una reunión con los profesores de mi hija, igual. cuando entraba con las niñas en casa, las preguntaba con quién había hablado mamá en el parque. llegó un momento que mis hijas estaban tan aleccionadas que nada más entrar por la puerta le contaban con quién hablaba en la calle. lo más normal es que si vas al parque con tus hijas te relaciones con los demás padres y madres. cuando iba a la piscina con las niñas, decía que me ponía el bañador para ligar con hombres. así era todo". </td> </tr> </tbody> </table> --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # ¿Qué otras cosas puedo hacer? Clasificador de textos Algoritmos no supervisados (k-means) -- **Desventajas** - No escala bien en corpus realmente grandes - No captura bien la semántica de las palabras -- ### Un ejemplo *lindo perro* *bonito can* En un enfoque TF-IDF ambos vectores tendrían similitud coseno = 0 -- ### Necesitamos algo que capture el significado de las palabras --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Word embeddings ¿Qué tal si tuviéramos un vector para representar cada palabra? -- ¿Qué tal si esos vectores capturaran el significado de la palabra? .center[ <img src="https://media.giphy.com/media/UP9ItQNj52DsM3e29m/giphy.gif" width="200" /> ] -- .center[ ### Existe algo llamado *Word embeddings* ] --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # ¿Qué es *word embeddings*? Cualquier mecanismo que permita convertir palabras en vectores -- **Idea clave**: El significado de una palabra está dada por su contexto -- La palabra **nación** está más cerca semánticamente a **país** que la palabra **hipopótamo** -- La palabra **animal** está asociada a la palabra **hipopótamo** -- No es tan común que la palabra **nación** esté cerca de **animal** -- Para un humano esto es trivial, pero para un computador es muy difícil -- Podemos entrenar a una red neuronal para que aprenda vectores de palabras --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Artículo clave (Mikolov et al, 2013) Efficient Estimation of Word Representations in Vector Space .center[ <img src="imagenes/mikolov.png" width="700" /> ] --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Ejemplo word embeddings .panelset[ .panel[.panel-name[spacy] Vamos a cargar vectores de una librería de python llamada [spacy](https://spacy.io/) **IMPORTANTE: Esta parte será más difícil de replicar** Tendremos que usar algunas librerías de Python Utilizaremos reticulate para articular ambos lenguajes .center[ <img src="imagenes/reticulate.png" width="400" /> ] ] .panel[.panel-name[código] **Activamos un ambiente virtual llamado taller-nlp** **Instalamos librerías en el ambiente virtual** ```r library(reticulate) virtualenv_create("taller-nlp") # crear un ambiente virtual use_virtualenv("taller-nlp") # activar un ambiente espećifico virtualenv_install("taller-nlp", "spacy") # instalar spacy virtualenv_install("taller-nlp", "es_core_news_sm") # descargar modelo con 96 dimensiones spacy <- reticulate::import("spacy") # cargar spacy en R nlp = spacy$load("es_core_news_sm") # cargar modelo pequeño con 96 dimensiones doc = nlp("limón pera manzana sandía melón rojo azul amarillo verde perro gato ratón tigre elefante") # Crear vectores para cada una de las palabras indices <- 0:(length(doc) - 1) vectores <- map(indices, ~doc[.x]$vector ) %>% map(poner_nombres) %>% bind_rows() ``` ] .panel[.panel-name[plot1] <img src="nlp_files/figure-html/pca-1.png" style="display: block; margin: auto;" /> ] .panel[.panel-name[plot2]
] ] --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Ejemplo word embeddings ## En lo que queda del taller haremos 2 cosas: -- ### Utilizar los vectores de *spacy* para procesar las noticias ### Crearemos nuestros propios vectores --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Usando los vectores de spacy **Plan:** 1. Separar todas las noticias en oraciones 2. Convertir las oraciones en vectores 3. Buscar algunos tópicos -- ```r # Oraciones editadas oraciones_editadas <- map(corpus, ~split_and_edit(.x ) ) %>% flatten() # Sin editar oraciones <- map(corpus, ~split_text(.x)) %>% flatten() ``` <table class="table" style="margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> oraciones </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> fiscalía anticorrupción eximido expresidentes madrileños alberto ruizgallardón ignacio gonzález responsabilidad penal compra presuntamente fraudulenta 2001 73 millones dólares empresa colombiana inassa parte canal isabel ii operación investiga caso lezo </td> </tr> <tr> <td style="text-align:left;"> escrito 12 páginas dirigido juez caso manuel garcía castellón fiscalía pide levante imputación pieza lezo 15 personas destacan gallardón gónzalez edmundo rodríguez sobrino considerado hombre fuerte gonzález negocios canal isabel ii latinoamérica quedar acreditado conocieran pormenores compra </td> </tr> </tbody> </table> --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Usando los vectores de spacy ```r # Eliminamos las oraciones sin tokens texto_vacio <- oraciones_editadas == "" oraciones_editadas <- oraciones_editadas[!texto_vacio] oraciones <- oraciones[!texto_vacio] ``` -- Haremos una muestra de 50.000 oraciones ```r set.seed(123) vector_muestra <- sample(x = 1:length(oraciones_editadas), 50000, replace = FALSE) oraciones_muestra <- oraciones_editadas[vector_muestra] oraciones_muestra_originales <- oraciones[vector_muestra] ``` -- La función `create_representation` convierte cada texto en un vector **Advertencia**: Este proceso puede tomar varios minutos ```r representations <- map(oraciones_muestra, create_representation) saveRDS(representations, "data/vector_representation_sample.rds") ``` -- #### Cargamos un archivo generado previamente ```r representations <- readRDS("data/vector_representation_sample.rds") print(representations[[1]][1] %>% unlist() %>% unname() %>% as.numeric()) ``` ``` ## [1] 1.139919670 1.289339807 -0.128935099 -1.379759598 0.174692698 ## [6] -0.509138841 -0.524521551 0.411224611 0.341409042 1.877448312 ## [11] 0.782376922 1.331240764 0.644728548 1.520211141 -0.512923195 ## [16] -1.391019246 1.021650749 0.893471112 -0.435116853 0.553371108 ## [21] -0.115867688 0.689281693 -0.638476541 -0.760966843 -0.526615042 ## [26] -0.522461856 0.721628436 0.359893376 -0.102418550 -0.098304266 ## [31] 0.268467416 0.449801772 0.467579763 -0.285095381 -0.067268470 ## [36] -0.402456694 -0.005299338 -0.447044349 1.512449630 0.339841221 ## [41] -0.573713461 1.663113077 -0.911665394 -0.856908688 -0.360334539 ## [46] 0.575334023 -0.616553461 -1.483858102 -0.908884239 0.435200838 ## [51] 1.303202680 -0.456058881 0.097785877 0.994705701 -0.745942887 ## [56] -0.853211344 0.183352376 -0.816818849 -1.205018152 0.897614222 ## [61] -0.987591564 1.162236152 -0.008950191 -0.126133801 -0.117885859 ## [66] 0.837914278 -1.882425516 -0.839670006 -0.847946147 -0.066498724 ## [71] 0.776539246 0.159901995 -0.078661843 0.749105386 -0.373677107 ## [76] 0.277381615 0.646791116 0.107197040 0.154915800 0.461926916 ## [81] -1.691129226 -0.503389231 -0.860755775 0.070191535 0.591613834 ## [86] 0.527795393 0.945032694 -0.562836929 0.956919684 0.121713771 ## [91] -1.568386391 -0.532285106 -0.001306802 1.689390579 0.071362297 ## [96] -0.189145903 -0.016042809 -0.636240780 -0.660900885 1.316920418 ## [101] 1.852979674 0.073608573 -0.598664503 -0.402555652 0.495894188 ## [106] -0.553617401 -0.013354999 -0.401857893 -0.114604999 1.259340768 ## [111] -1.528421165 -0.246771930 -0.753947473 -0.785872321 1.925523295 ## [116] -0.322690840 0.979453213 1.352302297 -1.096141837 -0.786463036 ## [121] -0.174083768 0.272843469 -0.873476151 0.235544647 0.402861275 ## [126] 1.197995850 0.801220787 0.588521450 2.476546128 0.138759244 ## [131] -0.570789574 0.134679306 0.479152154 -0.326155028 -0.451707573 ## [136] 0.420432058 1.099399604 0.796346508 0.420314597 -0.176589741 ## [141] -0.465591336 0.240054233 0.265529150 -0.620474242 1.293778079 ## [146] -0.259883584 -0.197315650 -0.242692857 -1.249765008 -0.984510760 ## [151] -1.651516909 -0.360202695 -1.002244615 1.116015588 -0.487756233 ## [156] -0.093120386 -1.363606467 -0.479004072 -0.117705617 1.139198477 ## [161] 0.234919222 0.317801953 0.006369452 -0.048321762 1.468489606 ## [166] -0.162936095 -1.258012643 -0.935303454 1.333597526 -1.519104990 ## [171] 0.329801145 -0.516136844 0.820350780 -0.844481928 1.380706398 ## [176] -0.194940263 -0.478232650 0.496373848 0.055901047 -0.324423750 ## [181] -0.133272911 1.379731313 0.372400770 0.021848849 -1.174655163 ## [186] 0.511842617 -0.090975403 0.401816474 -1.983635782 -0.161104992 ## [191] 1.828295704 0.384768353 -0.126070773 0.865673287 -0.659590690 ## [196] -1.134946534 -0.031413469 0.981060989 0.251061235 0.279376020 ## [201] -0.118618843 -1.073552443 -0.637313264 -0.940124108 0.068161925 ## [206] -0.322480609 0.241098610 0.305767846 0.183568846 0.824646910 ## [211] -1.141235779 1.191647346 0.479023255 1.060829998 -1.006085511 ## [216] 1.197383883 0.802626281 -0.772380012 -0.687731543 -0.206547461 ## [221] -1.122424999 -0.335745264 0.270443737 -0.017495917 0.212785774 ## [226] 0.457935533 0.766541894 0.693851346 -0.572609488 0.790113573 ## [231] -0.891154636 0.251065777 0.174725697 0.799342728 -0.252178566 ## [236] -0.214606909 0.107325468 0.745764628 0.781002682 -0.320886025 ## [241] -0.386107077 -0.398534117 -0.598896910 -0.171461158 -1.532684918 ## [246] 0.076325384 0.093970454 1.168520844 -0.392876306 0.086863078 ## [251] 1.087116151 0.645157726 -0.799292203 1.623713084 1.068396527 ## [256] 0.801820803 -0.690354150 -0.279137031 1.682411894 0.153046842 ## [261] 0.258236301 -1.414424053 -0.540846088 -0.249991934 0.884931273 ## [266] -1.067299217 0.817381152 1.173865103 0.147331212 -0.268115643 ## [271] 0.683509779 0.656455043 0.913223449 -1.046181499 0.183390578 ## [276] 0.241420378 -0.119874327 1.159959076 -0.163113383 -1.121313228 ## [281] 0.125421004 -0.240633877 -0.838153087 0.675397185 0.339872622 ## [286] 0.511369228 0.540725764 0.042450390 -0.575473854 0.568348083 ## [291] 0.494606756 0.178952331 -0.674394849 0.667927437 0.388159345 ## [296] -0.674171537 1.015108843 0.580292886 -0.064776377 -0.941601265 ``` ```r print(representations[[1]][2]) ``` ``` ## [[1]] ## [1] "psoe unidas podemos diferencia casi partidos presentado aún lista comparecientes formación morada restado importancia excomisario josé manuel villarejo declare comisión línea psoe venido sosteniendo ser cuestionado asunto" ``` --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Usando los vectores de spacy ### Un poco de procesamiento de datos ```r # Agregar oraciones originales a la lista representations <- map2(oraciones_muestra_originales, representations, ~append(.y, .x)) # Eliminar textos sin representación y con menos de 4 palabras representations2 <- representations %>% keep(~!is_empty(.x[[1]])) %>% keep(~.x[3] > 4) # Guardamos los vectores vectores <- representations2 %>% map(1) %>% map(~unlist(unname(.x))) # Guardamos las oraciones editadas textos <- representations2 %>% map(2) # Guardamos las oraciones editadas textos_originales <- representations2 %>% map(4) ``` --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Buscando oraciones ```r encontrar_mas_parecidos(vectores, "elecciones congreso nacional", 5, lista_textos = textos_originales) encontrar_mas_parecidos(vectores, "crecimiento económico", 5, lista_textos = textos_originales) encontrar_mas_parecidos(vectores, "inmigrantes musulmanes", 5, lista_textos = textos_originales) encontrar_mas_parecidos(vectores, "desigualdad económica", 5, lista_textos = textos_originales) encontrar_mas_parecidos(vectores, "ministerio sanidad", lista_textos = textos_originales) encontrar_mas_parecidos(vectores, "inflación", 5, lista_textos = textos_originales) encontrar_mas_parecidos(vectores, "terrorismo", 5, lista_textos = textos_originales) encontrar_mas_parecidos(vectores, "violencia género", 5, lista_textos = textos_originales) ``` .panelset[ .panel[.panel-name[elecciones] <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> oraciones </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> en las elecciones generales españolas el congreso de los diputados se elige provincia a provincia </td> </tr> <tr> <td style="text-align:left;"> en las primarias del partido para ratificar los candidatos al congreso también fue uno de los primeros </td> </tr> <tr> <td style="text-align:left;"> el candidato socialista a la presidencia del gobierno, pedro sánchez, presentará este lunes el programa electoral del psoe de cara a las elecciones generales del 10 de noviembre, y será el compromiso programático más progresista presentado por el líder socialistas en las cuatro elecciones a las que se ha concurrido como cabeza de lista de su partido, al asumir íntegramente la propuesta que hizo en septiembre a unidas podemos </td> </tr> <tr> <td style="text-align:left;"> el portavoz nacional de ciudadanos, edmundo bal, ha sido elegido en las primarias de la formación naranja como candidato a las elecciones del 4 de mayo en la comunidad de madrid, con el voto del 89,43% de los afiliados del partido </td> </tr> <tr> <td style="text-align:left;"> la imposición de beitia como candidata a las elecciones autonómicas por parte de génova devuelve al pp cántabro a la crisis derivada del congreso regional celebrado en marzo de 2017, en el que sáenz de buruaga fue elegida presidenta de la formación en cantabria por solo cuatro votos más que el expresidente conservador y del gobierno de cantabria, ignacio diego </td> </tr> </tbody> </table> ] .panel[.panel-name[crecimiento] <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> oraciones </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> entre los retos apremiantes apunta la necesidad de aumentar la productividad incrementando la inversión pública y privada en capital humano y tecnológico revisar el modelo educativo, y favorecer el crecimiento y el dinamismo empresarial </td> </tr> <tr> <td style="text-align:left;"> los principales portales inmobiliarios ven una reducción del ritmo de crecimiento de las compraventas de viviendas por la incertidumbre derivada de las elecciones y la moderación del crecimiento de la economía </td> </tr> <tr> <td style="text-align:left;"> “en ningún momento se plantea –concluyen- un cambio de modelo de crecimiento económico basado en el aprovechamiento de las capacidades intelectuales y competencias de las personas jóvenes, junto con políticas de crecimiento económico centradas en una política industrial, en la innovación y la investigación, que sí debería haber conformado el diseño de un nuevo modelo de políticas activas de empleo” </td> </tr> <tr> <td style="text-align:left;"> ello implica dar pasos para impulsar el crecimiento a largo plazo, reducir la deuda donde sea demasiado elevada y en otros países invertir en la economía a través de la infraestructura y un gasto social eficiente, opinó </td> </tr> <tr> <td style="text-align:left;"> en cualquier caso, la economista del fmi afirma que un gasto social más efectivo "no puede ser la única herramienta para elevar el nivel de vida y reducir la desigualdad" en españa, por lo que recomienda acometer reformas del mercado laboral para hacerlo "más inclusivo", abordando la alta proporción de empleo temporal, que se asocia con un bajo crecimiento de la productividad y una creciente desigualdad de ingresos </td> </tr> </tbody> </table> ] .panel[.panel-name[inmigrantes] <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> oraciones </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> ustedes además están extorsionando a los españoles, están culpando a los españoles que creen en la legítima defensa de sus fronteras de las muertes de africanos en el mediterráneo </td> </tr> <tr> <td style="text-align:left;"> estos hechos tienen consecuencias terribles sobre sectores de la población más vulnerables, como son las mujeres jóvenes, las que son madres solteras y las inmigrantes </td> </tr> <tr> <td style="text-align:left;"> "además, los ataques en el sur de europa han apuntado históricamente a opositores políticos -especialmente antifascistas-, más que a minorías étnicas o religiosas", añade </td> </tr> <tr> <td style="text-align:left;"> de hecho, coalición canaria-pnc denunció ayer la decisión de madrid de convertir canarias en una cárcel para los inmigrantes siguiendo el ejemplo de otros países europeos de concentrar los inmigrantes en puntos alejados del continente como lesbos o lampedusa </td> </tr> <tr> <td style="text-align:left;"> el historiador madrileño señala en su estudio que se enrola en la columna uribes, "integrada por soldados, guardias civiles y milicianos voluntarios, la mayoría de ellos simpatizantes socialistas y comunistas" </td> </tr> </tbody> </table> ] .panel[.panel-name[desigualdad] <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> oraciones </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> la adopción unilateral del euro conlleva una pérdida de autonomía en algunas cuestiones de política económica </td> </tr> <tr> <td style="text-align:left;"> el multilateralismo, continuó, "es la única herramienta para dar solución" a los principales desafíos a los que se enfrenta la humanidad "el hambre, la emergencia climática, la revolución digital, la desigualdad económica y social, la violencia de la guerra y la discriminación" </td> </tr> <tr> <td style="text-align:left;"> asimismo, ha reconocido la creciente desigualdad económica, especialmente en el seno de los países avanzados, y advertido de que puede afectar a la "cohesión social" y la polarización política dentro del ascenso de los populismos </td> </tr> <tr> <td style="text-align:left;"> madrid es rica, pero también es desigual y destaca por sus escasas políticas sociales y de redistribución de renta, lo que ha acentuado la brecha social </td> </tr> <tr> <td style="text-align:left;"> la pandemia de covid-19 ha afectado económicamente de forma desproporcionada a las mujeres en contraste con el resto de la población, hasta el punto de borrar décadas de progreso en materia de emancipación económica y brecha salarial </td> </tr> </tbody> </table> ] .panel[.panel-name[sanidad] <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> oraciones </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> el viceconsejero de salud pública y plan covid-19 de la comunidad de madrid, antonio zapatero, ya anunció el viernes que aplicarían los cierres pero presentarían un recurso ante la justicia al entender que "jurídicamente" el ministerio de sanidad no puede "imponer" el acuerdo del consejo interterritorial del sistema nacional de salud </td> </tr> <tr> <td style="text-align:left;"> en este sentido, la consejería de sanidad y servicios sociales ha publicado una resolución con los distintos niveles de alerta sanitaria y las medidas generales de prevención e intervención administrativas en materia de salud pública ante la crisis de la covid-19 </td> </tr> <tr> <td style="text-align:left;"> en este sentido, la consejería de sanidad y servicios sociales ha publicado una resolución con los distintos niveles de alerta sanitaria y las medidas generales de prevención e intervención administrativas en materia de salud pública ante la crisis de la covid-19 </td> </tr> <tr> <td style="text-align:left;"> en este sentido, la consejería de sanidad y servicios sociales ha publicado una resolución con los distintos niveles de alerta sanitaria y las medidas generales de prevención e intervención administrativas en materia de salud pública ante la crisis de la covid-19 </td> </tr> <tr> <td style="text-align:left;"> en este sentido, la consejería de sanidad y servicios sociales ha publicado una resolución con los distintos niveles de alerta sanitaria y las medidas generales de prevención e intervención administrativas en materia de salud pública ante la crisis de la covid-19 </td> </tr> </tbody> </table> ] .panel[.panel-name[inflación] <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> oraciones </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> con este dato, la inflación interanual encadena su octava tasa negativa consecutiva </td> </tr> <tr> <td style="text-align:left;"> el presidente del bce indicó que esperan que la inflación subyacente -que mide la evolución de los precios de consumo excluyendo los de alimentos y energía- "aumente más en los próximos meses conforme el endurecimiento del mercado de trabajo eleva los salarios" </td> </tr> <tr> <td style="text-align:left;"> el ligero incremento de la deuda en julio se debe al aumento del endeudamiento en el área de otras unidades de la administración central y mínimamente en la seguridad social, que han tenido que hacer un esfuerzo extra de gasto debido al impacto de la crisis del coronavirus, como consecuencia del establecimiento del estado de alarma el 14 de marzo y los reales decretos aprobados para paliar la crisis </td> </tr> <tr> <td style="text-align:left;"> las propias fuentes fueron unánimes en creer que era poco probable que la aportación del público influyera en las deliberaciones sobre cómo reajustar la definición de estabilidad de precios del bce, actualmente fijada en un tasa de inflación "inferior, pero cercana al 2%" </td> </tr> <tr> <td style="text-align:left;"> asimismo, en referencia a la evaluación estratégica que está llevando a cabo la institución, incluyendo la revisión de su definición de estabilidad de precios, la francesa ha expresado el deseo de la entidad de alcanzar un grado de claridad y predecibilidad en el objetivo de inflación, aunque ha advertido de que, a pesar de los bajos niveles de precios registrados en la zona euro en los últimos años, "no se debe descartar la inflación" </td> </tr> </tbody> </table> ] .panel[.panel-name[terrorismo] <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> oraciones </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> morir por nadano es mi intención establecer un paralelismo entre los aborrecibles crímenes perpetrados por el régimen nazi con lo vivido en la sociedad vasca y española con el terrorismo de eta </td> </tr> <tr> <td style="text-align:left;"> como presunto autor de los delitos de proposición (conspiración) para asesinato terrorista e integración en organización terrorista </td> </tr> <tr> <td style="text-align:left;"> com torhni7jnqen el vídeo, el partido denuncia que la "islamización perpetrada por el separatismo ha convertido cataluña en un peligroso refugio para los yihadistas y el fundamentalismo islámico" </td> </tr> <tr> <td style="text-align:left;"> "no es lo mismo la apología del terrorismo cuando eta estaba activa y la apología podía contribuir a la comisión de crímenes que en la actualidad, que eta ya no mata </td> </tr> <tr> <td style="text-align:left;"> en ese estudio se aludía igualmente a lo que señalaba como componentes ideológicos de la ultraderecha el racismo, las posiciones contra la inmigración, el nacionalismo, el fascismo, el machismo y la xenofobia </td> </tr> </tbody> </table> ] .panel[.panel-name[género] <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> oraciones </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> teléfono de atención a víctimas de violencia de género </td> </tr> <tr> <td style="text-align:left;"> con referencias a los últimos asesinatos machistas sucedidos en el país valenciano, puig ha considerado el drama de la violencia de género como el principal problema de nuestros tiempos y ha asegurado que, en caso de prosperar la investidura, convocará el pacto contra la violencia de género para intensificar el combate contra el machismo </td> </tr> <tr> <td style="text-align:left;"> ni en igualdad ni en violencia de género ni en los temas lgtbi, el iam no ha compartido ni comparte </td> </tr> <tr> <td style="text-align:left;"> “la violencia sexual ejercida contra las mujeres es una de las múltiples expresiones de las violencias machistas </td> </tr> <tr> <td style="text-align:left;"> el pasado mes de noviembre, la ley cántabra de garantía de derechos de las personas lesbianas, gais, trans, transgénero, bisexuales e intersexuales y no discriminación por razón de orientación sexual e identidad de género reconocía la libertad de autodeterminación de género de las personas que manifiesten una identidad sexual o identidad de género distinta a la asignada al nacer </td> </tr> </tbody> </table> ] ] --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Creando nuestros propios vectores -- ### Usamos nuestras noticias para crear embeddings ```r library(word2vec) x <- data$cuerpo # noticias # Generar embeddings de 300 dimensiones model <- word2vec(x = x, dim = 300, iter = 20, min_count = 5, threads = 16) # Crear una matriz embedding <- as.matrix(model) # Buscar palabras más cercanas lookslike <- predict(model, c("democracia", "violencia", "presidente", "dictadura", "rojo", "rey"), type = "nearest", top_n = 5) ``` <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> term1 </th> <th style="text-align:left;"> term2 </th> <th style="text-align:right;"> similarity </th> <th style="text-align:right;"> rank </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> inmigración </td> <td style="text-align:left;"> migración </td> <td style="text-align:right;"> 0.8002769 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> inmigración </td> <td style="text-align:left;"> migratoria </td> <td style="text-align:right;"> 0.7199104 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> inmigración </td> <td style="text-align:left;"> okupación </td> <td style="text-align:right;"> 0.6985853 </td> <td style="text-align:right;"> 3 </td> </tr> <tr> <td style="text-align:left;"> inmigración </td> <td style="text-align:left;"> emigración </td> <td style="text-align:right;"> 0.6863262 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> inmigración </td> <td style="text-align:left;"> despoblación </td> <td style="text-align:right;"> 0.6577292 </td> <td style="text-align:right;"> 5 </td> </tr> <tr> <td style="text-align:left;"> democracia </td> <td style="text-align:left;"> monarquía </td> <td style="text-align:right;"> 0.7462538 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> democracia </td> <td style="text-align:left;"> democracia» </td> <td style="text-align:right;"> 0.7438202 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> democracia </td> <td style="text-align:left;"> nación </td> <td style="text-align:right;"> 0.7405679 </td> <td style="text-align:right;"> 3 </td> </tr> <tr> <td style="text-align:left;"> democracia </td> <td style="text-align:left;"> constitución </td> <td style="text-align:right;"> 0.7263938 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> democracia </td> <td style="text-align:left;"> democracia” </td> <td style="text-align:right;"> 0.6982266 </td> <td style="text-align:right;"> 5 </td> </tr> <tr> <td style="text-align:left;"> violencia </td> <td style="text-align:left;"> represión </td> <td style="text-align:right;"> 0.7380143 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> violencia </td> <td style="text-align:left;"> frustrado» </td> <td style="text-align:right;"> 0.7190406 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> violencia </td> <td style="text-align:left;"> agresión </td> <td style="text-align:right;"> 0.7072052 </td> <td style="text-align:right;"> 3 </td> </tr> <tr> <td style="text-align:left;"> violencia </td> <td style="text-align:left;"> discriminación </td> <td style="text-align:right;"> 0.7028788 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> violencia </td> <td style="text-align:left;"> “violencia </td> <td style="text-align:right;"> 0.6951622 </td> <td style="text-align:right;"> 5 </td> </tr> <tr> <td style="text-align:left;"> presidente </td> <td style="text-align:left;"> expresidente </td> <td style="text-align:right;"> 0.8568649 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> presidente </td> <td style="text-align:left;"> vicepresidente </td> <td style="text-align:right;"> 0.8288137 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> presidente </td> <td style="text-align:left;"> president </td> <td style="text-align:right;"> 0.8050179 </td> <td style="text-align:right;"> 3 </td> </tr> <tr> <td style="text-align:left;"> presidente </td> <td style="text-align:left;"> líder </td> <td style="text-align:right;"> 0.7841408 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> presidente </td> <td style="text-align:left;"> portavoz </td> <td style="text-align:right;"> 0.7740862 </td> <td style="text-align:right;"> 5 </td> </tr> <tr> <td style="text-align:left;"> dictadura </td> <td style="text-align:left;"> represión </td> <td style="text-align:right;"> 0.7439038 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> dictadura </td> <td style="text-align:left;"> franquismo </td> <td style="text-align:right;"> 0.7357173 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> dictadura </td> <td style="text-align:left;"> posguerra </td> <td style="text-align:right;"> 0.7286432 </td> <td style="text-align:right;"> 3 </td> </tr> <tr> <td style="text-align:left;"> dictadura </td> <td style="text-align:left;"> guerra </td> <td style="text-align:right;"> 0.6935439 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> dictadura </td> <td style="text-align:left;"> sublevación </td> <td style="text-align:right;"> 0.6818935 </td> <td style="text-align:right;"> 5 </td> </tr> <tr> <td style="text-align:left;"> rey </td> <td style="text-align:left;"> monarca </td> <td style="text-align:right;"> 0.8925284 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> rey </td> <td style="text-align:left;"> don </td> <td style="text-align:right;"> 0.6991650 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> rey </td> <td style="text-align:left;"> rey» </td> <td style="text-align:right;"> 0.6871441 </td> <td style="text-align:right;"> 3 </td> </tr> <tr> <td style="text-align:left;"> rey </td> <td style="text-align:left;"> vi </td> <td style="text-align:right;"> 0.6737007 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> rey </td> <td style="text-align:left;"> reyespaña </td> <td style="text-align:right;"> 0.6575770 </td> <td style="text-align:right;"> 5 </td> </tr> </tbody> </table> --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Para terminar ### Retomemos nuestros textos sobre la ETA ### Trataremos de ver si los extractos tienen un "sentimiento" positivo o negativo ### Usaremos un modelo disponible en [huggingface](https://huggingface.co/pysentimiento/robertuito-sentiment-analysis) ### Empresa que pone a disposición *transformers* .center[ <img src="imagenes/huggingface.png" width="400" /> ] --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Huggingface ### Debemos instalar algunas librerías de *python* ```r reticulate::py_install("transformers", pip = TRUE) reticulate::py_install(c("torch", "sentencepiece"), pip = TRUE) ``` -- ### Cargamos la libraría y un modelo entrenado con datos en español ```r transformers <- reticulate::import("transformers") classifier <- transformers$pipeline(task = "text-classification", model = "pysentimiento/robertuito-sentiment-analysis" ) ``` -- ```r text <- c("Es lo mejor que me ha pasado en el último tiempo") classifier(text) ``` ``` ## [[1]] ## [[1]]$label ## [1] "POS" ## ## [[1]]$score ## [1] 0.9454799 ``` ```r text <- c("Es el peor producto que he comprado en mi vida") classifier(text) ``` ``` ## [[1]] ## [[1]]$label ## [1] "NEG" ## ## [[1]]$score ## [1] 0.9817094 ``` --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Datos ETA ```r # Armar dataframe con los primeros 10 extractos data <- data.frame(pre = comentarios_eta$pre, post = comentarios_eta$post ) %>% slice(1:10) %>% mutate(text = paste(pre, post)) %>% select(text) # Predecir sentimiento para cada uno de los textos out <- map(data$text, classifier) # Extraer la etiqueta de cada predicción labels <- flatten(out) %>% map(1) # Extraer probabilidad de cada predicción prob <- flatten(out) %>% map(2) # Añadir columnas a data frame data <- data %>% mutate(sentiment = labels, prob = prob) ``` --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Datos ETA <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> text </th> <th style="text-align:left;"> sentiment </th> <th style="text-align:left;"> prob </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> traición irresponsabilidad justicia merecen todas víctimas terrorismo opinión trata dejar manos cómplices terrorismo vasco </td> <td style="text-align:left;"> NEG </td> <td style="text-align:left;"> 0.955357 </td> </tr> <tr> <td style="text-align:left;"> mataron familiares psoe pnv nunca escribirán historia vencedores vencidos sino solo escribirán relato igualar </td> <td style="text-align:left;"> NEG </td> <td style="text-align:left;"> 0.7863782 </td> </tr> <tr> <td style="text-align:left;"> puede pronunciarse traslados presos política acercamiento reclusos impulsada gobierno situado treintena cárceles vascas competencia </td> <td style="text-align:left;"> NEU </td> <td style="text-align:left;"> 0.8576674 </td> </tr> <tr> <td style="text-align:left;"> balance imposible víctimas conocemos víctimas mortales número exacto heridos secuestrados </td> <td style="text-align:left;"> NEG </td> <td style="text-align:left;"> 0.5703851 </td> </tr> <tr> <td style="text-align:left;"> sacrificio inocentes motivos ideológicos sucediera exterminios nazis buscado medio siglo convertir cenizas niños adolescentes </td> <td style="text-align:left;"> NEG </td> <td style="text-align:left;"> 0.8711603 </td> </tr> <tr> <td style="text-align:left;"> humanidad configura única manera justicia víctimas terrorismo organización fuertemente jerarquizada estructura real dominio hecho </td> <td style="text-align:left;"> NEU </td> <td style="text-align:left;"> 0.7416216 </td> </tr> <tr> <td style="text-align:left;"> mando tan difícil contabilizar número exacto victimas saber número autores cooperadores colaboradores cómplices eta </td> <td style="text-align:left;"> NEG </td> <td style="text-align:left;"> 0.8768867 </td> </tr> <tr> <td style="text-align:left;"> eta saber número autores cooperadores colaboradores cómplices cada atentado cada expulsión forzosa país vasco </td> <td style="text-align:left;"> NEG </td> <td style="text-align:left;"> 0.87582 </td> </tr> <tr> <td style="text-align:left;"> veredicto condena hacía responsables configuraban organigrama poder devolvería sociedad memoria carece anestesia democracia eta </td> <td style="text-align:left;"> NEG </td> <td style="text-align:left;"> 0.5062088 </td> </tr> <tr> <td style="text-align:left;"> eta devolvería sociedad memoria carece anestesia democracia mata continúa sacrificando inocentes ahora olvido precede </td> <td style="text-align:left;"> NEG </td> <td style="text-align:left;"> 0.9067026 </td> </tr> </tbody> </table> --- background-image: url("imagenes/fondo2.PNG") background-size: contain; background-position: 100% 0% # Comentarios al cierre **En el taller revisamos:** - TF-IDF (quanteda) - *Word Embeddings* (spacy) - Clasificador de sentimientos (transformers) -- `R` cuenta con varias herramientas para trabajar con datos de texto -- * Las herramientas más populares en la actualidad están disponibles en *Python* + spacy + transformers + gensim + otras -- - Podemos articular ambos lenguajes a través de `reticulate` --- class: center, middle .linea-superior[] .linea-inferior[] <img src="imagenes/logo_portada2.png" width="200" /> ## INE Educa: Clases abiertas de R ## Proyecto Ciencia de Datos ### Agosto 2023