{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "<figure>\n", "<img src=\"../Imagenes/logo-final-ap.png\" width=\"80\" height=\"80\" align=\"left\"/> \n", "</figure>\n", "\n", "# <span style=\"color:#4361EE\"><left>Aprendizaje Profundo</left></span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "# <span style=\"color:red\"><center>Diplomado en Inteligencia Artificial y Aprendizaje Profundo</center></span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "# <span style=\"color:green\"><center> Técnicas modernas de clasificación de documentos</center></span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "<center>Técnicas word2vec</center>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "<figure>\n", "<center>\n", "<img src=\"../Imagenes/Taxonomy.png\" width=\"400\" height=\"400\" align=\"center\"/>\n", "</center>\n", "</figure>\n", "\n", "<center>Fuente: <a href=\"https://commons.wikimedia.org/wiki/File:Taxonomic_Rank_Graph.svg\">Annina Breen</a>, <a href=\"https://creativecommons.org/licenses/by-sa/4.0\">CC BY-SA 4.0</a>, via Wikimedia Commons</center>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Profesores</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "1. Alvaro Montenegro, PhD, ammontenegrod@unal.edu.co\n", "1. Camilo José Torres Jiménez, Msc, cjtorresj@unal.edu.co\n", "1. Daniel Montenegro, Msc, dextronomo@gmail.com " ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Asesora Medios y Marketing digital</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "4. Maria del Pilar Montenegro, pmontenegro88@gmail.com\n", "5. Jessica López Mejía, jelopezme@unal.edu.co\n", "6. Venus Puertas, vpuertasg@unal.edu.co" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Jefe Jurídica</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "7. Paula Andrea Guzmán, guzmancruz.paula@gmail.com" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Coordinador Jurídico</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "8. David Fuentes, fuentesd065@gmail.com" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Desarrolladores Principales</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "9. Dairo Moreno, damoralesj@unal.edu.co\n", "10. Joan Castro, jocastroc@unal.edu.co\n", "11. Bryan Riveros, briveros@unal.edu.co\n", "12. Rosmer Vargas, rovargasc@unal.edu.co" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Expertos en Bases de Datos</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "13. Giovvani Barrera, udgiovanni@gmail.com\n", "14. Camilo Chitivo, cchitivo@unal.edu.co" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Referencias</span> " ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "1. Adaptado de [deep-learning-methods-for-text-data]((https://towardsdatascience.com/understanding-feature-engineering-part-4-deep-learning-methods-for-text-data-96c44370bbfa))\n", "2. Mikolov et al. 2013a, Google, [Distributed Representations of Words and Phrases\n", "and their Compositionality](https://papers.nips.cc/paper/5021-distributed-representations-of-words-and-phrases-and-their-compositionality.pdf), \n", "3. Xin Rong, 2016, [word2vec Parameter Learning Explained](https://arxiv.org/pdf/1411.2738.pdf), \n", "4. Mikolov et al. 2013b, Google, [Efficient Estimation of Word Representations in Vector Space](https://arxiv.org/pdf/1301.3781.pdf).\n", "5. Baroni et al., 2014,[Don’t count, predict! A systematic comparison of context-counting vs. context-predicting semantic vectors](https://www.aclweb.org/anthology/P14-1023.pdf)." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Contenido</span> " ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "* [Introducción](#Introducción)\n", "* [No cuente, prediga](#No-cuente,-prediga)\n", "* [Sumergimiento o incrustamiento de palabras-word embeddings](#Sumergimiento-o-incrustamiento-de-palabras-word-embeddings)\n", "* [Modelos Word2Vec](#Modelos-Word2Vec)\n", "* [Modelo CBOW](#Modelo-CBOW)\n", "* [Modelo Skip-gram](#Modelo-Skip-gram)\n", "* [Sobre que podemos esperar](#Sobre-que-podemos-esperar)\n", "* [Las tareas linguísticas](#Las-tareas-linguísticas)\n", "* [Recursos linguísticos](#Recursos-linguísticos)\n", "* [Corpus de juguete](#Corpus-de-juguete)\n", "* [Ejemplo The King James version of the Bible](#Ejemplo-The-King-James-Version-of-the-Bible)\n", "* [Pre-procesamiento del texto](#Pre-procesamiento-del-texto)\n", "* [Modelos con Gensim](#Modelos-con-Gensim)\n", "* [Visualización de incrustaciones con TSNE](#Visualización-de-incrustaciones-con-TSNE)\n", "* [Incrustación de documentos](#Incrustación-de-documentos)\n", "* [Modelos pre-entrenados. El modelo Glove](#Modelos-pre-entrenados.-El-modelo-Glove)\n", "* [Introducción a spaCy](#Introducción-a-spaCy)\n", "* [Modelos en Español](Modelos-en-Español)\n", "* [El modelo FastText](#El-modelo-FastText)\n", "* [Modelos-de-incrustaciones-del -Español-Preentrenados](#Modelos-de-incrustaciones-del-Español-Preentrenados)\n", "* [Conclusión](#Conclusión)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Introducción</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Trabajar con datos de texto no estructurados es difícil, especialmente cuando se intenta construir un sistema inteligente que interprete y comprenda el lenguaje natural que fluye libremente al igual que los humanos. \n", "\n", "\n", "Debe poder procesar y transformar datos textuales no estructurados y ruidosos en algunos formatos estructurados y vectorizados que puedan ser entendidos por cualquier algoritmo de aprendizaje automático. \n", "\n", "\n", "Los principios del procesamiento del lenguaje natural, el aprendizaje automático o el aprendizaje profundo, todos los cuales caen bajo el amplio paraguas de la inteligencia artificial, son herramientas eficaces del oficio. \n", "\n", "\n", "Un punto importante para recordar aquí es que cualquier algoritmo de aprendizaje automático se basa en principios de estadística, matemáticas y optimización. \n", "\n", "Por lo tanto, no son lo suficientemente inteligentes como para comenzar a procesar texto en su forma original y sin pre-procesar. \n", "\n", "En esta lección revisamos los métodos más modernos para el descubrimiento de tópicos y clasificación de documentos. Usaremos algunos modelos globales pre-entrenados que se encuentran disponibles libremente.\n", "\n", "Más específicamente, cubriremos el modelos `Word2Vec`, `Glove` y `FasText` y usaremos las herramientas `nltk`, `gensim` y `spacy`.\n", "\n", "En esta lección no usaremos tensorflow.\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">No cuente, prediga</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Para superar las deficiencias de perder la semántica y la escasez de características basadas en el modelo de bolsa de palabras, necesitamos hacer uso de los modelos de espacio vectorial - **Vector Space Models**(VSM) de tal manera que podamos incrustar vectores de palabras en este espacio vectorial continuo basado en semánticas y similitud contextual. \n", "\n", "\n", "De hecho, la *hipótesis distributiva* en el campo de la *semántica distributiva* nos dice que **las palabras que ocurren y se usan en el mismo contexto, son semánticamente similares entre sí y tienen significados similares**. \n", "\n", "\n", "En términos simples, **una palabra se caracteriza por la compañía que mantiene**. ¡Uno de los artículos famosos que habla en detalle sobre estos vectores de palabras semánticas y varios tipos es [Don’t count, predict! A systematic comparison of context-counting vs. context-predicting semantic vectors’ by Baroni et al](https://www.aclweb.org/anthology/P14-1023.pdf), de by Baroni et al.\n", "\n", "\n", "No profundizaremos mucho, pero, en resumen, hay dos tipos principales de métodos para los vectores de palabras contextuales. \n", "\n", "- **Métodos basados en conteo** como el *Análisis semántico latente* (LSA) que se pueden usar para calcular algunas medidas estadísticas de la frecuencia con la que las palabras ocurren con sus palabras vecinas en un corpus y luego construir vectores de palabras densas para cada palabra a partir de estas medidas. \n", "- **Los métodos predictivos**s, como los modelos de lenguaje basados en redes neuronales, intentan predecir palabras a partir de las palabras vecinas observando secuencias de palabras en el corpus y, en el proceso, aprende representaciones distribuidas que nos proporcionan densas incrustaciones de palabras. \n", "\n", "Nos centraremos en estos métodos predictivos en esta lección.\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Sumergimiento o incrustamiento de palabras-word embeddings</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Con respecto a los sistemas de reconocimiento de voz o imágenes, toda la información ya está presente en forma de vectores de características ricos y densos incrustados en conjuntos de datos de alta dimensión como espectrogramas de audio e intensidades de píxeles de imagen, como hemos estudiado en otras lecciones.\n", "\n", "\n", "Sin embargo, cuando se trata de datos de texto sin procesar, especialmente modelos basados en conteo como la bolsa de palabras (bag of words), estamos tratando con palabras individuales que pueden tener sus propios identificadores y no capturan la relación semántica entre palabras. \n", "\n", "En lecciones anteriores trabajamos con la técnica de bolsa de palabras en la técnica Lattent Dirichlet Allocation (LDA). \n", "\n", "Esto conduce a enormes vectores de palabras dispersas para datos textuales y, por lo tanto, si no tenemos suficientes datos, podemos terminar obteniendo modelos deficientes o incluso sobreajustando los datos debido a la maldición de la dimensionalidad.\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Modelos Word2Vec</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "La familia de modelos Word2Vec no es supervisada, lo que esto significa es que puede simplemente darle un corpus sin etiquetas o información adicionales y puede construir incrustaciones densas de palabras a partir del corpus. \n", "\n", "Pero aún necesitará aprovechar una metodología de clasificación supervisada una vez que tenga este corpus para acceder a estas incorporaciones. \n", "\n", "Haremos esto desde el propio corpus, sin ninguna información auxiliar. Podemos modelar esta arquitectura CBOW ahora como un modelo de clasificación de aprendizaje profundo de modo que tomemos en las palabras de contexto como nuestra entrada, $X$ e intentemos predecir la palabra objetivo, $Y$. " ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Modelo CBOW</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "\n", "<figure>\n", "<center>\n", "<img src=\"../Imagenes/cbow_1_palabra.png\" width=\"600\" height=\"400\" align=\"center\"/>\n", "</center>\n", "<figcaption>\n", "<p style=\"text-align:center\">Arquitectura del modelo CBOW con una palabra de contexto</p>\n", "</figcaption>\n", "</figure>\n", "\n", "Fuente: Alvaro Montenegro" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "La siguiente imagen es la arquitectura general CBOW." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "\n", "<figure>\n", "<center>\n", "<img src=\"../Imagenes/CBOW.png\" width=\"300\" height=\"200\" align=\"center\"/>\n", "</center>\n", "<figcaption>\n", "<p style=\"text-align:center\">Arquitectura general del modelo CBOW</p>\n", "</figcaption>\n", "</figure>\n", "\n", "Fuente: \n", "[Efficient Estimation of Word Representations in Vector space](https://arxiv.org/pdf/1301.3781.pdf)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Veamos un ejemplo de cómo se hace la preparación de los datos para CBOW\n", "\n", "Usaremos el símbolo especial *PAD* para codificar los espacios faltantes (se hizo en tensorflow con la función *sequence_pad*. ¿Recuerda?\n", "\n", "Consideremos la frase en inglés (más tarde mostraremos como usar las herramientas para Español)\n", "\n", "- *the quick brown fox jumps over the lazzy dog*\n", "\n", "La construcción de los contextos usando una ventana de contexto de tamaño 2 es como sigue:\n", "\n", "1. (PAD, PAD,quick, brown) -> the\n", "2. (PAD, the, brown, fox) -> quick\n", "3. (the, quick, fox, jumps) -> brown\n", "4. (quick, brown, jumps, over) -> fox\n", "5. (brown, fox, over, the) -> jumps\n", "6. (fox, jumps, the, lazzy) -> over\n", "7. (jumps, over, lazzy, dog) -> the\n", "8. (over, the, dog, PAD) -> lazzy\n", "8. (the, lazzy, PAD, PAD) -> dog\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Modelo Skip-gram</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "La arquitectura del modelo Skip-gram generalmente intenta lograr lo contrario de lo que hace el modelo CBOW. \n", "\n", "\n", "Intenta predecir las palabras de contexto de origen (palabras circundantes) dada una palabra de destino (la palabra central). Teniendo en cuenta nuestra simple oración de antes, \"the quick brown fox jumps over the lazy dog”. \n", "\n", "Si usamos el modelo CBOW, obtenemos pares de (context_window, target_word) donde si consideramos una ventana de contexto de tamaño 2, tenemos ejemplos como ([quick, fox], brown), ([the, brown], quick) , ([the, dog], lazy) y así sucesivamente. \n", "\n", "Ahora, teniendo en cuenta que el objetivo del modelo *skip-gram* es predecir el contexto a partir de la palabra objetivo, el modelo normalmente invierte los contextos y objetivos e intenta predecir cada palabra de contexto a partir de su palabra objetivo. \n", "\n", "Por lo tanto, la tarea se convierte en predecir el contexto [quick, fox] dada la palabra objetivo *brown* o [the brown] dada la palabra objetivo *quick* y así sucesivamente. \n", "\n", "Por lo tanto, el modelo intenta predecir las palabras de la ventana context_window basándose en target_word.\n", "\n", "La figura ilustra la arquitectura skip-gram\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "\n", "<figure>\n", "<center>\n", "<img src=\"../Imagenes/SKIP_gram.png\" width=\"300\" height=\"300\" align=\"center\"/>\n", "</center>\n", "<figcaption>\n", "<p style=\"text-align:center\">Modelo Skip-gram</p>\n", "</figcaption>\n", "</figure>\n", "\n", "Fuente: \n", "[Dipanjan (DJ) Sarkar](https://towardsdatascience.com/understanding-feature-engineering-part-4-deep-learning-methods-for-text-data-96c44370bbfa)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "<figure>\n", "<center>\n", "<img src=\"../Imagenes/Skip-Gram-architecture.jpg\" width=\"600\" height=\"600\" align=\"center\"/>\n", "</center>\n", "<figcaption>\n", "<p style=\"text-align:center\">Arquitectura Skip-gram</p>\n", "</figcaption>\n", "</figure>\n", "\n", "Fuente: \n", "[Exploring chemical space using natural language processing](https://www.researchgate.net/publication/339013257_Exploring_chemical_space_using_natural_language_processing_methodologies_for_drug_discovery/figures?lo=1)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Para esto, alimentamos nuestros pares de modelos de skip-gram son $(X, Y)$ donde $X$ es nuestra entrada e $Y$ es nuestra etiqueta. \n", "\n", "Hacemos esto usando los pares [(objetivo, contexto), 1] como muestras de entrada positivas donde objetivo es nuestra palabra de interés y contexto es una palabra de contexto que aparece cerca de la palabra objetivo y la etiqueta positiva 1 indica que este es un par contextualmente relevante. \n", "\n", "\n", "También introducimos pares [(objetivo, aleatorio), 0] como muestras de entrada negativa donde objetivo es nuevamente nuestra palabra de interés, pero aleatorio significa que es solo una palabra seleccionada al azar de nuestro vocabulario que no tiene contexto o asociación con nuestra palabra objetivo. \n", "\n", "\n", "Por lo tanto, la etiqueta negativa 0 indica que este es un par contextualmente irrelevante. Hacemos esto para que el modelo pueda aprender qué pares de palabras son contextualmente relevantes y cuáles no y generar incrustaciones similares para palabras semánticamente similares.\n", "\n", "La construcción de los pares [(objetivo, aleatorio), 0] se hace tomando al azar palabras objetivo y asociándole al azar palabras con las que no haya conformado parejas de contexto. Los autores citados en las referencias proponen más de una alternativa para generar estas parejas, basados en distinto modelos de muestreo. Por lo general se sugiere que haya tantas parejas positivas como negativas.\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "En el mismo ejemplo anterior \n", "\n", "- *the quick brown fox jumps over the lazzy dog*\n", "\n", "se tiene que las parejas positivas son:\n", "\n", "1. the: (the, quick), (the, brown) (the, jumps), (the, over), (the, lazzy), (the,dog)\n", "2. quick: (quick, the), (quick, brown), (quick, fox)\n", "3. brown: (brown, the) (brown, quick), (brown, jumps), (brown, over)\n", "4. fox: (fox, quick), (fox, brown), (fox, jumps), (fox, over)\n", "5. jumps: (jumps, brown), (jumps, fox), (jumps, over), (jumps, the)\n", "6. lazzy: (lazzy, over), (lazzy, the), (lazzy, dog)\n", "7. dog: (dog,the), (dog, lazzy)\n", "\n", "Una pareja negativa puede ser (quick, lazzy)." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Sobre que podemos esperar</span> " ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Supongamos que se ha obtenido la siguiente codificación word2vec para personajes de comics.\n", "\n", "word2vec(‘Batman’) = [0.9, 0.8, 0.2]\n", "\n", "word2vec(‘Joker’) = [0.8, 0.3, 0.1]\n", "\n", "word2vec(‘Spiderman’) = [0.2, .9, 0.8]\n", "\n", "word2vec(‘Thanos’) = [0.3, 0.1, 0.9]\n", "\n", "1. Parece que la primera característica representa la pertenencia al Universo DC. Observa que \"Batman\" y \"Joker\" tienen valores más altos para su primera función porque pertenecen al Universo DC.\n", "2. Quizás el segundo elemento en la representación de word2vec aquí captura las características de héroe / villano. Es por eso que \"Batman\" y \"Spiderman\" tienen valores más altos y \"Joker\" y \"Thanos\" tienen valores más pequeños.\n", "3. Se podría decir que el tercer componente de la palabra vectores representa los poderes / habilidades sobrenaturales. Todos sabemos que \"Batman\" y \"Joker\" no tienen superpoderes y es por eso que sus vectores tienen números pequeños en la tercera posición." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "<figure>\n", "<center>\n", "<img src=\"../Imagenes/word2vec-models.jpg\" width=\"600\" height=\"600\" align=\"center\"/>\n", "</center>\n", "<figcaption>\n", "<p style=\"text-align:center\">Arquitectura word2vec</p>\n", "</figcaption>\n", "</figure>\n", "\n", "Fuente: \n", "[wor2vec arquitecture](https://figshare.com/articles/figure/_i_Word2Vec_i_architecture_The_figure_shows_two_variants_of_word2vec_architecture_CBOW_and_Skip_gram_26_for_a_sample_/11982951)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Las tareas linguisticas</span> " ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "En el paper de Baroni et al., 2014,[Don’t count, predict! A systematic comparison of context-counting vs. context-predicting semantic vectors](https://www.aclweb.org/anthology/P14-1023.pdf), se comparan los métodos clásicos de distribución semántica probabilística de documentos, con los modelos predictivos presentados en esta lección. Para la comparación ello desarrolla las siguientes tareas lingüísticas\n", "\n", "1. Relación semántica de términos.\n", "2. Detección de sinónimos.\n", "3. Categorización de conceptos.\n", "4. Selección de preferencias. (verbo, sustantivo). Variedad en el uso del lenguaje\n", "5. Analogías sintácticas. [(brother,sister), grandson] -> granddaughter.\n", "\n", "Invitamos al lector interesado la lectura del paper.\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Recursos linguísticos</span> " ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "[NLTK](https://www.nltk.org/py-modindex.html) incluye una pequeña selección de textos del archivo de texto electrónico del Proyecto Gutenberg, que contiene unos 25.000 libros electrónicos gratuitos, alojados en [Gutenberg project](http://www.gutenberg.org/)\n", "\n", "*Tokenizador de frases Punkt*\n", "\n", "Este tokenizador divide un texto en una lista de oraciones mediante el uso de un algoritmo no supervisado para construir un modelo de abreviaturas, colocaciones y palabras que inician oraciones. Debe entrenarse en una gran colección de texto sin formato en el idioma de destino antes de que pueda usarse.\n", "\n", "El paquete de datos NLTK incluye un tokenizador Punkt previamente entrenado para inglés." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Corpus de juguete</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Para empezar usaremos el siguiente *corpus de juguete*\n", "\n", "Nuestro corpus de juguetes consta de documentos pertenecientes a varias categorías. \n", "\n", "Otro corpus que usaremos en esta lección es la versión *King James de la Biblia* disponible gratuitamente en *Project Gutenberg* a través del módulo de corpus en nltk.\n", "\n", "Lo cargaremos en breve, en la siguiente sección. Antes de los análisis necesitamos preprocesar y normalizar este texto." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### <span style=\"color:#4CC9F0\">Importa librerías (módulos)</span>" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "import re\n", "import nltk\n", "import matplotlib.pyplot as plt\n", "\n", "pd.options.display.max_colwidth = 200\n", "\n", "%matplotlib inline" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### <span style=\"color:#4CC9F0\">Corpus de juguete</span>" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>Document</th>\n", " <th>Category</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>The sky is blue and beautiful.</td>\n", " <td>weather</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>Love this blue and beautiful sky!</td>\n", " <td>weather</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>The quick brown fox jumps over the lazy dog.</td>\n", " <td>animals</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>A king's breakfast has sausages, ham, bacon, e...</td>\n", " <td>food</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>I love green eggs, ham, sausages and bacon!</td>\n", " <td>food</td>\n", " </tr>\n", " <tr>\n", " <th>5</th>\n", " <td>The brown fox is quick and the blue dog is lazy!</td>\n", " <td>animals</td>\n", " </tr>\n", " <tr>\n", " <th>6</th>\n", " <td>The sky is very blue and the sky is very beaut...</td>\n", " <td>weather</td>\n", " </tr>\n", " <tr>\n", " <th>7</th>\n", " <td>The dog is lazy but the brown fox is quick!</td>\n", " <td>animals</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " Document Category\n", "0 The sky is blue and beautiful. weather\n", "1 Love this blue and beautiful sky! weather\n", "2 The quick brown fox jumps over the lazy dog. animals\n", "3 A king's breakfast has sausages, ham, bacon, e... food\n", "4 I love green eggs, ham, sausages and bacon! food\n", "5 The brown fox is quick and the blue dog is lazy! animals\n", "6 The sky is very blue and the sky is very beaut... weather\n", "7 The dog is lazy but the brown fox is quick! animals" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "corpus = ['The sky is blue and beautiful.',\n", " 'Love this blue and beautiful sky!',\n", " 'The quick brown fox jumps over the lazy dog.',\n", " \"A king's breakfast has sausages, ham, bacon, eggs, toast and beans\",\n", " 'I love green eggs, ham, sausages and bacon!',\n", " 'The brown fox is quick and the blue dog is lazy!',\n", " 'The sky is very blue and the sky is very beautiful today',\n", " 'The dog is lazy but the brown fox is quick!' \n", "]\n", "labels = ['weather', 'weather', 'animals', 'food', 'food', 'animals', 'weather', 'animals']\n", "\n", "corpus = np.array(corpus)\n", "corpus_df = pd.DataFrame({'Document': corpus, \n", " 'Category': labels})\n", "corpus_df = corpus_df[['Document', 'Category']]\n", "corpus_df" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Pre-procesamiento del texto</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Vamos a hacer un preprocesamiento diferente para cada corpus." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "wpt = nltk.WordPunctTokenizer()\n", "stop_words = nltk.corpus.stopwords.words('english')\n", "\n", "def normalize_document(doc):\n", " # remove special characters: \n", " doc = re.sub(r'[^a-zA-Z\\s]', '', doc, re.I|re.A)\n", " # transform to lower case\n", " doc = doc.lower()\n", " # remove \\whitespaces\n", " doc = doc.strip()\n", " # tokenize document\n", " tokens = wpt.tokenize(doc)\n", " # filter stopwords out of document\n", " filtered_tokens = [token for token in tokens if token not in stop_words]\n", " # re-create document from filtered tokens\n", " doc = ' '.join(filtered_tokens)\n", " return doc\n", "\n", "# crea una función vectorizada para que actué sobre múltiples textos\n", "normalize_corpus = np.vectorize(normalize_document)\n", "#normalize_corpus" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([['sky blue beautiful', 'weather'],\n", " ['love blue beautiful sky', 'weather'],\n", " ['quick brown fox jumps lazy dog', 'animals'],\n", " ['kings breakfast sausages ham bacon eggs toast beans', 'food'],\n", " ['love green eggs ham sausages bacon', 'food'],\n", " ['brown fox quick blue dog lazy', 'animals'],\n", " ['sky blue sky beautiful today', 'weather'],\n", " ['dog lazy brown fox quick', 'animals']], dtype='<U51')" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "norm_corpus_toy = normalize_corpus(corpus_df)\n", "norm_corpus_toy" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">The King James Version of the Bible</span>" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['!', '\"', '#', '$', '%', '&', \"'\", '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\\\', ']', '^', '_', '`', '{', '|', '}', '~', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[nltk_data] Downloading package gutenberg to /home/alvaro/nltk_data...\n", "[nltk_data] Package gutenberg is already up-to-date!\n" ] } ], "source": [ "from nltk.corpus import gutenberg\n", "from string import punctuation\n", "\n", "nltk.download('gutenberg')\n", "\n", "bible = gutenberg.sents('bible-kjv.txt') # tokeniza por sentencias\n", "remove_terms = list(punctuation + '0123456789')\n", "print(remove_terms)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total lines: 30103\n", "\n", "Sample line: ['1', ':', '6', 'And', 'God', 'said', ',', 'Let', 'there', 'be', 'a', 'firmament', 'in', 'the', 'midst', 'of', 'the', 'waters', ',', 'and', 'let', 'it', 'divide', 'the', 'waters', 'from', 'the', 'waters', '.']\n", "\n", "Processed line: god said let firmament midst waters let divide waters waters\n" ] } ], "source": [ "norm_bible = [[word.lower() for word in sent if word not in remove_terms] for sent in bible]\n", "norm_bible = [' '.join(tok_sent) for tok_sent in norm_bible]\n", "norm_bible = filter(None, normalize_corpus(norm_bible))\n", "norm_bible = [tok_sent for tok_sent in norm_bible if len(tok_sent.split()) > 2]\n", "\n", "print('Total lines:', len(bible))\n", "print('\\nSample line:', bible[10])\n", "print('\\nProcessed line:', norm_bible[10])" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Modelos con Gensim</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "El objeto word2vec de gensim puede usar CBOW o Skip-gram. Los autores de gensim tomaron el código original escritos por Mikolov y colegas, escrito en c++, lo optimizaron y volvieron *caja negra*. Según ellos gensim es 7 veces más rápido que la implementación que hicimos manualmente en otra lección, usando numpy." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### <span style=\"color:#4CC9F0\">Corpus Biblia </span>" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "from gensim.models import word2vec\n", "\n", "# tokenize sentences in corpus\n", "wpt = nltk.WordPunctTokenizer()\n", "tokenized_corpus_bible = [wpt.tokenize(document) for document in norm_bible]\n", "\n", "# Set values for various parameters\n", "feature_size = 100 # Word vector dimensionality (embedding dim)\n", "window_context = 30 # Context window size \n", "min_word_count = 1 # Minimum word count \n", "sample = 1e-3 # Downsample setting for frequent words\n", "\n", "w2v_model = word2vec.Word2Vec(tokenized_corpus_bible, size=feature_size, \n", " window=window_context, min_count=min_word_count,\n", " sample=sample, iter=50)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### <span style=\"color:#4CC9F0\">Palabras similares, corpus biblia</span>" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'god': ['worldly', 'lord', 'reasonable', 'covenant', 'sworn'],\n", " 'jesus': ['peter', 'messias', 'immediately', 'apostles', 'nathanael'],\n", " 'noah': ['ham', 'shem', 'japheth', 'kenan', 'enosh'],\n", " 'egypt': ['pharaoh', 'egyptians', 'bondage', 'flowing', 'rid'],\n", " 'john': ['james', 'baptist', 'peter', 'devine', 'galilee'],\n", " 'gospel': ['christ', 'repentance', 'faith', 'godly', 'hope'],\n", " 'moses': ['congregation', 'ordinance', 'children', 'doctor', 'aaron'],\n", " 'famine': ['pestilence', 'peril', 'mildew', 'blasting', 'sword']}" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# view similar words based on gensim's model\n", "similar_words = {search_term: [item[0] for item in w2v_model.wv.most_similar([search_term], topn=5)]\n", " for search_term in ['god', 'jesus', 'noah', 'egypt', 'john', 'gospel', 'moses','famine']}\n", "similar_words" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "{'dios': ['mundano', 'señor', 'razonable', 'menos', 'nosotros'],\n", " 'jesús': ['pedro', 'mesías', 'juan', 'apóstoles', 'james'],\n", " 'noah': ['japheth', 'shem', 'ham', 'henoch', 'enosh'],\n", " 'egipto': ['egipcios', 'esclavitud', 'faraón', 'fluyendo', 'piojos'],\n", " 'john': ['james', 'baptist', 'devine', 'pedro', 'baptism'],\n", " 'evangelio': ['cristo', 'fe', 'predicar', 'arrepentimiento', 'esperanza'],\n", " 'moisés': ['elisheba', 'congregación', 'joshua', 'naashon', 'doctor'],\n", " 'hambruna': ['pestilencia', 'peligro', 'alcanza', 'muertes', 'moho']}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "help(word2vec.Word2Vec)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### <span style=\"color:#4CC9F0\">Gráfico con tsne</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Incrustaciones estocásticas de vecinos con distribución t-Student.\n", "\n", "[t-SNE](https://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html), [Laurens van der Maaten and Geoffrey Hinton](https://www.jmlr.org/papers/volume9/vandermaaten08a/vandermaaten08a.pdf) es una herramienta para visualizar datos de alta dimensión. Convierte las similitudes entre los puntos de datos en probabilidades conjuntas y trata de minimizar la divergencia de Kullback-Leibler entre las probabilidades conjuntas de la incrustación de baja dimensión y los datos de alta dimensión. t-SNE tiene una función de costo que no es convexa, es decir, con diferentes inicializaciones podemos obtener diferentes resultados.\n", "\n", "Se recomienda fuertemente utilizar otro método de reducción de dimensionalidad (por ejemplo, PCA para datos densos o TruncatedSVD para datos escasos) para reducir el número de dimensiones a una cantidad razonable (por ejemplo, 50) si el número de características es muy alto. Esto suprimirá algo de ruido y acelerará el cálculo de distancias por pares entre muestras. Para obtener más consejos, consulte las preguntas frecuentes de [Laurens van der Maaten](https://lvdmaaten.github.io/tsne/)\n" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "image/png": "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2JAFCxbg5eXF2apVGZH8s6WW1IM1oce1y/8mTpxIRkYGXl5eeHh4MHHiRMCSle/AgQP4+PhYa0iJiIiIiPzVGbmzDXe6gIAAMzY2tqSHcXOuyp7HpDDbBXEbuFgCJff/NZ3ZCX6z7DmaUfCyuOTkZDp16sS+ffuKduwiIiIiIncZwzDiTNMMKOp+taepOPXtZztIutpV+6B+PQchn8LorHszI7uIiIiIyN1Ay/PuJFftg6pRBX78Bzxbr/Z1T3FxcdEsk4iIiIhIMVLQdCe5lX1QIiIiIiJSrLQ8706Su5Qv7z6o8D/ZByUiIiIiIsVKQdOd5mb3QYmIiIiISLHS8jwREREREREbFDSJiIiIiIjYoKBJRERERETEBgVNIiIiIiIiNihoEhERERERsUFBk4iIiIiIiA0KmkRERERERGxQ0CQiIiIiImKDgiYREREREREbFDSJiIiIiIjYoKBJRERERETEBgVNIiIiIiIiNihoEhERERERsUFBk4iIiIiIiA0KmkRERERERGxQ0CQiIiIiImKDgiYREREREREbFDSJiIiIiIjYoKBJRERERETEBgVNIiIiIiIiNihoEhERERERsUFBk4iIiIiIiA0KmkRERERERGxQ0CQiIiIiImKDgiYREREREREbFDSJiIiIiIjYoKBJRERERETEBgVNIiIiIiIiNihoEhERERERsUFBk4iIiIiIiA0KmkRERERERGxQ0CQiIiIiImKDgiYREREREREbFDSJiIiIiIjYoKBJRERERETEBgVNIiIiIiIiNihoEhERERERsUFBk4iIiIiIiA0KmkRERERERGxQ0CQiIiIiImKDgiYREREREREbFDSJiIiIiIjYoKBJRERERETEBgVNIiIiIiIiNihoEhERERERsUFBk4iIiIiIiA0KmkRERERERGxQ0CQiIiIiImJDoYMmwzAeMgzje8MwfjAMY79hGM/ntFc1DONbwzCSch6r5DlnvGEYhwzDOGgYRvvCjkFERERERKS4FMVMUybwkmmaDYFAYKRhGG7AOOA70zTrAt/lPCfntScAd6ADMNswDPsiGIeIiIiIiEiRK3TQZJrmCdM0d+X8fBH4AXgQeAxYkHPYAqBrzs+PAYtN0/zDNM0jwCGgcWHHISIiIiIiUhyKdE+TYRgugC+wHbjfNM0TYAmsgGo5hz0IHM9z2s85bSIiIiIiInecIguaDMNwBJYDL5imecHWoQW0mdfpc6hhGLGGYcSeOnWqKIYpIiIiIiJyU4okaDIMozSWgCnSNM0VOc0nDcOonvN6deD3nPafgYfynF4T+LWgfk3TnGuaZoBpmgH33XdfUQxVRERERETkphRF9jwD+Aj4wTTN6Xle+hwYmPPzQGB1nvYnDMMoaxiGK1AX2FHYcYiIiIiIiBSHUkXQRzPgSWCvYRjxOW2vAK8DSw3D+AdwDOgFYJrmfsMwlgIHsGTeG2maZlYRjENERERERKTIFTpoMk0zhoL3KQG0uc45YUBYYa8tIiIiIiJS3Io0e56IiIiIiMi9RkGTiIiIiIiIDQqaREREREREbFDQJCIiIiIiYoOCJhERERERERsUNImIiIiIiNigoElERERERMQGBU0iIiIiIiI2KGgSERERERGxQUGTiIiIiIiIDQqaREREREREbFDQJCIiIiIiYoOCJhERERERERsUNImIiIiIiNigoElERERERMQGBU0iIiIiIiI2KGgSERERERGxQUGTiIiIiIiIDQqaREREREREbFDQJCIiIiIiYoOCJhERERERERsUNImIiIiIiNigoElERERERMQGBU0iIiIiIiI2KGgSERERERGxQUGTiIiIiIiIDQqaREREREREbFDQJCIiIiIiYoOCJhERERERERsUNImIiIiIiNigoElERERERMQGBU0iInJXy8rKKukhiIjIPU5Bk4iI3BG6du2Kv78/7u7uzJ07F4ARI0YQEBCAu7s7kydPth7r4uLC1KlTad68OZ999hmffvopnp6eeHh4MHbsWOtxjo6OTJgwAW9vbwIDAzl58uRtvy8REbn7KWgSEZE7wrx584iLiyM2NpYZM2Zw5swZwsLCiI2NJSEhgY0bN5KQkGA9vly5csTExNCyZUvGjh3Lhg0biI+PZ+fOnaxatQqAtLQ0AgMD2bNnDy1btuSDDz4oobsTEZG7mYImERG5I8yYMcM6I3T8+HGSkpJYunQpfn5++Pr6sn//fg4cOGA9vnfv3gDs3LmTkJAQ7rvvPkqVKkW/fv2Ijo4GoEyZMnTq1AkAf39/kpOTb/t9iYjI3U9Bk4iI3H6LIqGBC9jbQQMXov45gfXr17N161b27NmDr68vP/zwA+Hh4Xz33XckJCTQsWNH0tPTrV1UqFABANM0r3uZ0qVLYxgG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L9bXXF1d8fHxAf6XQKF58+ZFc7N1a8HBo5aZplwHc9pFROSupqBJRESKzqJIyzK1pGNQtxZm45YYtWwHDblL07p06cL48eM5e/YscXFxtG7dmrS0NCpXrkx8fHyB5+YmQwC4cuUKDRo0wN7enosXLzJy5Ejat29PkyZNCAkJoVatWpQqZfnYi4uL491338XOzo7z588Xzb1PCrPsaRp0CepjCZgiHCA8rGj6FxGREqM9TSIiUjSuSoRAj6O0WfsZSz/6iDNnzgBw9uxZgoKCWLx4MQCRkZHWmR5HR0caN27M888/T6dOnbC3t6dSpUq4urry2WefAZZZpD179lxz6djYWDIzM9m9ezcDBgzgwoUL2Nvb0717d65cucLXX39NgwYNOHXqFACDBg3iscceY8iQIQDY2dlx8eLFwt1/334QPheW17YsyVte2/K8b78/PTUkJISClqDPnz+fZ555BoApU6YQHh5euDGKiMgtUdAkIiJF46pECLiD+9B0JpBBcHAw3t7evPjii8yYMYOIiAi8vLxYuHAh7777rrWL3r1788knn+SrSRQZGclHH32Et7c37u7u1sQOecXExGBvb0/58uX5xz/+gYODA9OnT+f333+nQYMGAPTo0YO0tDRrPaS///3vgGWJYJUqVRg+fHjhEkGAJUBKTLbsYUpMvqGAKSsr69avJyIit4WW54mISNFIOmZZlpZXfRj4+1kGnjidr3nDhg0FdtGzZ0+uTlDk6urK119/fc2x89s9Av8cDb0fx/xbZcZ36gSAs7MzTzzxBE5OTnz00Uf88MMPgCU4adiwIaZpYhiWNOAACQkJVKpUiX379t30Lb/55puUK1eO5557jlGjRrFnzx42bNjAd999R0REBB07duTf//43pmnSsWNH3njjDcAyq/biiy/yzTff8J///CdfnxEREbz22mtUr16devXq5VuCCHD48GF69erFrl27AEhKSuKJJ54gLi7upscvIiI3RjNNIiJSNOrWsuzjyau4EiFctRSwecdzfPHFKtLnR5CamsqXX35JhQoVCqx7VLlyZZycnIiJiQEsM1m3qmXLltb+Y2NjSU1NJSMjg5iYGOrWrcvYsWPZsGED8fHx7Ny5k1WrVgGQlpaGh4cH27dvz5eI4sSJE0yePJnNmzfz7bffcuDAgWuu+fe//x0nJyfrPq+IiAhCQ0Nv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qLu8hXXvlsy4IiJ3i+Iqbvs58IRhGGUNw3AF6gI7TNM8AVw0DCMwJ2veAMBW8CUiInLvKahA7rkzsHwZ58+f58EHLSvX58+fX+DpFStW5OLFi7dxwCIif22FTTnezTCMn4GmwJeGYXwDYJrmfmApcAD4GhiZkzkPYATwIZbkEIdR5jwREfmryVsgtxSWR0cT3grj5ZdfZvz48TRr1oysrKwCT+/cuTMrV67MlwhCRESKj4rbioiI3G5FVCBXRETyuyOL24qIiMgtKKYCuSIiUjwUNImIiNxuk8IsBXH3Y5lh2o/l+aSbK5ArIiK3R3HVaRIREZHrya3xNHUCJB2zzDCFhxVp7ScRESk6CppERERKQhEXyBURkeKj5XkiIiIiIiI2KGgSERERERGxQUGTiIiIiIiIDQqaREREREREbFDQJCIiIiIiYoOCJhERERERERsUNImIiIiIiNigoElERERERMQGBU0iIiIiIiI2KGgSERERERGxQUGTiIiIiIiIDQqaREREREREbFDQJCIiIiIiYoOCJhERERERERsUNImIiIiIiNigoElERERERMQGBU0iIiIiIiI2KGgSERERERGxQUGTiIiIiIiIDQqaREREREREbFDQJCIiIiIiYoOCJhERERERERsUNImIiIiIiNigoElERERERMQGBU0iIiIiIiI2KGgSERERERGxQUGTiIiIiIiIDQqaREREREREbFDQJCIiIiIiYoOCJhERERERERsUNImIiIiIiNigoElERERERMQGBU0iIiIiIiI2KGgSERERERGxQUGTiIiIiIiIDQqaREREREREbFDQJCIiIiIiYoOCJhERERERERsUNImIiIiIiNigoElERERERMQGBU0iIiIiIiI2KGgSERERERGxQUGTiIiIiIiIDQqaREREREREbFDQJCIiIiIiYoOCJhERERERERsUNImIiIiIiNigoElERERERMQGBU0iIiIiIiI2KGgSERERERGxQUGTiIiIiIiIDQqaREREREREbFDQJCIiIiIiYoOCJhERERERERsKFTQZhvGWYRiJhmEkGIax0jCMynleG28YxiHDMA4ahtE+T7u/YRh7c16bYRiGUZgxiIiIiIiIFKfCzjR9C3iYpukF/AiMBzAMww14AnAHOgCzDcOwzznnPWAoUDfnvw6FHIOIiIiIiEixKVTQZJrmOtM0M3OebgNq5vz8GLDYNM0/TNM8AhwCGhuGUR2oZJrmVtM0TeBjoGthxiAiIiIiIlKcinJP02Bgbc7PDwLH87z2c07bgzk/X90uIiIiIiJyRyr1ZwcYhrEeeKCAlyaYprk655gJQCYQmXtaAcebNtqvd+2hWJbyUatWrT8bqoiIiIiISJH706DJNM22tl43DGMg0Alok7PkDiwzSA/lOawm8GtOe80C2q937bnAXICAgIDrBlciIiIiIiLFpbDZ8zoAY4EupmleyvPS58AThmGUNQzDFUvChx2maZ4ALhqGEZiTNW8AsLowYxARERERESlOfzrT9CdmAWWBb3Myh28zTXO4aZr7DcNYChzAsmxvpGmaWTnnjADmA+Wx7IFae02vIiIiIiIid4hCBU2maT5s47UwIKyA9ljAozDXFRERERERuV2KMnueiIiIiIjIPUdBk4iIiIiIiA0KmkRERERERGxQ0CQiIiIiImKDgiYREREREREbFDSJiIiIiIjYoKBJRERERETEBgVNIiIiIiIiNihoEhERERERsUFBk4iIiIiIiA0KmkRERERERGxQ0CQiIiIiImKDgiYREREREREbFDSJiIiIiIjYoKBJRERERETEBgVNIiIiIiIiNihoEhERuQlBQUHXfS0qKopOnTrdxtGIiMjtoKBJRETkJmzZsqWkhyAiIreZgiYREZGb4OjoiGmajBkzBg8PDzw9PVmyZIn19dTUVHr27EmDBg3o168fpmkC4OLiwuTJk/Hz88PT05PExMSSugUREblJCppERERu0ooVK4iPj2fPnj2sX7+eMWPGcOLECQB2797NO++8w4EDB/jpp5/YvHmz9TxnZ2d27drFiBEjCA8PL6nhi4jITVLQJCIicpNiYmLo06cP9vb23H///QQHB7Nz504AGjduTM2aNbGzs8PHx4fk5GTred27dwfA398/X7uIiNzZFDSJiIhcz6JIaOAC9naWx0WRANYldwUpW7as9Wd7e3syMzOvee3q9tttypQp1pmuSZMmsX79egBCQkKIjY0tsXGJiNypFDSJiIgUZFEkjB4KPY5ChGl5HD0UMjNp2bIlS5YsISsri1OnThEdHU3jxo1LesS3ZOrUqbRt27akhyEickdT0CQiIlKQqRNg0CVwB0pheRx0CePKFbp164aXlxfe3t60bt2aN998kwceeKBE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", "text/plain": [ "<Figure size 1008x576 with 1 Axes>" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "from sklearn.manifold import TSNE\n", "\n", "words = sum([[k] + v for k, v in similar_words.items()], []) # a list of the words in similar_words\n", "wvs = w2v_model.wv[words] # Coordinates of the words\n", "\n", "tsne = TSNE(n_components=2, random_state=100, n_iter=10000, perplexity=2)\n", "np.set_printoptions(suppress=True)\n", "T = tsne.fit_transform(wvs)\n", "labels = words\n", "\n", "plt.figure(figsize=(14, 8))\n", "plt.scatter(T[:, 0], T[:, 1], c='orange', edgecolors='r')\n", "for label, x, y in zip(labels, T[:, 0], T[:, 1]):\n", " plt.annotate(label, xy=(x+1, y+1), xytext=(0, 0), textcoords='offset points')" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[-0.34405723, -2.2080076 , 0.22129701, ..., -0.27648592,\n", " -0.12405743, -0.15957785],\n", " [-0.11122978, -0.63676333, -0.18996008, ..., 0.06530013,\n", " 0.13042438, 0.25724903],\n", " [ 0.9176589 , 1.1386521 , 0.03363332, ..., 1.1606003 ,\n", " -1.6409662 , -1.9810503 ],\n", " ...,\n", " [ 1.0055212 , 0.5959988 , -1.167708 , ..., -0.2223904 ,\n", " 0.6689782 , -0.24536332],\n", " [ 1.0243756 , 0.62595314, -1.1647514 , ..., -0.17356953,\n", " 0.59791714, -0.216457 ],\n", " [-1.8861887 , 0.5809999 , -0.08317056, ..., 2.7208266 ,\n", " 5.5738573 , 0.00431524]], dtype=float32)" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wvs" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['god',\n", " 'worldly',\n", " 'lord',\n", " 'reasonable',\n", " 'covenant',\n", " 'sworn',\n", " 'jesus',\n", " 'peter',\n", " 'messias',\n", " 'immediately',\n", " 'apostles',\n", " 'nathanael',\n", " 'noah',\n", " 'ham',\n", " 'shem',\n", " 'japheth',\n", " 'kenan',\n", " 'enosh',\n", " 'egypt',\n", " 'pharaoh',\n", " 'egyptians',\n", " 'bondage',\n", " 'flowing',\n", " 'rid',\n", " 'john',\n", " 'james',\n", " 'baptist',\n", " 'peter',\n", " 'devine',\n", " 'galilee',\n", " 'gospel',\n", " 'christ',\n", " 'repentance',\n", " 'faith',\n", " 'godly',\n", " 'hope',\n", " 'moses',\n", " 'congregation',\n", " 'ordinance',\n", " 'children',\n", " 'doctor',\n", " 'aaron',\n", " 'famine',\n", " 'pestilence',\n", " 'peril',\n", " 'mildew',\n", " 'blasting',\n", " 'sword']" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "words" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Aplicación a etiquetado automático de textos</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Para esta aplicación vamos a usar nuestro ejemplo de juguete." ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'brown fox quick blue dog lazy'" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "norm_toy = [(text) for text, category in norm_corpus_toy]\n", "#norm_toy = [tok_sent for tok_sent in norm_toy if len(tok_sent.split()) > 2]\n", "norm_toy[5]" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "# build word2vec model\n", "wpt = nltk.WordPunctTokenizer()\n", "\n", "tokenized_corpus_toy = [wpt.tokenize(document) for document in norm_toy]\n", "\n", "# Set values for various parameters\n", "feature_size = 10 # Word vector dimensionality \n", "window_context = 10 # Context window size \n", "min_word_count = 1 # Minimum word count \n", "sample = 1e-3 # Downsample setting for frequent words\n", "\n", "w2v_model = word2vec.Word2Vec(tokenized_corpus_toy, size=feature_size, \n", " window=window_context, min_count = min_word_count,\n", " sample=sample, iter=100)\n", " " ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Visualización de incrustaciones con TSNE</span>" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "<Figure size 864x432 with 1 Axes>" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ " \n", "# visualize embeddings\n", "from sklearn.manifold import TSNE\n", "\n", "words = w2v_model.wv.index2word\n", "wvs = w2v_model.wv[words]\n", "\n", "tsne = TSNE(n_components=2, random_state=200, n_iter=5000, perplexity=2)\n", "np.set_printoptions(suppress=True)\n", "T = tsne.fit_transform(wvs)\n", "labels = words\n", "\n", "plt.figure(figsize=(12, 6))\n", "plt.scatter(T[:, 0], T[:, 1], c='orange', edgecolors='r')\n", "for label, x, y in zip(labels, T[:, 0], T[:, 1]):\n", " plt.annotate(label, xy=(x+1, y+1), xytext=(0, 0), textcoords='offset points')" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Recuerde que nuestro corpus es extremadamente pequeño, por lo que para obtener incrustaciones de palabras significativas y para que el modelo obtenga más contexto y semántica, más datos ayudan.\n", "\n", "Ahora bien, ¿qué es una palabra incrustada en este escenario? \n", "\n", "Por lo general, es un vector denso para cada palabra, como se muestra en el siguiente ejemplo para la palabra *sky*." ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0.0222188 , -0.00322705, 0.00577812, 0.02297305, 0.00253111,\n", " -0.03698301, -0.00314448, -0.03604106, 0.00387173, 0.01324753],\n", " dtype=float32)" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w2v_model.wv['sky']" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Incrustación de documentos</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Ahora suponga que quisiéramos agrupar los ocho documentos de nuestro corpus de juguetes, necesitaríamos obtener las incrustaciones de nivel de documento de cada una de las palabras presentes en cada documento. \n", "\n", "Una estrategia sería promediar las incrustaciones de palabras para cada palabra en un documento. \n", "\n", "Esta es una estrategia extremadamente útil y puede adoptar la misma para sus propios problemas. Apliquemos esto ahora en nuestro corpus para obtener características para cada documento." ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "<ipython-input-45-de269809cb6b>:9: DeprecationWarning: Call to deprecated `__getitem__` (Method will be removed in 4.0.0, use self.wv.__getitem__() instead).\n", " feature_vector = np.add(feature_vector, model[word])\n" ] } ], "source": [ "def average_word_vectors(words, model, vocabulary, num_features):\n", " \n", " feature_vector = np.zeros((num_features,),dtype=\"float64\")\n", " nwords = 0.\n", " \n", " for word in words:\n", " if word in vocabulary: \n", " nwords = nwords + 1.\n", " feature_vector = np.add(feature_vector, model[word])\n", " \n", " if nwords:\n", " feature_vector = np.divide(feature_vector, nwords)\n", " \n", " return feature_vector\n", " \n", " \n", "def averaged_word_vectorizer(corpus, model, num_features):\n", " vocabulary = set(model.wv.index2word)\n", " features = [average_word_vectors(tokenized_sentence, model, vocabulary, num_features)\n", " for tokenized_sentence in corpus]\n", " return np.array(features)\n", "\n", "\n", "# get document level embeddings\n", "w2v_feature_array = averaged_word_vectorizer(corpus=tokenized_corpus_toy, model=w2v_model, num_features=feature_size)\n", " " ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>0</th>\n", " <th>1</th>\n", " <th>2</th>\n", " <th>3</th>\n", " <th>4</th>\n", " <th>5</th>\n", " <th>6</th>\n", " <th>7</th>\n", " <th>8</th>\n", " <th>9</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>-0.003041</td>\n", " <td>-0.007926</td>\n", " <td>0.018282</td>\n", " <td>0.003400</td>\n", " <td>-0.003612</td>\n", " <td>0.017513</td>\n", " <td>-0.021539</td>\n", " <td>0.000254</td>\n", " <td>0.014870</td>\n", " <td>0.001121</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>0.004246</td>\n", " <td>-0.016616</td>\n", " <td>0.002898</td>\n", " <td>-0.003310</td>\n", " <td>0.001360</td>\n", " <td>0.015432</td>\n", " <td>-0.020553</td>\n", " <td>0.002866</td>\n", " <td>0.006426</td>\n", " <td>-0.000660</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>0.005549</td>\n", " <td>-0.010005</td>\n", " <td>-0.016900</td>\n", " <td>0.000572</td>\n", " <td>-0.012724</td>\n", " <td>0.019170</td>\n", " <td>-0.025599</td>\n", " <td>-0.007053</td>\n", " <td>-0.014700</td>\n", " <td>-0.017178</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>0.006906</td>\n", " <td>0.009039</td>\n", " <td>0.000851</td>\n", " <td>0.010022</td>\n", " <td>0.001052</td>\n", " <td>-0.004086</td>\n", " <td>0.006732</td>\n", " <td>-0.004544</td>\n", " <td>-0.006839</td>\n", " <td>-0.005179</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>0.007297</td>\n", " <td>0.004711</td>\n", " <td>-0.014360</td>\n", " <td>0.012438</td>\n", " <td>-0.011912</td>\n", " <td>0.015900</td>\n", " <td>0.001450</td>\n", " <td>-0.018203</td>\n", " <td>-0.009471</td>\n", " <td>-0.005930</td>\n", " </tr>\n", " <tr>\n", " <th>5</th>\n", " <td>0.012570</td>\n", " <td>-0.009762</td>\n", " <td>-0.005562</td>\n", " <td>0.001511</td>\n", " <td>-0.006945</td>\n", " <td>0.023436</td>\n", " <td>-0.029692</td>\n", " <td>0.000243</td>\n", " <td>-0.008374</td>\n", " <td>-0.003993</td>\n", " </tr>\n", " <tr>\n", " <th>6</th>\n", " <td>-0.000583</td>\n", " <td>-0.003620</td>\n", " <td>0.010479</td>\n", " <td>0.014733</td>\n", " <td>-0.004924</td>\n", " <td>0.005844</td>\n", " <td>-0.010194</td>\n", " <td>-0.009180</td>\n", " <td>0.019397</td>\n", " <td>0.006925</td>\n", " </tr>\n", " <tr>\n", " <th>7</th>\n", " <td>0.015602</td>\n", " <td>-0.009999</td>\n", " <td>-0.014323</td>\n", " <td>0.008859</td>\n", " <td>-0.010401</td>\n", " <td>0.020386</td>\n", " <td>-0.026200</td>\n", " <td>-0.004136</td>\n", " <td>-0.011145</td>\n", " <td>-0.012100</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " 0 1 2 3 4 5 6 \\\n", "0 -0.003041 -0.007926 0.018282 0.003400 -0.003612 0.017513 -0.021539 \n", "1 0.004246 -0.016616 0.002898 -0.003310 0.001360 0.015432 -0.020553 \n", "2 0.005549 -0.010005 -0.016900 0.000572 -0.012724 0.019170 -0.025599 \n", "3 0.006906 0.009039 0.000851 0.010022 0.001052 -0.004086 0.006732 \n", "4 0.007297 0.004711 -0.014360 0.012438 -0.011912 0.015900 0.001450 \n", "5 0.012570 -0.009762 -0.005562 0.001511 -0.006945 0.023436 -0.029692 \n", "6 -0.000583 -0.003620 0.010479 0.014733 -0.004924 0.005844 -0.010194 \n", "7 0.015602 -0.009999 -0.014323 0.008859 -0.010401 0.020386 -0.026200 \n", "\n", " 7 8 9 \n", "0 0.000254 0.014870 0.001121 \n", "1 0.002866 0.006426 -0.000660 \n", "2 -0.007053 -0.014700 -0.017178 \n", "3 -0.004544 -0.006839 -0.005179 \n", "4 -0.018203 -0.009471 -0.005930 \n", "5 0.000243 -0.008374 -0.003993 \n", "6 -0.009180 0.019397 0.006925 \n", "7 -0.004136 -0.011145 -0.012100 " ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ " \n", "pp = pd.DataFrame(w2v_feature_array)\n", "pp" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Ahora que tenemos nuestras características para cada documento, agrupemos estos documentos utilizando el **algoritmo de propagación de afinidad**, que es un algoritmo de agrupación basado en el concepto de \"paso de mensajes\" entre puntos de datos y no necesita el número de agrupaciones como una entrada explícita que a menudo es requerido por algoritmos de agrupación en clústeres basados en particiones." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### <span style=\"color:#4CC9F0\">Propagación por afinidad: Afinity propagation</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Este es el resumen del artículo de [Frey y Duek](https://science.sciencemag.org/content/315/5814/972).\n", "\n", "\"La agrupación de datos mediante la identificación de un subconjunto de ejemplos representativos es importante para procesar señales sensoriales y detectar patrones en los datos. \n", "\n", "Estos \"ejemplos\" se pueden encontrar eligiendo aleatoriamente un subconjunto inicial de puntos de datos y luego refinándolo iterativamente, pero esto funciona bien solo si esa elección inicial está cerca de una buena solución.\n", "\n", "\n", "Diseñamos un método llamado \"propagación por afinidad\", que toma como entrada medidas de similitud entre pares de puntos de datos. Los mensajes de valor real se intercambian entre puntos de datos hasta que emerge gradualmente un conjunto de ejemplos de alta calidad y los grupos correspondientes. \n", "\n", "Utilizamos la propagación por afinidad para agrupar imágenes de rostros, detectar genes en datos de microarrays, identificar oraciones representativas en este manuscrito e identificar ciudades a las que se accede de manera eficiente mediante viajes en avión. \n", "\n", "La propagación por afinidad encontró grupos con un error mucho menor que otros métodos, y lo hizo en menos de una centésima parte del tiempo.\"" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/alvaro/anaconda3/envs/nlp/lib/python3.8/site-packages/sklearn/cluster/_affinity_propagation.py:148: FutureWarning: 'random_state' has been introduced in 0.23. It will be set to None starting from 1.0 (renaming of 0.25) which means that results will differ at every function call. Set 'random_state' to None to silence this warning, or to 0 to keep the behavior of versions <0.23.\n", " warnings.warn(\n" ] }, { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>Document</th>\n", " <th>Category</th>\n", " <th>ClusterLabel</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>The sky is blue and beautiful.</td>\n", " <td>weather</td>\n", " <td>0</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>Love this blue and beautiful sky!</td>\n", " <td>weather</td>\n", " <td>0</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>The quick brown fox jumps over the lazy dog.</td>\n", " <td>animals</td>\n", " <td>2</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>A king's breakfast has sausages, ham, bacon, eggs, toast and beans</td>\n", " <td>food</td>\n", " <td>1</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>I love green eggs, ham, sausages and bacon!</td>\n", " <td>food</td>\n", " <td>1</td>\n", " </tr>\n", " <tr>\n", " <th>5</th>\n", " <td>The brown fox is quick and the blue dog is lazy!</td>\n", " <td>animals</td>\n", " <td>2</td>\n", " </tr>\n", " <tr>\n", " <th>6</th>\n", " <td>The sky is very blue and the sky is very beautiful today</td>\n", " <td>weather</td>\n", " <td>0</td>\n", " </tr>\n", " <tr>\n", " <th>7</th>\n", " <td>The dog is lazy but the brown fox is quick!</td>\n", " <td>animals</td>\n", " <td>2</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " Document \\\n", "0 The sky is blue and beautiful. \n", "1 Love this blue and beautiful sky! \n", "2 The quick brown fox jumps over the lazy dog. \n", "3 A king's breakfast has sausages, ham, bacon, eggs, toast and beans \n", "4 I love green eggs, ham, sausages and bacon! \n", "5 The brown fox is quick and the blue dog is lazy! \n", "6 The sky is very blue and the sky is very beautiful today \n", "7 The dog is lazy but the brown fox is quick! \n", "\n", " Category ClusterLabel \n", "0 weather 0 \n", "1 weather 0 \n", "2 animals 2 \n", "3 food 1 \n", "4 food 1 \n", "5 animals 2 \n", "6 weather 0 \n", "7 animals 2 " ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.cluster import AffinityPropagation\n", "\n", "ap = AffinityPropagation()\n", "ap.fit(w2v_feature_array)\n", "cluster_labels = ap.labels_\n", "cluster_labels = pd.DataFrame(cluster_labels, columns=['ClusterLabel'])\n", "pd.concat([corpus_df, cluster_labels], axis=1)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Finalmente hagamos un plot de los documentos usando un análisis de componentes principales (ACP)." ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "<Figure size 576x432 with 1 Axes>" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "from sklearn.decomposition import PCA\n", "\n", "pca = PCA(n_components=2, random_state=0)\n", "pcs = pca.fit_transform(w2v_feature_array)\n", "labels = ap.labels_\n", "categories = list(corpus_df['Category'])\n", "plt.figure(figsize=(8, 6))\n", "\n", "for i in range(len(labels)):\n", " label = labels[i]\n", " color = 'orange' if label == 0 else 'blue' if label == 1 else 'green'\n", " annotation_label = categories[i]\n", " x, y = pcs[i]\n", " plt.scatter(x, y, c=color, edgecolors='k')\n", " plt.annotate(annotation_label, xy=(x+1e-4, y+1e-3), xytext=(0, 0), textcoords='offset points')\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Modelos pre-entrenados. El modelo Glove</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "El modelo GloVe significa Vectores Globales, que es un modelo de aprendizaje no supervisado que se puede utilizar para obtener vectores de palabras densas similares a Word2Vec. \n", "\n", "Sin embargo, la técnica es diferente y el entrenamiento se realiza en una matriz global de co-ocurrencia palabra-palabra, usando el contexto de las mismas, lo que nos da un espacio vectorial con subestructuras significativas. \n", "\n", "Este método fue inventado en Stanford por Pennington et al. y se recomienda que leer el artículo original sobre GloVe, [GloVe: Global Vectors for Word Representation](https://nlp.stanford.edu/pubs/glove.pdf) de Pennington et al. que es una lectura excelente para tener una perspectiva de cómo funciona este modelo.\n", "\n", "\n", "\n", "No cubriremos la implementación del modelo desde cero con demasiado detalle aquí, pero si está interesado en el código real, puede consultar la página oficial de [GloVe](https://nlp.stanford.edu/projects/glove/). \n", "\n", "Aquí mantendremos las cosas simples e intentaremos comprender los conceptos básicos detrás del modelo GloVe. Hemos hablado de métodos de factorización matricial basados en recuento como LSA y métodos predictivos como Word2Vec. \n", "\n", "\n", "El paper afirma que, actualmente, ambas familias sufren importantes inconvenientes. \n", "\n", "\n", "1. Los métodos como LSA aprovechan de manera eficiente la información estadística, pero funcionan relativamente mal en la tarea de analogía de palabras, como la forma en que descubrimos palabras semánticamente similares. \n", "2. Los métodos como skip-gram pueden funcionar mejor en la tarea de analogía, pero no utilizan tan bien las estadísticas del corpus a nivel global.\n", "\n", "\n", "La metodología básica del modelo GloVe es crear primero una enorme matriz de co-ocurrencia palabra-contexto que consta de pares (palabra, contexto) de modo que cada elemento de esta matriz represente la frecuencia con la que aparece una palabra con el contexto (que puede ser una secuencia de palabras).\n", "\n", "La idea entonces es aplicar factorización matricial para aproximar esta matriz como se muestra en la siguiente figura." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "<figure>\n", "<center>\n", "<img src=\"../Imagenes/glove_matrix.png\" width=\"400\" height=\"300\" align=\"center\"/>\n", "</center>\n", "<figcaption>\n", "<p style=\"text-align:center\">Base matemática del modelo Glove</p>\n", "</figcaption>\n", "</figure>\n", "\n", "Fuente: [understanding-feature-engineering](https://towardsdatascience.com/understanding-feature-engineering-part-4-deep-learning-methods-for-text-data-96c44370bbfa)\n", "\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Teniendo en cuenta la matriz **Word-Context (WC)**, la matriz **Word-Feature (WF)** y la **matriz Feature-Context (FC)**, intentamos factorizar **WC = WF x FC**, de modo que nuestro objetivo es reconstruir WC a partir de WF y FC multiplicando ellos. \n", "\n", "\n", "Para esto, normalmente inicializamos WF y FC con algunos pesos aleatorios e intentamos multiplicarlos para obtener WC ’(una aproximación de WC) y medir qué tan cerca está de WC. Hacemos esto varias veces usando el Descenso de gradiente estocástico (SGD) para minimizar el error. \n", "\n", "Finalmente, la matriz Word-Feature (WF) nos da las incrustaciones de palabras para cada palabra donde F se puede preestablecer para un número específico de dimensiones.\n", "\n", "Un punto muy importante para recordar es que los modelos Word2Vec y GloVe son muy similares en su funcionamiento. \n", "\n", "\n", "Ambos tienen como objetivo construir un espacio vectorial donde la posición de cada palabra está influenciada por las palabras vecinas en función de su contexto y semántica. \n", "\n", "Word2Vec comienza con ejemplos individuales locales de pares de co-ocurrencia de palabras y GloVe comienza con estadísticas globales de co-ocurrencia agregadas en todas las palabras del corpus." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Introducción a spaCy</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Intentemos aprovechar las incrustaciones basadas en GloVe para nuestra tarea de agrupación de documentos. \n", "\n", "El marco de trabajo **spaCy** es muy popular y viene con capacidades para aprovechar las incrustaciones de GloVe basadas en diferentes modelos de lenguaje. \n", "\n", "También puede obtener vectores de palabras previamente entrenados y cargarlos según sea necesario usando gensim o spacy. \n", "\n", "Primero instalaremos spacy y usaremos el modelo **en_core_web_md** un modelo intermedio del inglés. Si desea resultados más potentes instale **en_vectors_web_lg** que consiste en vectores de palabras de 300 dimensiones entrenados en Common Crawl con GloVe, [GloVe](https://nlp.stanford.edu/projects/glove/).\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Modelos en Español</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "En la página [spacy-models](https://spacy.io/usage/models) encuentra los modelos disponibles en *spacy*, basados en Glove, para distintos idiomas. \n", "\n", "En particular para Español se tienen [modelos para Español en spacy](https://spacy.io/models/es) : \n", "\n", "1. es_core_news_sm (small): 15 MB\n", "2. es_core_news_md (medium): 500k keys, 20k unique vectors (300 dimensions), 45 MB\n", "3. es_core_news_lg (long): : 500k keys, 500k unique vectors (300 dimensions), 546 MB\n", "\n", "Para bajar e instalar por ejemplo *es_core_news_md* puede escribir\n", "\n", "*python -m spacy download es_core_news_md*\n", "\n", "Veamos\n" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total word vectors: 20000\n" ] } ], "source": [ "#!conda install -c conda-forge spacy\n", "# !python -m spacy en_core_web_md\n", "\n", "import spacy\n", "\n", "nlp = spacy.load('en_core_web_md')\n", "\n", "\n", "total_vectors = len(nlp.vocab.vectors)\n", "print('Total word vectors:', total_vectors)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Si todo va bien hasta aquí, podemos continuar." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>0</th>\n", " <th>1</th>\n", " <th>2</th>\n", " <th>3</th>\n", " <th>4</th>\n", " <th>5</th>\n", " <th>6</th>\n", " <th>7</th>\n", " <th>8</th>\n", " <th>9</th>\n", " <th>...</th>\n", " <th>290</th>\n", " <th>291</th>\n", " <th>292</th>\n", " <th>293</th>\n", " <th>294</th>\n", " <th>295</th>\n", " <th>296</th>\n", " <th>297</th>\n", " <th>298</th>\n", " <th>299</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>green</th>\n", " <td>-0.072368</td>\n", " <td>0.233200</td>\n", " <td>0.137260</td>\n", " <td>-0.156630</td>\n", " <td>0.248440</td>\n", " <td>0.349870</td>\n", " <td>-0.241700</td>\n", " <td>-0.091426</td>\n", " <td>-0.530150</td>\n", " <td>1.34130</td>\n", " <td>...</td>\n", " <td>-0.405170</td>\n", " <td>0.243570</td>\n", " <td>0.437300</td>\n", " <td>-0.461520</td>\n", " <td>-0.352710</td>\n", " <td>0.336250</td>\n", " <td>0.069899</td>\n", " <td>-0.111550</td>\n", " <td>0.532930</td>\n", " <td>0.712680</td>\n", " </tr>\n", " <tr>\n", " <th>dog</th>\n", " <td>-0.401760</td>\n", " <td>0.370570</td>\n", " <td>0.021281</td>\n", " <td>-0.341250</td>\n", " <td>0.049538</td>\n", " <td>0.294400</td>\n", " <td>-0.173760</td>\n", " <td>-0.279820</td>\n", " <td>0.067622</td>\n", " <td>2.16930</td>\n", " <td>...</td>\n", " <td>0.022908</td>\n", " <td>-0.259290</td>\n", " <td>-0.308620</td>\n", " <td>0.001754</td>\n", " <td>-0.189620</td>\n", " <td>0.547890</td>\n", " <td>0.311940</td>\n", " <td>0.246930</td>\n", " <td>0.299290</td>\n", " <td>-0.074861</td>\n", " </tr>\n", " <tr>\n", " <th>fox</th>\n", " <td>-0.348680</td>\n", " <td>-0.077720</td>\n", " <td>0.177750</td>\n", " <td>-0.094953</td>\n", " <td>-0.452890</td>\n", " <td>0.237790</td>\n", " <td>0.209440</td>\n", " <td>0.037886</td>\n", " <td>0.035064</td>\n", " <td>0.89901</td>\n", " <td>...</td>\n", " <td>-0.283050</td>\n", " <td>0.270240</td>\n", " <td>-0.654800</td>\n", " <td>0.105300</td>\n", " <td>-0.068738</td>\n", " <td>-0.534750</td>\n", " <td>0.061783</td>\n", " <td>0.123610</td>\n", " <td>-0.553700</td>\n", " <td>-0.544790</td>\n", " </tr>\n", " <tr>\n", " <th>toast</th>\n", " <td>0.130740</td>\n", " <td>-0.193730</td>\n", " <td>0.253270</td>\n", " <td>0.090102</td>\n", " <td>-0.272580</td>\n", " <td>-0.030571</td>\n", " <td>0.096945</td>\n", " <td>-0.115060</td>\n", " <td>0.484000</td>\n", " <td>0.84838</td>\n", " <td>...</td>\n", " <td>0.142080</td>\n", " <td>0.481910</td>\n", " <td>0.045167</td>\n", " <td>0.057151</td>\n", " <td>-0.149520</td>\n", " <td>-0.495130</td>\n", " <td>-0.086677</td>\n", " <td>-0.569040</td>\n", " <td>-0.359290</td>\n", " <td>0.097443</td>\n", " </tr>\n", " <tr>\n", " <th>lazy</th>\n", " <td>-0.353320</td>\n", " <td>-0.299710</td>\n", " <td>-0.176230</td>\n", " <td>-0.321940</td>\n", " <td>-0.385640</td>\n", " <td>0.586110</td>\n", " <td>0.411160</td>\n", " <td>-0.418680</td>\n", " <td>0.073093</td>\n", " <td>1.48650</td>\n", " <td>...</td>\n", " <td>0.402310</td>\n", " <td>-0.038554</td>\n", " <td>-0.288670</td>\n", " <td>-0.244130</td>\n", " <td>0.460990</td>\n", " <td>0.514170</td>\n", " <td>0.136260</td>\n", " <td>0.344190</td>\n", " <td>-0.845300</td>\n", " <td>-0.077383</td>\n", " </tr>\n", " <tr>\n", " <th>brown</th>\n", " <td>-0.374120</td>\n", " <td>-0.076264</td>\n", " <td>0.109260</td>\n", " <td>0.186620</td>\n", " <td>0.029943</td>\n", " <td>0.182700</td>\n", " <td>-0.631980</td>\n", " <td>0.133060</td>\n", " <td>-0.128980</td>\n", " <td>0.60343</td>\n", " <td>...</td>\n", " <td>-0.015404</td>\n", " <td>0.392890</td>\n", " <td>-0.034826</td>\n", " <td>-0.720300</td>\n", " <td>-0.365320</td>\n", " <td>0.740510</td>\n", " <td>0.108390</td>\n", " <td>-0.365760</td>\n", " <td>-0.288190</td>\n", " <td>0.114630</td>\n", " </tr>\n", " <tr>\n", " <th>ham</th>\n", " <td>-0.773320</td>\n", " <td>-0.282540</td>\n", " <td>0.580760</td>\n", " <td>0.841480</td>\n", " <td>0.258540</td>\n", " <td>0.585210</td>\n", " <td>-0.021890</td>\n", " <td>-0.463680</td>\n", " <td>0.139070</td>\n", " <td>0.65872</td>\n", " <td>...</td>\n", " <td>0.464470</td>\n", " <td>0.481400</td>\n", " <td>-0.829200</td>\n", " <td>0.354910</td>\n", " <td>0.224530</td>\n", " <td>-0.493920</td>\n", " <td>0.456930</td>\n", " <td>-0.649100</td>\n", " <td>-0.131930</td>\n", " <td>0.372040</td>\n", " </tr>\n", " <tr>\n", " <th>jumps</th>\n", " <td>-0.334840</td>\n", " <td>0.215990</td>\n", " <td>-0.350440</td>\n", " <td>-0.260020</td>\n", " <td>0.411070</td>\n", " <td>0.154010</td>\n", " <td>-0.386110</td>\n", " <td>0.206380</td>\n", " <td>0.386700</td>\n", " <td>1.46050</td>\n", " <td>...</td>\n", " <td>-0.107030</td>\n", " <td>-0.279480</td>\n", " <td>-0.186200</td>\n", " <td>-0.543140</td>\n", " <td>-0.479980</td>\n", " <td>-0.284680</td>\n", " <td>0.036022</td>\n", " <td>0.190290</td>\n", " <td>0.692290</td>\n", " <td>-0.071501</td>\n", " </tr>\n", " <tr>\n", " <th>today</th>\n", " <td>-0.156570</td>\n", " <td>0.594890</td>\n", " <td>-0.031445</td>\n", " <td>-0.077586</td>\n", " <td>0.278630</td>\n", " <td>-0.509210</td>\n", " <td>-0.066350</td>\n", " <td>-0.081890</td>\n", " <td>-0.047986</td>\n", " <td>2.80360</td>\n", " <td>...</td>\n", " <td>-0.326580</td>\n", " <td>-0.413380</td>\n", " <td>0.367910</td>\n", " <td>-0.262630</td>\n", " <td>-0.203690</td>\n", " <td>-0.296560</td>\n", " <td>-0.014873</td>\n", " <td>-0.250060</td>\n", " <td>-0.115940</td>\n", " <td>0.083741</td>\n", " </tr>\n", " <tr>\n", " <th>quick</th>\n", " <td>-0.445630</td>\n", " <td>0.191510</td>\n", " <td>-0.249210</td>\n", " <td>0.465900</td>\n", " <td>0.161950</td>\n", " <td>0.212780</td>\n", " <td>-0.046480</td>\n", " <td>0.021170</td>\n", " <td>0.417660</td>\n", " <td>1.68690</td>\n", " <td>...</td>\n", " <td>-0.329460</td>\n", " <td>0.421860</td>\n", " <td>-0.039543</td>\n", " <td>0.150180</td>\n", " <td>0.338220</td>\n", " <td>0.049554</td>\n", " <td>0.149420</td>\n", " <td>-0.038789</td>\n", " <td>-0.019069</td>\n", " <td>0.348650</td>\n", " </tr>\n", " <tr>\n", " <th>eggs</th>\n", " <td>-0.417810</td>\n", " <td>-0.035192</td>\n", " <td>-0.126150</td>\n", " <td>-0.215930</td>\n", " <td>-0.669740</td>\n", " <td>0.513250</td>\n", " <td>-0.797090</td>\n", " <td>-0.068611</td>\n", " <td>0.634660</td>\n", " <td>1.25630</td>\n", " <td>...</td>\n", " <td>-0.232860</td>\n", " <td>-0.139740</td>\n", " <td>-0.681080</td>\n", " <td>-0.370920</td>\n", " <td>-0.545510</td>\n", " <td>0.073728</td>\n", " <td>0.111620</td>\n", " <td>-0.324700</td>\n", " <td>0.059721</td>\n", " <td>0.159160</td>\n", " </tr>\n", " <tr>\n", " <th>breakfast</th>\n", " <td>0.073378</td>\n", " <td>0.227670</td>\n", " <td>0.208420</td>\n", " <td>-0.456790</td>\n", " <td>-0.078219</td>\n", " <td>0.601960</td>\n", " <td>-0.024494</td>\n", " <td>-0.467980</td>\n", " <td>0.054627</td>\n", " <td>2.28370</td>\n", " <td>...</td>\n", " <td>0.647710</td>\n", " <td>0.373820</td>\n", " <td>0.019931</td>\n", " <td>-0.033672</td>\n", " <td>-0.073184</td>\n", " <td>0.296830</td>\n", " <td>0.340420</td>\n", " <td>-0.599390</td>\n", " <td>-0.061114</td>\n", " <td>0.232200</td>\n", " </tr>\n", " <tr>\n", " <th>beautiful</th>\n", " <td>0.171200</td>\n", " <td>0.534390</td>\n", " <td>-0.348540</td>\n", " <td>-0.097234</td>\n", " <td>0.101800</td>\n", " <td>-0.170860</td>\n", " <td>0.295650</td>\n", " <td>-0.041816</td>\n", " <td>-0.516550</td>\n", " <td>2.11720</td>\n", " <td>...</td>\n", " <td>-0.285540</td>\n", " <td>0.104670</td>\n", " <td>0.126310</td>\n", " <td>0.120040</td>\n", " <td>0.254380</td>\n", " <td>0.247400</td>\n", " <td>0.207670</td>\n", " <td>0.172580</td>\n", " <td>0.063875</td>\n", " <td>0.350990</td>\n", " </tr>\n", " <tr>\n", " <th>kings</th>\n", " <td>0.259230</td>\n", " <td>-0.854690</td>\n", " <td>0.360010</td>\n", " <td>-0.642000</td>\n", " <td>0.568530</td>\n", " <td>-0.321420</td>\n", " <td>0.173250</td>\n", " <td>0.133030</td>\n", " <td>-0.089720</td>\n", " <td>1.52860</td>\n", " <td>...</td>\n", " <td>-0.470090</td>\n", " <td>0.063743</td>\n", " <td>-0.545210</td>\n", " <td>-0.192310</td>\n", " <td>-0.301020</td>\n", " <td>1.068500</td>\n", " <td>0.231160</td>\n", " <td>-0.147330</td>\n", " <td>0.662490</td>\n", " <td>-0.577420</td>\n", " </tr>\n", " <tr>\n", " <th>love</th>\n", " <td>0.139490</td>\n", " <td>0.534530</td>\n", " <td>-0.252470</td>\n", " <td>-0.125650</td>\n", " <td>0.048748</td>\n", " <td>0.152440</td>\n", " <td>0.199060</td>\n", " <td>-0.065970</td>\n", " <td>0.128830</td>\n", " <td>2.05590</td>\n", " <td>...</td>\n", " <td>-0.124380</td>\n", " <td>0.178440</td>\n", " <td>-0.099469</td>\n", " <td>0.008682</td>\n", " <td>0.089213</td>\n", " <td>-0.075513</td>\n", " <td>-0.049069</td>\n", " <td>-0.015228</td>\n", " <td>0.088408</td>\n", " <td>0.302170</td>\n", " </tr>\n", " <tr>\n", " <th>bacon</th>\n", " <td>-0.430730</td>\n", " <td>-0.016025</td>\n", " <td>0.484620</td>\n", " <td>0.101390</td>\n", " <td>-0.299200</td>\n", " <td>0.761820</td>\n", " <td>-0.353130</td>\n", " <td>-0.325290</td>\n", " <td>0.156730</td>\n", " <td>0.87321</td>\n", " <td>...</td>\n", " <td>0.304240</td>\n", " <td>0.413440</td>\n", " <td>-0.540730</td>\n", " <td>-0.035930</td>\n", " <td>-0.429450</td>\n", " <td>-0.246590</td>\n", " <td>0.161490</td>\n", " <td>-1.065400</td>\n", " <td>-0.244940</td>\n", " <td>0.269540</td>\n", " </tr>\n", " <tr>\n", " <th>sausages</th>\n", " <td>-0.481340</td>\n", " <td>0.023467</td>\n", " <td>0.396470</td>\n", " <td>0.364770</td>\n", " <td>-0.083069</td>\n", " <td>0.684590</td>\n", " <td>0.007079</td>\n", " <td>-0.210320</td>\n", " <td>-0.021993</td>\n", " <td>0.81876</td>\n", " <td>...</td>\n", " <td>0.602560</td>\n", " <td>0.297010</td>\n", " <td>-0.543030</td>\n", " <td>-0.169150</td>\n", " <td>-0.689910</td>\n", " <td>-0.307360</td>\n", " <td>0.193250</td>\n", " <td>-0.634980</td>\n", " <td>0.183010</td>\n", " <td>0.285290</td>\n", " </tr>\n", " <tr>\n", " <th>sky</th>\n", " <td>0.312550</td>\n", " <td>-0.303080</td>\n", " <td>0.019587</td>\n", " <td>-0.354940</td>\n", " <td>0.100180</td>\n", " <td>-0.141530</td>\n", " <td>-0.514270</td>\n", " <td>0.886110</td>\n", " <td>-0.530540</td>\n", " <td>1.55660</td>\n", " <td>...</td>\n", " <td>-0.667050</td>\n", " <td>0.279110</td>\n", " <td>0.500970</td>\n", " <td>-0.277580</td>\n", " <td>-0.143720</td>\n", " <td>0.342710</td>\n", " <td>0.287580</td>\n", " <td>0.537740</td>\n", " <td>0.363490</td>\n", " <td>0.496920</td>\n", " </tr>\n", " <tr>\n", " <th>blue</th>\n", " <td>0.129450</td>\n", " <td>0.036518</td>\n", " <td>0.032298</td>\n", " <td>-0.060034</td>\n", " <td>0.399840</td>\n", " <td>-0.103020</td>\n", " <td>-0.507880</td>\n", " <td>0.076630</td>\n", " <td>-0.422920</td>\n", " <td>0.81573</td>\n", " <td>...</td>\n", " <td>-0.501280</td>\n", " <td>0.169010</td>\n", " <td>0.548250</td>\n", " <td>-0.319380</td>\n", " <td>-0.072887</td>\n", " <td>0.382950</td>\n", " <td>0.237410</td>\n", " <td>0.052289</td>\n", " <td>0.182060</td>\n", " <td>0.412640</td>\n", " </tr>\n", " <tr>\n", " <th>beans</th>\n", " <td>-0.423290</td>\n", " <td>-0.264500</td>\n", " <td>0.200870</td>\n", " <td>0.082187</td>\n", " <td>0.066944</td>\n", " <td>1.027600</td>\n", " <td>-0.989140</td>\n", " <td>-0.259950</td>\n", " <td>0.145960</td>\n", " <td>0.76645</td>\n", " <td>...</td>\n", " <td>0.048760</td>\n", " <td>0.351680</td>\n", " <td>-0.786260</td>\n", " <td>-0.368790</td>\n", " <td>-0.528640</td>\n", " <td>0.287650</td>\n", " <td>-0.273120</td>\n", " <td>-1.114000</td>\n", " <td>0.064322</td>\n", " <td>0.223620</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "<p>20 rows × 300 columns</p>\n", "</div>" ], "text/plain": [ " 0 1 2 3 4 5 \\\n", "green -0.072368 0.233200 0.137260 -0.156630 0.248440 0.349870 \n", "dog -0.401760 0.370570 0.021281 -0.341250 0.049538 0.294400 \n", "fox -0.348680 -0.077720 0.177750 -0.094953 -0.452890 0.237790 \n", "toast 0.130740 -0.193730 0.253270 0.090102 -0.272580 -0.030571 \n", "lazy -0.353320 -0.299710 -0.176230 -0.321940 -0.385640 0.586110 \n", "brown -0.374120 -0.076264 0.109260 0.186620 0.029943 0.182700 \n", "ham -0.773320 -0.282540 0.580760 0.841480 0.258540 0.585210 \n", "jumps -0.334840 0.215990 -0.350440 -0.260020 0.411070 0.154010 \n", "today -0.156570 0.594890 -0.031445 -0.077586 0.278630 -0.509210 \n", "quick -0.445630 0.191510 -0.249210 0.465900 0.161950 0.212780 \n", "eggs -0.417810 -0.035192 -0.126150 -0.215930 -0.669740 0.513250 \n", "breakfast 0.073378 0.227670 0.208420 -0.456790 -0.078219 0.601960 \n", "beautiful 0.171200 0.534390 -0.348540 -0.097234 0.101800 -0.170860 \n", "kings 0.259230 -0.854690 0.360010 -0.642000 0.568530 -0.321420 \n", "love 0.139490 0.534530 -0.252470 -0.125650 0.048748 0.152440 \n", "bacon -0.430730 -0.016025 0.484620 0.101390 -0.299200 0.761820 \n", "sausages -0.481340 0.023467 0.396470 0.364770 -0.083069 0.684590 \n", "sky 0.312550 -0.303080 0.019587 -0.354940 0.100180 -0.141530 \n", "blue 0.129450 0.036518 0.032298 -0.060034 0.399840 -0.103020 \n", "beans -0.423290 -0.264500 0.200870 0.082187 0.066944 1.027600 \n", "\n", " 6 7 8 9 ... 290 291 \\\n", "green -0.241700 -0.091426 -0.530150 1.34130 ... -0.405170 0.243570 \n", "dog -0.173760 -0.279820 0.067622 2.16930 ... 0.022908 -0.259290 \n", "fox 0.209440 0.037886 0.035064 0.89901 ... -0.283050 0.270240 \n", "toast 0.096945 -0.115060 0.484000 0.84838 ... 0.142080 0.481910 \n", "lazy 0.411160 -0.418680 0.073093 1.48650 ... 0.402310 -0.038554 \n", "brown -0.631980 0.133060 -0.128980 0.60343 ... -0.015404 0.392890 \n", "ham -0.021890 -0.463680 0.139070 0.65872 ... 0.464470 0.481400 \n", "jumps -0.386110 0.206380 0.386700 1.46050 ... -0.107030 -0.279480 \n", "today -0.066350 -0.081890 -0.047986 2.80360 ... -0.326580 -0.413380 \n", "quick -0.046480 0.021170 0.417660 1.68690 ... -0.329460 0.421860 \n", "eggs -0.797090 -0.068611 0.634660 1.25630 ... -0.232860 -0.139740 \n", "breakfast -0.024494 -0.467980 0.054627 2.28370 ... 0.647710 0.373820 \n", "beautiful 0.295650 -0.041816 -0.516550 2.11720 ... -0.285540 0.104670 \n", "kings 0.173250 0.133030 -0.089720 1.52860 ... -0.470090 0.063743 \n", "love 0.199060 -0.065970 0.128830 2.05590 ... -0.124380 0.178440 \n", "bacon -0.353130 -0.325290 0.156730 0.87321 ... 0.304240 0.413440 \n", "sausages 0.007079 -0.210320 -0.021993 0.81876 ... 0.602560 0.297010 \n", "sky -0.514270 0.886110 -0.530540 1.55660 ... -0.667050 0.279110 \n", "blue -0.507880 0.076630 -0.422920 0.81573 ... -0.501280 0.169010 \n", "beans -0.989140 -0.259950 0.145960 0.76645 ... 0.048760 0.351680 \n", "\n", " 292 293 294 295 296 297 \\\n", "green 0.437300 -0.461520 -0.352710 0.336250 0.069899 -0.111550 \n", "dog -0.308620 0.001754 -0.189620 0.547890 0.311940 0.246930 \n", "fox -0.654800 0.105300 -0.068738 -0.534750 0.061783 0.123610 \n", "toast 0.045167 0.057151 -0.149520 -0.495130 -0.086677 -0.569040 \n", "lazy -0.288670 -0.244130 0.460990 0.514170 0.136260 0.344190 \n", "brown -0.034826 -0.720300 -0.365320 0.740510 0.108390 -0.365760 \n", "ham -0.829200 0.354910 0.224530 -0.493920 0.456930 -0.649100 \n", "jumps -0.186200 -0.543140 -0.479980 -0.284680 0.036022 0.190290 \n", "today 0.367910 -0.262630 -0.203690 -0.296560 -0.014873 -0.250060 \n", "quick -0.039543 0.150180 0.338220 0.049554 0.149420 -0.038789 \n", "eggs -0.681080 -0.370920 -0.545510 0.073728 0.111620 -0.324700 \n", "breakfast 0.019931 -0.033672 -0.073184 0.296830 0.340420 -0.599390 \n", "beautiful 0.126310 0.120040 0.254380 0.247400 0.207670 0.172580 \n", "kings -0.545210 -0.192310 -0.301020 1.068500 0.231160 -0.147330 \n", "love -0.099469 0.008682 0.089213 -0.075513 -0.049069 -0.015228 \n", "bacon -0.540730 -0.035930 -0.429450 -0.246590 0.161490 -1.065400 \n", "sausages -0.543030 -0.169150 -0.689910 -0.307360 0.193250 -0.634980 \n", "sky 0.500970 -0.277580 -0.143720 0.342710 0.287580 0.537740 \n", "blue 0.548250 -0.319380 -0.072887 0.382950 0.237410 0.052289 \n", "beans -0.786260 -0.368790 -0.528640 0.287650 -0.273120 -1.114000 \n", "\n", " 298 299 \n", "green 0.532930 0.712680 \n", "dog 0.299290 -0.074861 \n", "fox -0.553700 -0.544790 \n", "toast -0.359290 0.097443 \n", "lazy -0.845300 -0.077383 \n", "brown -0.288190 0.114630 \n", "ham -0.131930 0.372040 \n", "jumps 0.692290 -0.071501 \n", "today -0.115940 0.083741 \n", "quick -0.019069 0.348650 \n", "eggs 0.059721 0.159160 \n", "breakfast -0.061114 0.232200 \n", "beautiful 0.063875 0.350990 \n", "kings 0.662490 -0.577420 \n", "love 0.088408 0.302170 \n", "bacon -0.244940 0.269540 \n", "sausages 0.183010 0.285290 \n", "sky 0.363490 0.496920 \n", "blue 0.182060 0.412640 \n", "beans 0.064322 0.223620 \n", "\n", "[20 rows x 300 columns]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "unique_words = list(set([word for sublist in [doc.split() for doc in norm_corpus] for word in sublist]))\n", "\n", "word_glove_vectors = np.array([nlp(word).vector for word in unique_words])\n", "pd.DataFrame(word_glove_vectors, index=unique_words)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Veamos una gŕafico TSNE para este caso." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAs4AAAFlCAYAAAD7326cAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOzde1yVVd7//9cCzcRTTZZZoWi3R2CDuvEskmXWlKfsJFiKo5Rl9quv3lp2W7dlOQ733YxTZjYOaoE5YVnZVDPmCYomQEHBkcwCy7wdzDQIMTau3x8b96CibuWwUd7Px4PHta91Hfbn2n+9Xa5rLWOtRUREREREzszP1wWIiIiIiFwIFJxFRERERLyg4CwiIiIi4gUFZxERERERLyg4i4iIiIh4QcFZRERERMQLjXxdgLdat25tg4KCfF2GiIiIiFzEMjMzD1hrr6zq2AUTnIOCgsjIyPB1GSIiIiJyETPGFJzumIZqiIiIiIh4QcFZRERERMQLCs4iIiIiIl5QcBYRERER8YKCs4iIiFRb8+bNfV2CSK1TcBYRERER8YKCs4iIiNSY4uJibrzxRnr27EloaCjvvvsuAIsXLyY8PJzw8HA6dOjADTfcwNKlS3nsscc817722ms8/vjjvipd5KyMtdbXNXjF6XRazeMsIiJSPzVv3pzi4mJcLhclJSW0bNmSAwcO0LdvX3bt2oUxBoCysjKGDBnCf/7nfzJkyBAcDgc7d+6kcePG9O/fn1dffZXQ0FAfP400ZMaYTGuts6pjF8wCKCIiIlL/WWt58skn2bx5M35+fuzdu5f9+/dz9dVXA/Doo48yZMgQhg8fDsCQIUNYu3Yt3bp1o6ysTKFZ6jUN1RAREZFzk5QIXYPA38+9TUr0HEpMTKSwsJDMzEyysrJo06YNpaWlACxbtoyCggKefvppz/mTJk1i2bJlJCQkEBsbW8cPInJu1OMsIiIi3ktKhOlxEFsCXYC8Ave+qxyAw4cPc9VVV9G4cWM2bNhAQYF79eLMzEzi4+NJSUnBz+/f/XZ9+vTh22+/ZcuWLWzbts0XTyTiNfU4i4iIiPfmznaH5mDc3W/BuPd/+QWAmJgYMjIycDqdJCYm0rVrVwBeeuklDh48yA033EB4eDiTJk3y3PLuu+9mwIABXH755XX/PCLnQD3OIiIi4r1de9w9zZV1gWL3u3+0bt2atLS0Uy5LSEg47S1TU1NPmF1DpL5Sj7OIiIh4r1M7yDupLa+i/RwdOnSIzp0707RpU2688cYaKU+kNqnHWURERLw3Z95JY5yBhACIn3fOt7rsssv48ssva7xEkdqi4CwiIiLei45xb+fOdg/b6NTOHZqPt4tcxBScRURE5NxExygoS4OkMc4iIiIiIl5QcBYRERER8YKCs4iISDX179/f1yWISB1QcBYREammzz77zNcliEgdUHAWERGppubNm7Nx40Zuv/12T9vUqVNZtmwZAEFBQTz55JP069cPp9PJli1bGDZsGNdffz2LFy8GYOPGjURGRjJ69Gi6d+/Ogw8+yLFjxygvL2fChAmEhIQQGhrKiy++6ItHFBE0q4aIiEidCAwMJC0tjccee4wJEybw6aefUlpaSnBwMA8++CAAX3zxBTt27KB9+/bccsstvP3223To0IG9e/eSk5MDuBcNqSsZGRmsWLGChQsXnvac5s2bU1xcXGc1ifiSgrOIiEgdGDFiBAChoaEUFxfTokULWrRowaWXXuoJw71796Zjx44AjB07ltTUVG688Ua+/vprHnnkEW677TZuvvnmOqvZ6XTidDrr7PtE6jsN1RAREfFWUiJ0DQJ/P/c2KdFzqFGjRhw7dsyzX1paesKlTZo0AcDPz8/z+fi+y+UCwBhzwjXGGC6//HKys7OJiori5ZdfZtKkSdV6hHnz5tGlSxduuukmxo4dS3x8PFFRUWRkZABw4MABgoKCAE4YflJcXExsbCyhoaE4HA5Wr159wn0PHDhAv379+OCDD6pVn0h9ph5nERERbyQlnrTUdIF7v0L79u3ZsWMHR48epbS0lE8++YSBAwee01d88cUXfPPNN7Rv355Vq1YRFxfHgQMHuOSSSxgzZgzXX389EyZMOO9HyMzM5M0332Tr1q24XC569uxJr169vLr22WefpVWrVmzfvh2AH3/80XNs//79jBgxgueee46hQ4eed30i9Z2Cs4iIiDfmznaH5uCK/WDc+3NnY4whMDCQu+++G4fDQadOnejRo8c5f0W/fv2YNWsW27dv97wouH37dmJjYz292S+88MJ5P0JKSgqjR48mICAA+PfwEW+sW7eON99807N/+eWXA1BWVsaNN97Iyy+/zODBg8+7NpELgYKziIiIN3btcfc0V9YF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Lyg4i4iIiIh4QcFZRERERMQLCs4iIiIiIl5QcBYRERER8YKCs4iIiIiIFxScRURERES8oOAsIiIiIuIFBWcRERERES8oOIuIiIiIeEHBWURERETECwrOIiIiIiJeUHAWEREREfGCgrOIiIiIiBcUnEVEREREvKDgLCIiIiLiBQVnEREREREvKDiLiIiIiHhBwVlERERExAsKziIiIiIiXlBwFhERERHxgoKziIiIiIgXFJxFRERERLyg4CwiIiIi4gUFZxERERERLyg4i4iIiIh4QcFZRERERMQLCs4iIiIiIl5QcBYRERER8UK1grMx5i5jTK4x5pgxxnnSsSeMMV8ZY/KMMcMqtd9S0faVMWZWdb5fRERERKSuVLfHOQe4A9hcudEY0x24FwgGbgEWGWP8jTH+wMvArUB3YGzFuXIBys/PJyQkpMbvGxUVRUZGxintb731Ft26deOGG24453s+//zzNVGaiIiINGDVCs7W2n9aa/OqODQSeNNae9Ra+w3wFdC74u8ra+3X1tpfgDcrzpWLVHl5eY3da+nSpSxatIgNGzac87UKziIiIlJdjWrpvtcCn1fa/66iDeDbk9r71FINUgdcLhfjx49n69atdO7cmRUrVtC9e3cmTpzI3/72N6ZOncqvfvUrnn76aY4ePcr1119PQkICzZs3Z+7cubz//vscOXKE/v378+qrr2KM8dz72LFjxMbGEhgYyCWXXEJqairffPMNI0aM4OGHH+a+++7j559/BuCll16if//+7Nu3j3vuuYeffvoJl8vFK6+8wgcffMCRI0cIDw8nODiYxMREX/1cIiIicgE7a4+zMWadMSanir8z9RSbKtrsGdpP991xxpgMY0xGYWHh2UoVH8jLyyMuLo5t27bRsmVLFi1aBMCll15KamoqN910E8899xzr1q1jy5YtOJ1O/vd//xeAqVOnkp6eTk5ODkeOHGHt2rWe+7pcLmJiYujcuTPPPfccc+bMwel0kpiYyO9+9zuuuuoq/v73v7NlyxZWrVrFtGnTAEhKSmLYsGFkZWWRnZ1NeHg48+fPp2nTpmRlZSk0i4iIyHk7a4+ztfam87jvd0Bgpf3rgO8rPp+uvarvXgIsAXA6nacN2OI7gYGBDBgwAIBx48axcOFCAO655x4APv/8c3bs2OE555dffqFfv34AbNiwgQULFlBSUsLBgwcJDg5m+PDhADzwwAPcfffdzJ49u8rvLSsrY+rUqWRlZeHv78+XX34JQEREBBMnTqSsrIxRo0YRHh5eew8vIiIiDUptTUf3HnCvMaaJMaYD0An4AkgHOhljOhhjLsH9AuF7tVSD1KSkROgaBP5+7m2Su+e28tCKyvvNmjUDwFrL0KFDycrKIisrix07drB06VJKS0t56KGHSE5OZvv27UyePJnS0lLPffr378+GDRtOaKvsxRdfpE2bNmRnZ5ORkcEvv/wCQGRkJJs3b+baa6/lvvvuY8WKFTX8Q4iIiEhDVd3p6EYbY74D+gEfGGM+BrDW5gJ/AXYAHwEPW2vLrbUuYCrwMfBP4C8V50p9lpQI0+NgTAEkWPd2ehy8u4Y9e/aQlpYGwMqVKxk4cOAJl/bt25dPP/2Ur776CoCSkhK+/PJLTyBu3bo1xcXFJCcnn3Ddb37zG379619z11134XK5Tinp8OHDtG3bFj8/P15//XXPS4gFBQVcddVVTJ48md/85jds2bIFgMaNG1NWVlazv4uIiIg0KNWdVeMda+111tom1to21tphlY7Ns9Zeb63tYq39sFL7X621nSuOzavO90sdmTsbYkvckws2wr2NLYGF8XTr1o3ly5fjcDg4ePAgU6ZMOeHSK6+8kmXLljF27FgcDgd9+/Zl586dXHbZZUyePJnQ0FBGjRpFRETEKV/7+OOP07NnT+677z6OHTt2wrGHHnqI5cuX07dvX7788ktPD/fGjRsJDw+nR48erF69mkcffRSAuLg4HA4HMTExtfELiYiISANgrL0whg47nU5b1dy+Ugf8/dw9zZVHxLuAWAPlx053lYiIiMgFxxiTaa11VnVMS27L2XVqByfP1p1X0S4iIiLSQCg4y9nNmQcJAZCLu6c5F/f+HI20ERERkYajthZAkYtJdMW44LmzYdced09z/Lx/t4uIiIg0AArO4p3oGAVlERERadA0VENERERExAsKziIiIiIiXlBwFhERERHxgoKziIiIiIgXFJwbqEOHDrFo0aIavefvf/97SkpKavSeIiIiIvWFgnMDpeAsIiIicm40HV0DNWvWLHbv3k14eDhDhw4F4MMPP8QYw1NPPcU999xDcXExI0eO5Mcff6SsrIznnnuOkSNH8vPPP3P33Xfz3XffUV5ezn/913+xf/9+vv/+e2644QZat27N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vZ5xw5deeikBAQGkpqYy9rHH8M8roM0xy+B7x5Ie6B6m0bt3b6677jr8/PwIDw8nPz/fV48pIiIiUm8pONc3J821TFIiwClDJ4wxVc65fLqhN2caktOkSRPPZ39/f1wuV7UfQ0RERORio+Bcn1Qx1zLT4+DdNezZs4e0tDQAVq5cycCBA4FT51xu2bIl1113HWvWrAHg6NGjlJSUEBkZyapVqygvL6ewsJDNmzfTu3dv3zyniIiIyAVIwbk+qTzXciPc29gSWBhPt27dWL58OQ6Hg4MHDzJlyhQmT55MaGgoo0aNOmHO5ddff52FCxficDjo378///d//8fo0aNxOByEhYUxZMgQFixYwNVXX+2rJxURERG54GhWjfqknsy1LCIiItJQaVaNC0U9mWtZRERERE6l4FyfzJkHCQGQi7unORf3/px5Pi5MRERERBqd/RSpM9Ex7u3c2bBrj7unOX7ev9tFRERExGcUnOub6BgFZREREZF6SEM1RERERES8oOAsIiIiIuIFBWcRERERES8oOIuIiIiIeEHBWc5bfn4+ISEhvi5DREREpE4oOIuIiIiIeEHBWarF5XIxfvx4HA4Hd955JyUlJWRmZjJ48GB69erFsGHD2LdvHwCvvfYaERERhIWFMWbMGEpKSgCYMGEC06ZNo3///nTs2JHk5GQA9u3bR2RkJOHh4YSEhJCSkuKz5xQRERFRcJZqycvLIy4ujm3bttGyZUtefvllHnnkEZKTk8nMzGTixInMnj0bgDvuuIP09HSys7Pp1q0bS5cu9dxn3759pKamsnbtWmbNmgVAUlISw4YNIysri+zsbMLDw33yjCIiIiKgBVCkmgIDAxkwYAAA48aN4/nnnycnJ4ehQ4cCUF5eTtu2bQHIycnhqaee4tChQxQXFzNs2DDPfUaNGoWfnx/du3dn//79AERERDBx4kTKysoYNWqUgrOIiIj4lHqcpVqMMSfst2jRguDgYLKyssjKymL79u387W9/A9xDMl566SW2b9/O008/TWlpqee6Jk2aeD5bawGIjIxk8+bNXHvttdx3332sWLGiDp5IREREpGoKzrXsjTfeoHfv3oSHh/PAAw9QXl7O0qVL6dy5M1FRUUyePJmpU6cCsHv3bvr27UtERARz/v/27je0qvsM4Pj3aWTDzlG3tim6rX8YUmtBUxENDEbHNP3z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", "text/plain": [ "<Figure size 864x432 with 1 Axes>" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "from sklearn.manifold import TSNE\n", "\n", "tsne = TSNE(n_components=2, random_state=0, n_iter=5000, perplexity=3)\n", "np.set_printoptions(suppress=True)\n", "T = tsne.fit_transform(word_glove_vectors)\n", "labels = unique_words\n", "\n", "plt.figure(figsize=(12, 6))\n", "plt.scatter(T[:, 0], T[:, 1], c='orange', edgecolors='r')\n", "for label, x, y in zip(labels, T[:, 0], T[:, 1]):\n", " plt.annotate(label, xy=(x+1, y+1), xytext=(0, 0), textcoords='offset points')" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Finalmente una clasificación k-means." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>Document</th>\n", " <th>Category</th>\n", " <th>ClusterLabel</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>The sky is blue and beautiful.</td>\n", " <td>weather</td>\n", " <td>1</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>Love this blue and beautiful sky!</td>\n", " <td>weather</td>\n", " <td>1</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>The quick brown fox jumps over the lazy dog.</td>\n", " <td>animals</td>\n", " <td>2</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>A king's breakfast has sausages, ham, bacon, eggs, toast and beans</td>\n", " <td>food</td>\n", " <td>0</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>I love green eggs, ham, sausages and bacon!</td>\n", " <td>food</td>\n", " <td>0</td>\n", " </tr>\n", " <tr>\n", " <th>5</th>\n", " <td>The brown fox is quick and the blue dog is lazy!</td>\n", " <td>animals</td>\n", " <td>2</td>\n", " </tr>\n", " <tr>\n", " <th>6</th>\n", " <td>The sky is very blue and the sky is very beautiful today</td>\n", " <td>weather</td>\n", " <td>1</td>\n", " </tr>\n", " <tr>\n", " <th>7</th>\n", " <td>The dog is lazy but the brown fox is quick!</td>\n", " <td>animals</td>\n", " <td>2</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " Document \\\n", "0 The sky is blue and beautiful. \n", "1 Love this blue and beautiful sky! \n", "2 The quick brown fox jumps over the lazy dog. \n", "3 A king's breakfast has sausages, ham, bacon, eggs, toast and beans \n", "4 I love green eggs, ham, sausages and bacon! \n", "5 The brown fox is quick and the blue dog is lazy! \n", "6 The sky is very blue and the sky is very beautiful today \n", "7 The dog is lazy but the brown fox is quick! \n", "\n", " Category ClusterLabel \n", "0 weather 1 \n", "1 weather 1 \n", "2 animals 2 \n", "3 food 0 \n", "4 food 0 \n", "5 animals 2 \n", "6 weather 1 \n", "7 animals 2 " ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.cluster import KMeans\n", "\n", "\n", "doc_glove_vectors = np.array([nlp(str(doc)).vector for doc in norm_corpus])\n", "\n", "km = KMeans(n_clusters=3, random_state=0)\n", "km.fit_transform(doc_glove_vectors)\n", "cluster_labels = km.labels_\n", "cluster_labels = pd.DataFrame(cluster_labels, columns=['ClusterLabel'])\n", "pd.concat([corpus_df, cluster_labels], axis=1)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">El modelo FastText</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "El modelo [FastText](https://fasttext.cc/) fue introducido por primera vez por Facebook en 2016 como una extensión y supuestamente una mejora del modelo vainilla de Word2Vec. \n", "\n", "Está basado en el artículo original titulado [Enriching Word Vectors with Subword Information](https://arxiv.org/pdf/1607.04606.pdf) de Mikolov et al. que es una lectura excelente para obtener una comprensión profunda de cómo funciona este modelo. En general, FastText es un marco para el aprendizaje de representaciones de palabras y también para realizar una clasificación de texto sólida, rápida y precisa. \n", "\n", "El marco es de código abierto de Facebook en GitHub y afirma tener lo siguiente.\n", "\n", "1. Vectores de palabras en inglés de última generación.\n", "2. Vectores de palabras para 157 idiomas entrenados en Wikipedia y rastreo.\n", "3. Modelos para identificación de idiomas y diversas tareas supervisadas.\n", "\n", "De acuedo con los autores, en general, los modelos predictivos como el modelo *Word2Vec* suelen considerar cada palabra como una entidad distinta (por ejemplo, dónde) y generan una incrustación densa para la palabra. \n", "\n", "Sin embargo, esto representa una seria limitación con los idiomas que tienen un vocabulario masivo y muchas palabras raras que pueden no aparecer mucho en diferentes corpus. El modelo Word2Vec normalmente ignora la estructura morfológica de cada palabra y considera una palabra como una sola entidad. \n", "\n", "El modelo **FastText** considera cada palabra como una bolsa de n-gramas de caracteres. Esto también se denomina modelo de subpalabras en el documento.\n", "\n", "\n", "Se agregan símbolos de límites especiales <y> al principio y al final de las palabras. Esto permite distinguir prefijos y sufijos de otras secuencias de caracteres. También incluiyen la propia palabra *w* en el conjunto de sus n-gramas, para aprender una representación de cada palabra (además de su carácter n-gramas). \n", " \n", " \n", "Tomando la palabra *where* y n = 3 (tri-gramas) como ejemplo, estará representada por el carácter n-gramas: <wh, whe, her, ere, re> y la secuencia especial <where> que representa la palabra completa . \n", " \n", " Tenga en cuenta que la secuencia, correspondiente a la palabra <her> es diferente del trigrama ella de la palabra where.\n", " \n", "En la práctica, el artículo recomienda extraer todos los n-gramas para $3\\le n \\le 6$ Este es un enfoque muy simple, y se podrían considerar diferentes conjuntos de n-gramas, por ejemplo, tomando todos los prefijos y sufijos. \n", " \n", "Normalmente asociamos una representación vectorial (incrustación) a cada n-grama de una palabra. Por tanto, podemos representar una palabra mediante la suma de las representaciones vectoriales de sus n-gramas o el promedio de la incrustación de estos n-gramas. \n", " \n", "Según los autores, debido a este efecto de aprovechar los n-gramas de palabras individuales basadas en sus caracteres, existe una mayor probabilidad de que las palabras raras obtengan una buena representación, ya que sus n-gramas basados en caracteres deben aparecer en otras palabras del corpus.\n", " \n", "Vamos a la práctica." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### <span style=\"color:#4CC9F0\">Gráfico basado en ACP</span>" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "image/png": "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3LgRgPT09Ku6z4IFCwgLC2PDhg20adOGLVu22M8dPny4QmIVERERERG5Hjg5OgCR6mD48OEkJyfbl4ScLbp5paZMmcKDDz4InJ6FMXfuXACaNGlCvXr1qF27tupYiIiIiIiIAMbviwJWJVar1UxLS3N0GCIiIiIiIiJyDsMw0k3TtF7LMTTDQm5Y3T7oxpq9ayg+UUytmrXodHsnlvVf5uiwREREREREBCUs5AbV7YNufPPjN/y1x1/xdPckryCP9796n24fdKvUpEVJSQlOTvo2FBERERER+b0KKbopUt2s2buGR+99FO9m3lgsFrybefPovY+yZu+aCh3nxRdfpFWrVkRFRfHwww+TmJhIREQE//jHP7jnnnt4/fXXWbx4Me3btycwMJCuXbuyf/9+AIqKivjLX/6Cn58f/v7+LFiwAIBly5bRoUMHgoKCePDBBykqKqrQmEVERERERKoC/WpXbkjFJ4rxdPcs0+bp7knxieIKGyMtLY0FCxawadMmSkpKCAoKol27dgAcOnSI1atXA/DLL7/wzTffYBgG77zzDpMmTeLf//43L774IjfffDNZWVn2fgcPHuSll15ixYoV1KlTh3/9619MnjyZcePGVVjcIiIiIiIiVYESFnJDqlWzFnkFeXg387a35RXkUatmrQobY+3atTzwwAO4uroCcP/999vPxcTE2D/v3buXmJgY9u3bx4kTJ/Dw8ABgxYoVzJs3z96vfv36LFmyhK1btxIWFgbAiRMn6NChQ4XFLCIiIiIiUlVoSYjckDrd3on3v3qfnD05lJaWkrMnh/e/ep9Ot3eqsDEutQNPnTp17J+HDx/OsGHDyMrK4q233qK4uNh+vWEY590zKiqKjIwMMjIy2Lp1K7NmzaqwmEVERERERKoKJSzkhrSs/zJCbgth1n9m8fdpf2fWf2YRcltIhRbc7NixI4sXL6a4uJiioiL+85//XLDf4cOHadq0KQDvvfeevb1bt25MnTrVfvzLL78QEhLCunXryM3NBeC3335jx44dFRaziIiIiIhIVaElIXLDuta7gdx9991ER0fTtm1bmjdvjtVq5eabbz6v3/jx43nwwQdp2rQpISEh7Nq1C4AXXniBoUOH4uvri8ViIT4+nj59+jBnzhwefvhhjh8/DsBLL71Ey5Ytr+mziIiIiIiIVDbjUtPWHc1qtZppaWmODkPkqhUVFeHm5sZvv/1GeHg4M2fOJCgoyNFhiYiIiIiIlIthGOmmaVqv5RhaEiJyBZKykvCZ5oNlggWfaT4kZSVdsv8TTzxBQEAAQUFB9O3bV8kKERERERGRy6QlISKXKSkribiVcdgibQx2H0xeQR5xK+MAiPWLvfA1SZdOaIiIiIiIiMiFaYaFyGVKSE3AFmnDu5k3FosF72be2CJtJKQmODo0ERERERGR644SFiKXKbcwF093zzJtnu6e5BbmOigiERERERGR65cSFiKXyauhF3kFeWXa8gry8Gro5aCIRERERERErl9KWIhcpvjweJJTksnZk0NpaSk5e3JITkkmPjze0aGJiIiIiIhcd5SwELlMsX6xTO4ymeVrlvPM9GdYvmY5k7tMvmjBzepgypQp3HXXXfTr1++C59PS0hgxYgQAq1atYv369fZzAwcOJDk5uVLi20PVmgAAIABJREFUFBERERGRG492CRG5ArF+sdU6QfF706dP54svvsDDw+OC561WK1br6a2VV61ahZubG6GhoZUZooiIiIiI3KA0w0LkBvXkk0+Sl5dHdHQ0//rXvwgNDSUwMJDQ0FCys7OB00mKnj17kp+fz4wZM/i///s/AgICWLNmDQCpqamEhobi6emp2RYiIiIiIlKhNMNC5AY1Y8YMvvzyS77++mtq1qzJ3//+d5ycnFixYgX/+Mc/WLBggb1vixYtePLJJ3Fzc2PUqFEAzJo1i3379rF27Vq2b99OdHQ0NpvNUY8jIiIiIiLXGSUsRITDhw8zYMAAcnJyMAyDkydPXtZ1vXr1okaNGrRu3Zr9+/df4yhFRERERORGoiUhIsLYsWPp3LkzmzdvZvHixRQXF1/WdS4uLvbPpmleq/BEREREROQGpISFiHD48GGaNm0KwJw5cy7Yp27duhw5cqQSoxIRERERkRuZEhYiwrPPPstzzz1HWFgYpaWlF+xz//33s3DhwjJFN0VERERERK4VoypP47ZarWZaWpqjwxCpNpKykkhITSC3MBevhl7Eh8dfV9uwioiIiIhI1WAYRrppmtZrOYaKbopcJ5KykohbGYct0sZg98HkFeQRtzIOQEkLERERERGpdrQkROQ6kZCagC3ShnczbywWC97NvLFF2khITXB0aCIiIiIiIldMCQuR60RuYS6e7p5l2jzdPcktzHVQRCIiIiIiIldPCQuR64RXQy/yCvLKtOUV5OHV0MtBEYmIiIiIiFw9JSxErhPx4fEkpySTsyeH0tJScvbkkJySTHx4vKNDExERERERuWIquilynThbWPPcXUImd5msgpsiIiIiIlItaVtTEREREREREbkilbGtqZaEiFyF0NBQR4cgIiIiIiJyXVPCQuQqrF+/3tEhXDNz5syhoKDA0WGIiIiIiMgNTgkLkavg5uYGwKuvvsrdd9+Nv78/8fGni1sePXqUHj160LZtW3x9fZk/fz4ALVq04ODBgwCkpaUREREBwOrVqwkICCAgIIDAwECOHDlS+Q90jqtJWJSUlFyjaERERERE5EalopsiV2nZsmXk5OSwceNGTNMkOjqa1NRUDhw4gLu7O//5z38AOHz48CXvk5iYyLRp0wgLC6OoqIhatWpVaJz5+fl0796d9u3bs2nTJlq2bMn777/Ptm3biIuLo6ioiEaNGjFnzhzWrVtHWloa/fr1w9XVlQ0bNrB169bz+jVp0oSIiAhCQ0NZt24d0dHR/P3vf6/QuEVERERE5MamGRYiV2nZsmUsW7aMwMBAgoKC2L59Ozk5Ofj5+bFixQpGjx7NmjVruPnmmy95n7CwMOLi4pgyZQqHDh3Cyani84jZ2dk88cQTZGZmctNNNzFt2jSGDx9OcnIy6enpDBo0iOeffx6bzYbVamXu3LlkZGTg5OR0wX5nHTp0iNWrVytZISIiIiIiFU4zLESukmmaPPfccwwePPi8c+np6SxdupTnnnuObt26MW7cOJycnDh16hQAxcXF9r5jxoyhR48eLF26lJCQEFasWEGrVq0qNNZmzZoRFhYGwCOPPMLLL7/M5s2biYqKAqC0tJQmTZqcd112dvYl+8XExFRonCIiIiIiImcpYSFyle69917Gjh1Lv379cHNz43//+x/Ozs6UlJTQoEEDHnnkEdzc3JgzZw5wuoZFeno69913HwsWLLDfZ+fOnfj5+eHn58eGDRvYvn17hScsDMMoc1y3bl3atGnDhg0bLnmdaZqX7FenTp0Ki1FERERERORcWhIichUMw6Bbt27ExsbSoUMH/Pz8sNlsHDlyhKysLIKDgwkICGDixIm88MILAMTHxzNy5Eg6deqExWKx3+u1117D19eXtm3b4urqyn333Vfh8f7www/2pMNHH31ESEgIBw4csLedPHmSLVu2AKeTGWcLf/r4+Fy0n4iIiIiIyLVkmKbp6Bguymq1mmlpaY4OQ65zSVlJJKQmkFuYi1dDL+LD44n1i71o/8LCQoKCgti9e3clRnn18vPz+dOf/kR4eDjr16/H29ubDz74gB07djBixAgOHz5MSUkJTz/9NI8//jgLFizgH//4h73oZnZ29gX7RUREkJiYiNVqdfQjioiIiIhIJTMMI900zWv6w4ASFnJDS8pKIm5lHLZIG57unuQV5JGckszkLpMvmLQoKCggIiKC4cOHM3z4cAdEfOUJlvz8fHr27MnmzZsrMUoREREREbmeVUbCQjUs5IaWkJqALdKGdzNvALybeWOLtJGQmnDBJIC7uzs7duyo7DDtzk2wDHYfTF5BHnEr4wAumbQQERERERGpblTDQm5ouYW5eLp7lmnzdPcktzDXQRFd2rkJFovFUibBcjEtWrTQ7AoREREREal2lLCQG5pXQy/yCvLKtOUV5OHV0MtBEV1adUuwiIiIiIiIXC0lLOSGFh8eT3JKMjl7cigtLSVnTw7JKcnEh8c7OrQLqm4JFhERufamTJnCXXfdRdOmTRk2bFiF3NPNza1C7iMiIlIeqmEhN7SzdR/OLWJ5sYKbVUF8ePxFi4SKiMiNafr06XzxxResXr0aFSsXEZHriRIWcsOL9YutsgmK36tuCRYREbm2nnzySfLy8oiOjmbQoEH29t27dzNo0CAOHDhA48aNeffdd7njjjsu2r5r1y5iY2MpKSmhe/fuDnwiERGR/09LQkSqmVi/WLKHZlM6rpTsodlKVoiI3MBmzJiBu7s7X3/9NfXr17e3Dxs2jEcffZTMzEz69evHiBEjLtk+cuRIhgwZwnfffcdtt93mkGcRERH5PcM0TUfHcFFWq9XU1EYRxxk/fjxubm78+uuvhIeH07Vr1yu6PjQ0lPXr11+yT4sWLUhLS6NRo0blCVVE5IZ19r+jS5YsIS0tjalTp9KoUSP27duHs7MzJ0+epEmTJhw8ePCi7Q0bNuTHH3/E2dmZX3/9FXd3d4qKihz9aCIiUoUZhpFumqb1Wo6hJSEi8ocmTJhwVdf9UbJCREQqh2EYf9h+sT4iIiKOUiFLQgzD6G4YRrZhGLmGYYy5wHkXwzDmnzn/rWEYLSpiXBGpeBMnTsTHx4euXbuSnZ0NwMCBA0lOTgZgzJgxtG7dGn9/f0aNGgXA/v376d27N23btqVt27b2RMXZKvOrVq0iPDyc3r1707p1a5588klOnTp13tgffvghwcHBBAQEMHjwYEpLSyktLWXgwIH4+vri5+fH//3f/1XGaxARqdZCQ0OZN28eAHPnzqVjx46XbA8LCyvTLiIiUhWUe4aFYRgWYBoQBewFvjMM43PTNLee0+2vwC+maXoZhvEQ8C8gprxji0jFSk9PZ968eWzatImSkhKCgoJo166d/fzPP//MwoUL2b59O4ZhcOjQIQBGjBjBPffcw8KFCyktLb3gNOKNGzeydetWmjdvTvfu3fn000+x2Wz289u2bWP+/PmsW7cOZ2dnnnrqKebOnUubNm343//+x+bNmwHsY4qIyMVNmTKFQYMG8eqrr9qLa16q/fXXXyc2NpbXX3+dvn37OjJ0ERERu4pYEhIM5JqmmQdgGMY84AHg3ITFA8D4M5+TgamGYRhmVS6gIXIDWrNmDb1796Z27doAREdHlzl/0003UatWLR577DF69OhBz549AUhJSeH9998HwGKxcPPNN5937+DgYDw9PQF4+OGHWbt2bZmExcqVK0lPT+fuu+8G4NixY9xyyy3cf//95OXlMXz4cHr06EG3bt0q/sFFRKqx/Px84PRsuIEDBwKn61qkpKSc1/di7R4eHmzYsMF+PGbMeRNmRUREKl1FLAlpCuw553jvmbYL9jFNswQ4DDSsgLFFpIJdag2zk5MTGzdupG/fvixatOiKtr77/X1/f2yaJgMGDCAjI4OMjAyys7MZP3489evX5/vvvyciIoJp06bx2GOPXdkDiYhUM0lZSfhM88EywYLPNB+SspIcHZKIiIhDVETC4kI/3fx+5sTl9Dnd0TCeMAwjzTCMtAMHDpQ7OBG5fOHh4SxcuJBjx45x5MgRFi9eXOZ8UVERhw8f5k9/+hOvvfYaGRkZAHTp0oU333wTgNLSUn799dfz7r1x40Z27drFqVOnmD9/vn3d9FldunQhOTmZn376CTi9/GT37t0cPHiQU6dO0bdvX1588UX++9//XotHFxGpEpKykohbGUdUpyhefepVojpFEbcyTkkLERG5IVVEwmIv0Oyc49uBgov1MQzDCbgZ+PlCNzNNc6ZpmlbTNK2NGzeugPBE5HIFBQURExNDQEAAffv2pVOnTmXOHzlyhJ49e+Lv788999xjL4D5+uuv8/XXX+Pn50e7du3YsmXLeffu0KEDY8aMwdfXFw8PD3r37l3mfOvWrXnppZfo1q0b/v7+REVFsW/fPv73v/8RERFBQEAAAwcO5J///Oe1ewEiIg6WkJqALdKGdzNvLBYL3s28sUXaSEhNcHRoIiIilc4obxmJMwmIHUAX4H/Ad0CsaZpbzukzFPAzTfPJM0U3+5im+ec/urfVajXT0tLKFZ/IjS4pK4mE1ARyC3PxauhFfHg8sX6xlRrDqlWrSExMZMmSJZU6rohIdWOZYOHVp17FYrHY20pLS3lm+jOUjit1YGQiIiJlGYaRbpqm9VqOUe6im6ZplhiGMQz4CrAAs03T3GIYxgQgzTTNz4FZwAeGYeRyembFQ+UdV0T+2NmpxbZIG4PdB5NXkEfcyjiASk9aiIjIH/Nq6EVeQR7ezbztbXkFeXg19HJgVCIiIo5R7hkW15JmWIiUj880H6I6RZX5H9+cPTksX7Oc7KHZDoxMREQu5NxEs6e7J3kFeSSnJDO5y2QlmkVEpEqpFjMsRKTqyi3MZbD74DJtnu6e5BbmOigiERG5lLNJiXOX8ilZISIiNyolLESuY5paLCJS/cT6xSpBISIiQsXsEiIiVVR8eDzJKcnk7MmhtLSUnD05JKckEx8e7+jQRERERERELkkzLESuY5paLCIiIiIi1ZWKboqIiIiIiIjIFamMoptaEiIiIiIiIiIiVY4SFiIiIiIiIiJS5ShhISIiIiIiIiJVjhIWIiIiIiIiIlLlKGEhIiIiIiIiIlWOEhYiIiIiIiIiUuUoYSEiIiIiIiIiVY4SFiIiIiIiIiJS5ShhISIiIiIiIiJVjhIWIiIiIiIiIlLlKGEhIiIiIiIiIlWOEhYiIiIiIiIiUuUoYSEiIiIiIiIiVY4SFiIiIiIiIiJS5ShhISIiIiIiIiJVjhIWIiIiIiIiIlLlKGEhIiIiIiIiIlWOEhYiIiIiIiIiUuUoYSEiIiIiIiIiVY4SFiIiIiIiIiJS5ShhISIiIiIiIiJVjhIWIlJtHTp0iOnTp1/xdXPmzKGgoMB+3KJFCw4ePFiRoYmIiIiISDkpYSEi1dbFEhalpaWXvO73CQsREREREal6nBwdgIjI1RozZgw7d+4kICAAZ2dn3NzcaNKkCRkZGSxdupSePXuyefNmABITEykqKsLX15e0tDT69euHq6srGzZsAOCNN95g8eLFnDx5kk8++YRWrVo58tFERERERG54mmEhItXWK6+8wp133klGRgavvvoqGzduZOLEiWzduvWi19hsNqxWK3PnziUjIwNXV1cAGjVqxH//+1+GDBlCYmJiZT2CiIiIiIhchBIWInLdCA4OxsPD46qu7dOnDwDt2rUjPz+/AqMSEREREZGroYSFiFw36tSpY//s5OTEqVOn7MfFxcWXvNbFxQUAi8VCSUnJtQlQREREREQumxIWIlJt1a1blyNHjlzw3K233spPP/1EYWEhx48fZ8mSJZd1nYiIiIiIVA0quiki1VbDhg0JCwvD19cXV1dXbr31Vvs5Z2dnxo0bR/v27fHw8ChTRHPgwIE8+eSTZYpuioiIiIhI1WKYpunoGC7KarWaaWlpjg5DRCpRUlYSCakJ5Bbm4tXQi/jweGL9Yh0dloiIiIiInMMwjHTTNK3XcgzNsBCRKiMpK4m4lXHYIm0Mdh9MXkEecSvjAJS0EBERERG5waiGhYhUGQmpCdgibXg388ZiseDdzBtbpI2E1ARHhyYiIiIiIpVMCQsRqTJyC3PxdPcs0+bp7kluYa6DIhIREREREUdRwkJEqgyvhl7kFeSVacsryMOroZeDIhIREREREUdRwkJEqoz48HiSU5LJ2ZNDaWkpOXtySE5JJj483tGhiYiIiIhIJVPRTRGpMs4W1jx3l5DJXSar4KaIiIiIyA1I25qKiIiIiIiIyBWpjG1NtSRERERERERERKocJSxEREREREREpMpRwkJEREREREREqhwlLERERERERESkylHCQkRERERERESqHCUsRERERERERKTKUcJCRERERERERKocJSxEREREREREpMpRwkJEREREREREqhwlLERERERERESkyilXwsIwjAaGYSw3DCPnzNf6F+lXahhGxpk/n5dnTBERERERERG5/pV3hsUYYKVpmt7AyjPHF3LMNM2AM3+iyzmmiEi5jR8/nsTExHLfJyMjg6VLl1b4fUVEREREbnTlTVg8ALx35vN7QK9y3k9EpNooKSk5L2EhIiIiIiIVo7wJi1tN09wHcObrLRfpV8swjDTDML4xDENJDRFxiIkTJ+Lj40PXrl3Jzs4GYOfOnXTv3p127drRqVMntm/fDsDixYtp3749gYGBdO3alf379wOnZ1A88cQTdOvWjUcffZRx48Yx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", "text/plain": [ "<Figure size 1296x720 with 1 Axes>" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "from sklearn.decomposition import PCA\n", "\n", "words = sum([[k] + v for k, v in similar_words.items()], [])\n", "wvs = ft_model.wv[words]\n", "\n", "pca = PCA(n_components=2)\n", "np.set_printoptions(suppress=True)\n", "P = pca.fit_transform(wvs)\n", "labels = words\n", "\n", "plt.figure(figsize=(18, 10))\n", "plt.scatter(P[:, 0], P[:, 1], c='lightgreen', edgecolors='g')\n", "for label, x, y in zip(labels, P[:, 0], P[:, 1]):\n", " plt.annotate(label, xy=(x+0.06, y+0.03), xytext=(0, 0), textcoords='offset points')\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "¡Podemos ver muchos patrones interesantes! Noah, su hijo Shem y su abuelo Matusalén están cerca el uno del otro. \n", "\n", "También vemos a Dios asociado con Moisés y Egipto donde soportó las plagas bíblicas, incluidas el hambre y la pestilencia. También Jesús y algunos de sus discípulos están asociados muy cerca unos de otros.\n", "\n", "Para acceder a cualquiera de las incrustaciones de palabras, puede indexar el modelo con la palabra de la siguiente manera." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0.17718132, -0.19709586, 0.25530368, -0.03545383, 0.76611197,\n", " 0.13848874, -0.05604259, -0.02210611, 0.20488791, 0.17241424,\n", " -0.48582503, 0.05138803, 0.18877277, -0.05722686, 0.16079944,\n", " -0.35822144, 0.5743341 , 0.06780402, -0.3008401 , -0.01876839,\n", " 0.09861004, 0.19337818, -0.41912812, -0.09735594, 0.27861547,\n", " -0.16222528, 0.4602971 , -0.46578154, -0.1064477 , 0.42992973,\n", " 0.06472561, 0.16854142, 0.00933973, 0.04791377, 0.18041942,\n", " 0.05097766, -0.27860153, 0.11862674, 0.06555321, 0.06788372,\n", " -0.20273678, 0.40175107, -0.00107946, 0.31407824, -0.08528732,\n", " 0.0850415 , -0.47559258, 0.11246356, -0.20559783, -0.14798933,\n", " 0.14808579, -0.23450403, -0.15976913, 0.15428546, -0.17971121,\n", " 0.40536925, -0.02532636, -0.49386576, 0.20632172, -0.2625528 ,\n", " 0.00773285, 0.50493914, -0.12690398, -0.23250476, -0.41272193,\n", " -0.28254688, -0.43109837, 0.13680667, 0.2277264 , 0.3559441 ,\n", " 0.19570442, 0.04869397, 0.23427969, -0.1791803 , 0.17570105,\n", " 0.4019909 , 0.17426194, -0.06929158, 0.09311975, -0.13352323,\n", " -0.34312806, 0.46036175, 0.32394302, -0.5765276 , -0.0285289 ,\n", " -0.20002018, 0.16436048, -0.2363575 , -0.21630326, -0.35550892,\n", " -0.37143084, 0.33584678, 0.05374669, 0.0320545 , 0.1500369 ,\n", " 0.11470003, 0.50080407, -0.21105155, 0.10132139, -0.00495873],\n", " dtype=float32)" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ft_model.wv['jesus']" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Con estas incrustaciones, podemos realizar algunas tareas interesantes en lenguaje natural. Uno de estos sería encontrar similitudes entre diferentes palabras (entidades)." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.3183717\n", "0.6547534\n" ] } ], "source": [ "print(ft_model.wv.similarity(w1='god', w2='satan'))\n", "print(ft_model.wv.similarity(w1='god', w2='jesus'))" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "o también!!" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Odd one out for [ god jesus satan john ]: satan\n", "Odd one out for [ john peter james judas ]: judas\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/home/alvaro/anaconda3/envs/tf2/lib/python3.7/site-packages/gensim/models/keyedvectors.py:877: FutureWarning: arrays to stack must be passed as a \"sequence\" type such as list or tuple. Support for non-sequence iterables such as generators is deprecated as of NumPy 1.16 and will raise an error in the future.\n", " vectors = vstack(self.word_vec(word, use_norm=True) for word in used_words).astype(REAL)\n" ] } ], "source": [ "st1 = \"god jesus satan john\"\n", "print('Odd one out for [',st1, ']:', \n", " ft_model.wv.doesnt_match(st1.split()))\n", "st2 = \"john peter james judas\"\n", "print('Odd one out for [',st2, ']:', \n", " ft_model.wv.doesnt_match(st2.split()))\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Modelos de incrustaciones del Español Preentrenados</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "A continuación encontrará enlaces a incrustaciones de palabras en español calculadas con diferentes métodos y de diferentes corpus. Este trabajo es liderado en el Departamento de Ciencias de la Computación Universidad de Chile.\n", "\n", "S incluye una descripción de los parámetros utilizados para calcular las incrustaciones, junto con estadísticas simples de los vectores, vocabulario y descripción del corpus a partir del cual se calcularon las incrustaciones. \n", "\n", "Se proporcionan enlaces directos a las incrustaciones, así que consulte las fuentes originales para obtener una cita adecuada (consulte también las Referencias). Un ejemplo del uso de algunas de estas incrustaciones se puede encontrar aquí o en este tutorial (ambos en español).\n", "\n", "[dccuchile](https://github.com/dccuchile/spanish-word-embeddings/blob/master/README.md)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## <span style=\"color:#4361EE\">Conclusión</span>" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Estos ejemplos deberían darle una buena idea acerca de las estrategias más nuevas y eficientes para aprovechar los modelos de lenguaje de aprendizaje profundo para extraer características de los datos de texto y también abordar problemas como la semántica de palabras, el contexto y la escasez de datos. " ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" } }, "nbformat": 4, "nbformat_minor": 4 }