Blog
Cómo desarrollar Embeddings (Incrustaciones) de palabras con Gensim
- Publicado por: Rafael Fernandez
- Categoría: Natural Language Processing
Las Embeddings (Incrustaciones) de texto son un enfoque moderno para representar texto en el procesamiento del lenguaje natural. La incorporación de algoritmos como Word2Vec y GloVe es clave para los resultados de última generación logrados por los modelos de redes neuronales en problemas de procesamiento de lenguaje natural como la traducción automática. En esta parte del curso, descubrirás cómo entrenar y cargar modelos de incrustación de palabras para aplicaciones de procesamiento de lenguaje natural en Python utilizando Gensim. Después de completar este tutorial, tú sabrás:
- Cómo entrenar su propio modelo de Word2Vec para incrustar palabras en datos de texto.
- Cómo visualizar un modelo de incrustación de palabras capacitado utilizando el Análisis de Componentes Principales.
- Cómo cargar modelos pre-entrenados de Word2Vec y GloVe para incrustar palabras de Google y Stanford.
Resumen del tutorial de hoy
Este tutorial está dividido en las siguientes partes:
1. Incrustaciones de palabras
2. Biblioteca Gensim
3. Desarrollar Word2Vec Embedding
4. Visualizar incrustación de palabras
5. Cargar la incrustación de Word2Vec de Google
6. Cargue el GloVe Embedding de Stanford
Incrustaciones de palabras
Una incrustación de palabras es un enfoque para proporcionar una representación vectorial densa de palabras que capturan algo acerca de su significado. Las incrustaciones de palabras son una mejora con respecto a los esquemas de codificación de palabras modelo de bolsa de palabras más simples, como los recuentos de palabras y las frecuencias, que dan como resultado vectores grandes y dispersos (en su mayoría valores 0) que describen documentos pero no el significado de las palabras.
Las incrustaciones de palabras funcionan utilizando un algoritmo para entrenar un conjunto de vectores densos y continuos de longitud fija basados en un gran corpus de texto. Cada palabra está representada por un punto en el espacio de incrustación y estos puntos se aprenden y se mueven en función de las palabras que rodean a la palabra de destino. Es la definición de una palabra por parte de la compañia que permite que la palabra embebida aprenda algo sobre el significado de las palabras. La representación espacial vectorial de las palabras proporciona una proyección en la que palabras con significados similares se agrupan localmente dentro del espacio.
El uso de incrustaciones de palabras sobre otras representaciones de texto es uno de los métodos clave que ha llevado a un rendimiento revolucionario con redes neuronales profundas en problemas como la traducción automática. En este tutorial, vamos a ver cómo utilizar dos métodos diferentes de incrustación de palabras llamados Word2Vec por los investigadores de Google y GloVe por los investigadores de Stanford.
Biblioteca Gensim Python
Gensim es una librería Python de código abierto para el procesamiento de lenguaje natural, con un enfoque en el modelado de temas. Se define como “modelado temático para humanos”. Gensim fue desarrollado y es mantenido por el investigador checo de procesamiento de lenguaje natural Radim Rehurek y su compañía RaRe Technologies. No es una biblioteca de investigación de PNL que lo incluye todo como NLTK; en cambio, Gensim es un conjunto maduro, enfocado y una eficiente herramientas de PNL para el modelado de temas. Más notablemente para este tutorial, soporta una implementación de la incrustación de palabras de Word2Vec para el aprendizaje de nuevos vectores de palabras a partir de texto.
También proporciona herramientas para cargar incrustaciones de texto pre-entrenadas en unos pocos formatos y para hacer uso y consultar una incrustación cargada. Gensim puede ser instalado fácilmente usando pip. Por ejemplo, puedes instalar Gensim con pip escribiendo lo siguiente en tu línea de comandos:
sudo pip install -U gensim
Para anconda:
conda install -c anaconda gensim
Desarrollar Word2Vec Embedding
Word2Vec es un algoritmo para aprender una palabra incrustada de un corpus de texto. Hay dos algoritmos principales de entrenamiento que pueden ser usados para aprender la incrustación a partir del texto; son el Continuous Bag-of-Words (CBOW) y el skip grams. No entraremos en los algoritmos más que para decir que generalmente miran una ventana de palabras para que cada palabra objetivo proporcione contexto y, a su vez, significado para las palabras. El enfoque fue desarrollado por Tomas Mikolov, anteriormente en Google y actualmente en Facebook.
Los modelos de Word2Vec requieren mucho texto, por ejemplo, todo el corpus de Wikipedia. Sin embargo, vamos a demostrar los principios utilizando un pequeño ejemplo de texto en memoria. Gensim proporciona la clase Word2Vec para trabajar con un modelo de Word2Vec. Aprender una palabra incrustada a partir de un texto implica cargar y organizar el texto en frases y proporcionarlas al constructor de una nueva instancia de Word2Vec(). Por ejemplo:
sentences = ... model = Word2Vec(sentences)
Específicamente, cada frase debe ser simbólica, es decir, dividida en palabras y preparada (por ejemplo, tal vez prefiltrada y tal vez convertida a un caso preferido). Las oraciones pueden ser texto cargado en la memoria, o un iterador que carga progresivamente el texto, necesario para corpus de texto muy grandes. Hay muchos parámetros en este constructor; algunos argumentos notables que usted puede desear configurar son:
- tamaño: (por defecto 100) El número de dimensiones de la incrustación, por ejemplo, la longitud del vector denso para representar cada ficha (word).
- ventana: (predeterminado 5) La distancia máxima entre una palabra de destino y las palabras alrededor de la palabra de destino.
recuento mínimo: (predeterminado 5) El número mínimo de palabras a considerar cuando se entrena el modelo; las palabras con una ocurrencia menor a este número serán ignoradas. - trabajadores: (por defecto 3) El número de hilos a utilizar durante el entrenamiento
- sg: (por defecto 0 o CBOW) El algoritmo de entrenamiento, ya sea CBOW (0) o skip gram (1).
Los valores predeterminados son a menudo suficientemente buenos cuando se acaba de empezar. Si tienes muchos núcleos, como la mayoría de los ordenadores modernos, te recomiendo encarecidamente que aumentes el número de trabajadores para que coincida con el número de núcleos (por ejemplo, 8). Después de que el modelo es entrenado, es accesible a través del atributo wv. Este es el modelo vectorial de la palabra real en el que se pueden realizar consultas. Por ejemplo, puede imprimir el vocabulario aprendido de tokens (palabras) de la siguiente manera:
words = list(model.wv.vocab) print(words)
Puede revisar el vector incrustado para un token específico de la siguiente manera:
print(model['word'])
Finalmente, un modelo entrenado puede ser guardado en un archivo llamando a la función save_word2vec_format() en la palabra modelo vectorial. Por defecto, el modelo se guarda en formato binario para ahorrar espacio. Por ejemplo:
model.wv.save_word2vec_format('model.bin')
Al empezar, puede guardar el modelo aprendido en formato ASCII y revisar el contenido. Puede hacerlo configurando binary=False cuando llame a la función save_word2vec_format(), por ejemplo:
model.wv.save_word2vec_format('model.txt', binary=False)
El modelo guardado puede ser cargado de nuevo llamando a la función Word2Vec.load(). Por ejemplo:
model = Word2Vec.load('model.bin')
Podemos relacionar todo esto con un buen ejemplo. En lugar de cargar un documento de texto grande o un corpus desde un archivo, trabajaremos con una pequeña lista en memoria de oraciones pre-tokenizado. El modelo se entrena y el número mínimo de palabras se establece en 1 para que no se ignoren las palabras. Después de aprender el modelo, resumimos, imprimimos el vocabulario, y luego imprimimos un solo vector para la palabra “frase”. Finalmente, el modelo se guarda en un archivo en formato binario, se carga y se resume.
from gensim.models import Word2Vec # define los datos de entrenamiento sentences = [['this', 'is', 'the', 'first', 'sentence', 'for', 'word2vec'], ['this', 'is', 'the', 'second', 'sentence'], ['yet', 'another', 'sentence'], ['one', 'more', 'sentence'], ['and', 'the', 'final', 'sentence']] # entrenamiento modelo model = Word2Vec(sentences, min_count=1) # summarize el modelo cargado print(model) # summarize vocabulario words = list(model.wv.vocab) print(words) # aceso al vector para una palabra print(model['sentence']) # guardamos modelo model.save('model.bin') # cargamos el modelo new_model = Word2Vec.load('model.bin') print(new_model)
Dada la naturaleza estocástica de las redes neuronales, sus resultados específicos pueden variar. Considere la posibilidad de ejecutar el ejemplo varias veces.
Word2Vec(vocab=14, size=100, alpha=0.025) ['this', 'is', 'the', 'first', 'sentence', 'for', 'word2vec', 'second', 'yet', 'another', 'one', 'more', 'and', 'final'] [ 0.00484051 -0.00060799 0.00263828 ..., -0.00405033 -0.00050171 0.00254669] Word2Vec(vocab=14, size=100, alpha=0.025)
Visualizar la incrustación (embeddings) de palabras
Después de aprender a incrustar o embeber las palabras para sus datos de texto, puede ser agradable explorarlo con una visualización. Puede usar métodos de proyección clásicos para reducir los vectores de palabras de alta dimensión a gráficos de dos dimensiones y dibujarlos en un gráfico. Las visualizaciones pueden proporcionar un diagnóstico cualitativo para su modelo aprendido. Podemos recuperar todos los vectores de un modelo entrenado de la siguiente manera:
X = model[model.wv.vocab]
Luego podemos entrenar un método de proyección sobre los vectores, como los métodos que se ofrecen en scikit-learn, y luego usar Matplotlib para trazar la proyección como una gráfica de dispersión. Veamos un ejemplo con el Análisis de Componentes Principales o PCA.
Trazar vectores de palabras usando PCA
Podemos crear un modelo PCA bidimensional de los vectores de la palabra usando la clase PCA de scikit-learn como sigue.
pca = PCA(n_components=2) result = pca.fit_transform(X)
La proyección resultante se puede trazar usando Matplotlib de la siguiente manera, sacando las dos dimensiones como coordenadas x e y.
pyplot.scatter(result[:, 0], result[:, 1])
Podemos ir un paso más allá y anotar los puntos del gráfico con las propias palabras.
words = list(model.wv.vocab) for i, word in enumerate(words): pyplot.annotate(word, xy=(result[i, 0], result[i, 1]))
Poniendo todo esto junto con el modelo de la sección anterior, el ejemplo completo se enumera a continuación.
from gensim.models import Word2Vec from sklearn.decomposition import PCA from matplotlib import pyplot # definir los datos de formación sentences = [['this', 'is', 'the', 'first', 'sentence', 'for', 'word2vec'], ['this', 'is', 'the', 'second', 'sentence'], ['yet', 'another', 'sentence'], ['one', 'more', 'sentence'], ['and', 'the', 'final', 'sentence']] # modelo de entrenamiento model = Word2Vec(sentences, min_count=1) # ajustar un modelo de PCA 2d a los vectores X = model[model.wv.vocab] pca = PCA(n_components=2) result = pca.fit_transform(X) # create a scatter plot of the projection pyplot.scatter(result[:, 0], result[:, 1]) words = list(model.wv.vocab) for i, word in enumerate(words): pyplot.annotate(word, xy=(result[i, 0], result[i, 1])) pyplot.show()
Al ejecutar el ejemplo se crea un gráfico de dispersión con los puntos anotados con las palabras. Es difícil sacar mucho significado del gráfico dado que se utilizó un corpus tan pequeño para encajar en el modelo.
Dada la naturaleza estocástica de las redes neuronales, sus resultados específicos pueden variar. Considere la posibilidad de ejecutar el ejemplo varias veces.
Cargar la incrustación de Word2Vec de Google
Entrenar sus propios vectores de palabras puede ser el mejor enfoque para un problema de PNL dado, pero puede llevar mucho tiempo. Una alternativa es simplemente usar una inserción de palabras pre-entrenada existente. Google publicó un modelo de Word2Vec previamente entrenado en el Proyecto de Código de Google de Word2Vec.
Un modelo pre-entrenado no es más que un archivo que contiene tokens y sus vectores de palabras asociados. El modelo pre-entrenado de Google Word2Vec fue entrenado con datos de noticias de Google (cerca de 100 mil millones de palabras); contiene 3 millones de palabras y frases y fue ajustado usando vectores de palabras de 300 dimensiones. Es un archivo de 1.53 Gigabytes. Lo puedes descargar desde aquí.
Descomprimido, el archivo binario (GoogleNews-vectoress-negativo300.bin) es de 3.4 Gigabytes. La librería Gensim proporciona herramientas para cargar este archivo. Específicamente, puede llamar a la función KeyedVectors.load_word2vec_format() para cargar este modelo en la memoria, por ejemplo:
from gensim.models import KeyedVectors filename = 'GoogleNews-vectors-negative300.bin' model = KeyedVectors.load_word2vec_format(filename, binary=True)
Tenga en cuenta que este ejemplo puede requerir un PC con 8 o más Gigabytes de RAM para ejecutarse. En mi moderno PC, tarda unos 43 segundos en cargarse. Otra cosa interesante que puedes hacer es hacer un poco de aritmética de álgebra lineal con palabras. Por ejemplo, un ejemplo popular descrito en conferencias y documentos de introducción es:
queen = (king - man) + woman
Esa es la palabra reina, es la palabra más cercana dada la sustracción de la noción de hombre del rey y añadiendo la palabra mujer. La masculinidad en el rey es reemplazada por la feminidad para darnos a la reina. Un concepto muy guay. Gensim proporciona una interfaz para realizar este tipo de operaciones en la función most_similar() en el modelo entrenado o cargado. Por ejemplo:
result = model.most_similar(positive=['woman', 'king'], negative=['man'], topn=1) print(result)
Podemos poner todo esto junto de la siguiente manera.
from gensim.models import KeyedVectors # cargar el modelo de google word2vec filename = 'GoogleNews-vectors-negative300.bin' model = KeyedVectors.load_word2vec_format(filename, binary=True) # calcular: (king - man) + woman = ? result = model.most_similar(positive=['woman', 'king'], negative=['man'], topn=1) print(result)
Ejecutando el ejemplo se carga el modelo Word2Vec pre-entrenado de Google y luego se calcula la operación (( king – man ) + woman = ?) en la palabra vectores para esas palabras. La respuesta, como cabría esperar, es reina.
[('queen', 0.7118192315101624)]
Te animamos a seguir explorando estas arítmeticas interesantes.
Cargue el GloVe Embedding de Stanford
Los investigadores de Stanford también tienen su propio algoritmo de incrustación de palabras como Word2Vec llamado Vectores Globales para la Representación de Palabras, o GloVe para abreviar. No voy a entrar en los detalles de las diferencias entre Word2Vec y GloVe aquí, pero en general, los practicantes de PNL parecen preferir GloVe por el momento basado en resultados.
Al igual que Word2Vec, los investigadores de GloVe también proporcionan vectores de palabras pre-entrenados, en este caso, una gran selección para elegir. Puedes descargar los vectores de palabras previamente entrenados de GloVe y cargarlos fácilmente con Gensim. El primer paso es convertir el formato de archivo GloVe al formato de archivo Word2Vec. La única diferencia es la adición de una pequeña línea de encabezado. Esto se puede hacer llamando a la función glove2word2vec(). Por ejemplo (note, este ejemplo es sólo una demostración con un nombre de archivo de entrada simulado):
from gensim.scripts.glove2word2vec import glove2word2vec glove_input_file = 'glove.txt' word2vec_output_file = 'word2vec.txt' glove2word2vec(glove_input_file, word2vec_output_file)
Una vez convertido, el archivo se puede cargar igual que el archivo de Word2Vec anterior. Hagamos esto concreto con un ejemplo. Puede descargar el modelo más pequeño de GloVe ya entrenado desde el sitio web de GloVe, concretamente desde aquí. Es un archivo zip de 822 Megabytes con 4 modelos diferentes (vectores de 50, 100, 200 y 300 dimensiones) entrenados con datos de Wikipedia con 6 billones de tokens y un vocabulario de 400,000 palabras.
Trabajando con la versión 100-dimensional del modelo, podemos convertir el archivo a formato Word2Vec de la siguiente manera:
from gensim.scripts.glove2word2vec import glove2word2vec glove_input_file = 'glove.6B.100d.txt' word2vec_output_file = 'glove.6B.100d.txt.word2vec' glove2word2vec(glove_input_file, word2vec_output_file)
Ahora tienes una copia del modelo GloVe en formato Word2Vec con el nombre de archivo glove.6B.100d.txt.word2vec. Ahora podemos cargarlo y realizar la misma prueba (rey – hombre) + mujer = ? que en la sección anterior. La lista completa de códigos se proporciona a continuación. Tenga en cuenta que el archivo convertido es de formato ASCII, no binario, por lo que se establece binario=Falso al cargar.
from gensim.models import KeyedVectors # cargar el modelo Stanford GloVe filename = 'glove.6B.100d.txt.word2vec' model = KeyedVectors.load_word2vec_format(filename, binary=False) # calcular: (king - man) + woman = ? result = model.most_similar(positive=['woman', 'king'], negative=['man'], topn=1) print(result)
Juntando todo esto, el ejemplo completo se muestra a continuación.
from gensim.models import KeyedVectors from gensim.scripts.glove2word2vec import glove2word2vec # convertir GloVe a formato word2vec glove_input_file = 'glove.6B.100d.txt' word2vec_output_file = 'glove.6B.100d.txt.word2vec' glove2word2vec(glove_input_file, word2vec_output_file) # cargar el modelo convertido filename = 'glove.6B.100d.txt.word2vec' model = KeyedVectors.load_word2vec_format(filename, binary=False) # calcular: (king - man) + woman = ? result = model.most_similar(positive=['woman', 'king'], negative=['man'], topn=1) print(result)
Ejecutando el ejemplo se imprime el mismo resultado de Queen.
[('queen', 0.7698540687561035)]
➡ Continúa aprendiendo de Procesamiento de Lenguaje Natural en nuestro curso:
Hola.
Una vez cargado un modelo pre-entrenado, si yo tengo un fichero con una frase por línea:
Me gusta jugar al futbol
Odio ir al colegio
No entiendo las matematicas
etc….
¿Cómo se hace para pasarlo al modelo y que me genere un vector que represente dicha frase?
Me gusta jugar al futbol -> [0.334, 5.87676, 9.123, 0.8763 …… 3.5412]
Odio ir al colegio -> [2.134, 2.87621, 3.123, 1.873 …… 0.2432]
No entiendo las matematicas -> [6.3411, 8.7676, 0.123, 0.6113 …… 4.4412]
etc…. -> [9.334, 9.87676, 5.123, 4.8763 …… 9.2412]
Hola Allan, en las lecciones del curso se explica paso a paso, te recomiendo que lo revises. Saludos!
Hola,
He seguido las indicaciones para cargar un modelo Glove en formato binario y también en formato comprimido (gz) pero aunque los “migro” sin errores parentes a formato word2vec, luego no consigo cargarlos. He probado indicando encoding utf-8 e iso-8859-1, también he probado con el método “load” y he probado a indicarle el parámetro “nicode_errors=’ignore'” al método “load_word2vec_format”. PEro siempre obtengo errores en el procesamiento del archivo, o bien porque se encuentra EOF inesperado o bien porque no reconoce algún carácter.
Por favor, ¿sabría indicarme alguien si existe alguna librería/método con el que pueda cargar modelos glove preentrenados, o bien porqué no consigo cargar uno? Sería una gran ayuda
Gracias de antemano