Guía paso a paso de Word2Vec con Gensim

Guía de Word2Vec con Gensim

Introducción

Hace unos meses, cuando comencé a trabajar en Office People, me interesé en los Modelos de Lenguaje, particularmente en Word2Vec. Siendo usuario nativo de Python, naturalmente me concentré en la implementación de Word2Vec de Gensim y busqué artículos y tutoriales en línea. Aplicaba directamente y duplicaba fragmentos de código de múltiples fuentes, como cualquier buen científico de datos haría. Me adentré más y más para intentar entender qué salió mal con mi método, leyendo conversaciones en Stackoverflow, los grupos de Google de Gensim y la documentación de la biblioteca.

Sin embargo, siempre pensé que faltaba uno de los aspectos más importantes para crear un modelo de Word2Vec. Durante mis experimentos, descubrí que lematizar las oraciones o buscar frases/bigrama en ellas tenía un impacto significativo en los resultados y rendimiento de mis modelos. Aunque el impacto del preprocesamiento varía según el conjunto de datos y la aplicación, decidí incluir los pasos de preparación de datos en este artículo y utilizar la fantástica biblioteca de spaCy junto con él.

Algunos de estos problemas me irritan, así que decidí escribir mi propio artículo. No prometo que sea perfecto o la mejor forma de implementar Word2Vec, solo que es mejor que gran parte de lo que hay ahí fuera.

Objetivos de Aprendizaje

  • Comprender las incrustaciones de palabras y su papel en la captura de relaciones semánticas.
  • Implementar modelos de Word2Vec utilizando bibliotecas populares como Gensim o TensorFlow.
  • Medir la similitud de palabras y calcular distancias utilizando incrustaciones de Word2Vec.
  • Explorar analogías de palabras y relaciones semánticas capturadas por Word2Vec.
  • Aplicar Word2Vec en diversas tareas de PNL, como análisis de sentimientos y traducción automática.
  • Aprender técnicas para ajustar modelos de Word2Vec para tareas o dominios específicos.
  • Manejar palabras fuera del vocabulario utilizando información de subpalabras o incrustaciones pre-entrenadas.
  • Comprender las limitaciones y compensaciones de Word2Vec, como la desambiguación del sentido de las palabras y la semántica a nivel de oraciones.
  • Profundizar en temas avanzados como las incrustaciones de subpalabras y la optimización del modelo con Word2Vec.

Este artículo fue publicado como parte del Data Science Blogathon.

Breve Sobre Word2Vec

Un equipo de investigadores de Google presentó Word2Vec en dos artículos entre septiembre y octubre de 2013. Los investigadores también publicaron su implementación en C junto con los artículos. Gensim completó la implementación en Python poco después del primer artículo.

La premisa subyacente de Word2Vec es que dos palabras con contextos similares tienen significados similares y, como resultado, una representación vectorial similar en el modelo. Por ejemplo, “perro”, “cachorro” y “cachorrito” se utilizan con frecuencia en contextos similares, con palabras circundantes similares como “bueno”, “esponjoso” o “lindo”, y por lo tanto tienen una representación vectorial similar según Word2Vec.

Basándose en esta premisa, Word2Vec se puede utilizar para descubrir las relaciones entre palabras en un conjunto de datos, calcular su similitud o utilizar la representación vectorial de esas palabras como entrada para otras aplicaciones como la clasificación de texto o el agrupamiento.

Implementación de Word2Vec

La idea detrás de Word2Vec es bastante simple. Partimos del supuesto de que el significado de una palabra se puede inferir por la compañía que mantiene. Esto es análogo al dicho “Dime con quién andas y te diré quién eres”. A continuación se muestra una implementación de Word2Vec.

Configuración del Entorno

python==3.6.3

Librerías utilizadas:

  • xlrd==1.1.0:
  • spaCy==2.0.12:
  • gensim==3.4.0:
  • scikit-learn==0.19.1:
  • seaborn==0.8:
import re  # Para el preprocesamiento
import pandas as pd  # Para el manejo de datos
from time import time  # Para cronometrar nuestras operaciones
from collections import defaultdict  # Para la frecuencia de palabras

import spacy  # Para el preprocesamiento

import logging  # Configuración de los registros para monitorear gensim
logging.basicConfig(format="%(levelname)s - %(asctime)s: %(message)s", 
                    datefmt= '%H:%M:%S', level=logging.INFO)

Conjunto de datos

Este conjunto de datos contiene información sobre los personajes, ubicaciones, detalles de los episodios y líneas de guión de más de 600 episodios de Los Simpsons que datan de 1989. Está disponible en Kaggle. (~25MB)

Preprocesamiento

Al hacer el preprocesamiento, mantendremos solo dos columnas del conjunto de datos, que son raw_character_text y spoken_words.

  • raw_character_text: el personaje que habla (útil para rastrear los pasos de preprocesamiento).
  • spoken_words: el texto sin procesar de la línea de diálogo.

Como queremos hacer nuestro propio preprocesamiento, no conservamos normalized_text.

df = pd.read_csv('../input/simpsons_dataset.csv')
df.shape

df.head()

Los valores faltantes provienen de una sección del guión donde sucede algo pero no hay diálogo. “(Springfield Elementary School: EXT. ELEMENTARY – SCHOOL PLAYGROUND – AFTERNOON)” es un ejemplo.

df.isnull().sum()

Limpieza

Para cada línea de diálogo, lematizamos y eliminamos las palabras de parada y los caracteres no alfabéticos.

nlp = spacy.load('en', disable=['ner', 'parser']) 

def cleaning(doc):
    # Lematiza y elimina las palabras de parada
    # doc debe ser un objeto de tipo spacy Doc
    txt = [token.lemma_ for token in doc if not token.is_stop]

    if len(txt) > 2:
        return ' '.join(txt)

Elimina los caracteres no alfabéticos:

brief_cleaning = (re.sub("[^A-Za-z']+", ' ', str(row)).lower() for row in df['spoken_words'])

Usando el atributo spaCy.pipe() para acelerar el proceso de limpieza:

t = time()

txt = [cleaning(doc) for doc in nlp.pipe(brief_cleaning, batch_size=5000,
                   n_threads=-1)]

print('Tiempo para limpiar todo: {} mins'.format(round((time() - t) / 60, 2)))

Para eliminar los valores faltantes y duplicados, colocamos los resultados en un DataFrame:

df_clean = pd.DataFrame({'clean': txt})
df_clean = df_clean.dropna().drop_duplicates()
df_clean.shape

Bigramas

Los bigramas son un concepto utilizado en el procesamiento del lenguaje natural y el análisis de texto. Se refieren a pares consecutivos de palabras o caracteres que aparecen en una secuencia de texto. Al analizar los bigramas, podemos obtener información sobre las relaciones entre palabras o caracteres en un texto dado.

Tomemos como ejemplo la siguiente oración: “Me encanta el helado”. Para identificar los bigramas en esta oración, observamos los pares de palabras consecutivas:

“Me encanta”

“encanta el”

“el helado”

Cada uno de estos pares representa un bigrama. Los bigramas pueden ser útiles en diversas tareas de procesamiento del lenguaje. Por ejemplo, en el modelado del lenguaje, podemos usar los bigramas para predecir la siguiente palabra en una oración basada en la palabra anterior.

Los bigramas pueden extenderse a secuencias más grandes llamadas trigramas (tercetos consecutivos) o n-gramas (secuencias consecutivas de n palabras o caracteres). La elección de n depende del análisis o tarea específica que se esté realizando.

Se está utilizando el paquete Gensim Phrases para detectar automáticamente frases comunes (bigramas) de una lista de oraciones. https://radimrehurek.com/gensim/models/phrases.html

¡Hacemos esto principalmente para capturar palabras como “mr_burns” y “bart_simpson”!

from gensim.models.phrases import Phrases, Phraser
sent = [row.split() for row in df_clean['clean']]

A continuación se generan las siguientes frases a partir de la lista de oraciones:

phrases = Phrases(sent, min_count=30, progress_per=10000)

El objetivo de Phraser() es reducir el consumo de memoria de Phrases() descartando el estado del modelo que no es estrictamente necesario para la tarea de detección de bigramas:

bigram = Phraser(phrases)

Transformar el corpus basado en los bigramas detectados:

sentences = bigram[sent]

Palabras más frecuentes

Principalmente una comprobación de la efectividad de la lematización, la eliminación de palabras vacías y la adición de bigramas.

word_freq = defaultdict(int)
for sent in sentences:
    for i in sent:
        word_freq[i] += 1
len(word_freq)

sorted(word_freq, key=word_freq.get, reverse=True)[:10]

Separar el entrenamiento del modelo en 3 pasos

Por claridad y seguimiento, prefiero dividir el entrenamiento en tres pasos distintos.

  • Word2Vec():
    • En este primer paso, configuro los parámetros del modelo uno por uno.
    • De manera intencional, dejo el modelo sin inicializar al no proporcionar el parámetro de oraciones.
  • build_vocab():
    • Inicializa el modelo construyendo el vocabulario a partir de una secuencia de oraciones.
    • Puedo seguir el progreso y, lo que es más importante, el efecto de min_count y sample en el corpus de palabras utilizando los registros. Descubrí que estos dos parámetros, especialmente sample, tienen un impacto significativo en el rendimiento del modelo. Mostrar ambos permite una gestión más precisa y sencilla de su influencia.
  • .train():
    • Finalmente, se entrena el modelo.
    • Los registros en esta página son principalmente útiles.
import multiprocessing

from gensim.models import Word2Vec

cores = multiprocessing.cpu_count() # Contar el número de núcleos en una computadora


w2v_model = Word2Vec(min_count=20,
                     window=2,
                     size=300,
                     sample=6e-5, 
                     alpha=0.03, 
                     min_alpha=0.0007, 
                     negative=20,
                     workers=cores-1)

Implementación de Gensim de word2vec: https://radimrehurek.com/gensim/models/word2vec.html

Construyendo la tabla de vocabulario

Word2Vec requiere que creemos la tabla de vocabulario (digestionando todas las palabras, filtrando las palabras únicas y realizando algunos conteos básicos en ellas):

t = time()

w2v_model.build_vocab(sentences, progress_per=10000)

print('Tiempo para construir el vocabulario: {} mins'.format(round((time() - t) / 60, 2)))

La tabla de vocabulario es crucial para codificar palabras como índices y buscar sus correspondientes embeddings de palabras durante el entrenamiento o inferencia. Forma la base para entrenar modelos Word2Vec y permite una representación eficiente de palabras en el espacio vectorial continuo.

Entrenamiento del modelo

El entrenamiento de un modelo Word2Vec implica alimentar un corpus de datos de texto en el algoritmo y optimizar los parámetros del modelo para aprender los embeddings de palabras. Los parámetros de entrenamiento para Word2Vec incluyen varios hiperparámetros y configuraciones que afectan el proceso de entrenamiento y la calidad de los embeddings de palabras resultantes. Aquí hay algunos parámetros de entrenamiento comúnmente utilizados para Word2Vec:

  • total_examples = int – El número de oraciones;
  • epochs = int – El número de iteraciones (épocas) sobre el corpus – [10, 20, 30]
t = time()

w2v_model.train(sentences, total_examples=w2v_model.corpus_count, epochs=30, report_delay=1)

print('Tiempo para entrenar el modelo: {} mins'.format(round((time() - t) / 60, 2)))

Llamamos a init_sims() para hacer que el modelo sea mucho más eficiente en memoria ya que no tenemos la intención de entrenarlo aún más:

w2v_model.init_sims(replace=True)

Estos parámetros controlan aspectos como el tamaño de la ventana de contexto, el equilibrio entre palabras frecuentes y raras, la tasa de aprendizaje, el algoritmo de entrenamiento y el número de muestras negativas para el muestreo negativo. Ajustar estos parámetros puede afectar la calidad, eficiencia y requisitos de memoria del proceso de entrenamiento de Word2Vec.

Explorando el modelo

Una vez que se entrena un modelo Word2Vec, se puede explorar para obtener información sobre los embeddings de palabras aprendidos y extraer información útil. Aquí hay algunas formas de explorar el modelo Word2Vec:

Más similar a

En Word2Vec, se pueden encontrar las palabras más similares a una palabra dada en función de los embeddings de palabras aprendidos. La similitud se calcula típicamente utilizando la similitud del coseno. Aquí hay un ejemplo de cómo encontrar las palabras más similares a una palabra objetivo utilizando Word2Vec:

Veamos lo que obtenemos para el personaje principal del programa:

similar_words = w2v_model.wv.most_similar(positive=["homer"])
for word, similarity in similar_words:
    print(f"{word}: {similarity}")

Para ser claros, cuando miramos las palabras que son más similares a “homer”, no necesariamente obtenemos a sus miembros de la familia, rasgos de personalidad o incluso sus citas más memorables.

Comparemos eso con lo que devuelve el bigrama “homer_simpson”:

w2v_model.wv.most_similar(positive=["homer_simpson"])

¿Y ahora Marge?

w2v_model.wv.most_similar(positive=["marge"])

Veamos ahora a Bart:

w2v_model.wv.most_similar(positive=["bart"])

Parece que tiene sentido!

Similitudes

Aquí hay un ejemplo de cómo encontrar la similitud del coseno entre dos palabras usando Word2Vec:

Ejemplo: Calculando la similitud del coseno entre dos palabras.

w2v_model.wv.similarity("moe_'s", 'tavern')

¿Quién podría olvidar la taberna de Moe? No Barney.

w2v_model.wv.similarity('maggie', 'baby')

¡Maggie es de hecho el bebé más famoso de los Simpsons!

w2v_model.wv.similarity('bart', 'nelson')

Bart y Nelson, aunque son amigos, no son tan cercanos, ¡tiene sentido!

El diferente

Aquí, le pedimos a nuestro modelo que nos dé la palabra que no pertenece a la lista.

Entre Jimbo, Milhouse y Kearney, ¿quién no es un matón?

w2v_model.wv.doesnt_match(['jimbo', 'milhouse', 'kearney'])

¿Y si comparamos la amistad entre Nelson, Bart y Milhouse?

w2v_model.wv.doesnt_match(["nelson", "bart", "milhouse"])

¡Parece que Nelson es el diferente aquí!

Por último, pero no menos importante, ¿cómo es la relación entre Homer y sus cuñadas?

w2v_model.wv.doesnt_match(['homer', 'patty', 'selma'])

¡Dios, realmente no les caes bien a Homer!

Diferencia de analogía

¿Qué palabra es para mujer como Homero es para Marge?

w2v_model.wv.most_similar(positive=["woman", "homer"], negative=["marge"], topn=3)

“hombre” ocupa la primera posición, ¡eso parece correcto!

¿Qué palabra es para mujer como Bart es para hombre?

w2v_model.wv.most_similar(positive=["woman", "bart"], negative=["man"], topn=3)

Lisa es la hermana de Bart, su contraparte masculina.

Conclusión

En conclusión, Word2Vec es un algoritmo ampliamente utilizado en el campo del procesamiento del lenguaje natural (NLP) que aprende incrustaciones de palabras al representar las palabras como vectores densos en un espacio vectorial continuo. Captura relaciones semánticas y sintácticas entre palabras basadas en sus patrones de co-ocurrencia en un corpus de texto grande.

Word2Vec funciona utilizando el modelo Continuous Bag-of-Words (CBOW) o el modelo Skip-gram, que son arquitecturas de redes neuronales. Los word embeddings, generados por Word2Vec, son representaciones vectoriales densas de palabras que codifican información semántica y sintáctica. Permiten realizar operaciones matemáticas como el cálculo de similitud entre palabras y se pueden usar como características en varias tareas de procesamiento del lenguaje natural (NLP).

Puntos clave

  • Word2Vec aprende word embeddings, representaciones vectoriales densas de palabras.
  • Analiza patrones de co-ocurrencia en un corpus de texto para capturar relaciones semánticas.
  • El algoritmo utiliza una red neuronal con el modelo CBOW o Skip-gram.
  • Los word embeddings permiten el cálculo de similitud entre palabras.
  • Se pueden usar como características en varias tareas de NLP.
  • Word2Vec requiere un corpus de entrenamiento grande para obtener embeddings precisos.
  • No captura la desambiguación del sentido de las palabras.
  • No se considera el orden de las palabras en Word2Vec.
  • Las palabras fuera del vocabulario pueden plantear desafíos.
  • A pesar de sus limitaciones, Word2Vec tiene aplicaciones significativas en NLP.

Aunque Word2Vec es un algoritmo poderoso, tiene algunas limitaciones. Requiere una gran cantidad de datos de entrenamiento para aprender embeddings precisos de palabras. Trata cada palabra como una entidad atómica y no captura la desambiguación del sentido de las palabras. Las palabras fuera del vocabulario pueden plantear un desafío, ya que no tienen embeddings preexistentes.

Word2Vec ha contribuido significativamente a los avances en NLP y continúa siendo una herramienta valiosa para tareas como la recuperación de información, el análisis de sentimientos, la traducción automática y más.

Preguntas frecuentes

Los medios mostrados en este artículo no son propiedad de Analytics Vidhya y se utilizan bajo la discreción del autor.

We will continue to update Zepes; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Aprendizaje Automático

¡Hola GPU, ¿qué hay de mi matriz?

Multiplicación de matrices; el Santo Grial de las redes neuronales profundas y los gigantes modernos de la comprensió...

Inteligencia Artificial

Pythia Un conjunto de 16 LLMs para investigación en profundidad

Pythia es un conjunto de 16 modelos de lenguaje grandes de Eleuther AI. Ayuda a comprender y analizar modelos de leng...

Ciencias de la Computación

Europa avanza en la regulación de la IA, desafiando el poder de los gigantes tecnológicos.

Bruselas presentó un nuevo desafío antimonopolio contra Google el mismo día en que los legisladores europeos votaron ...

Inteligencia Artificial

6 Podcasts de GenAI que deberías estar escuchando

Introducción En el paisaje en constante evolución de la inteligencia artificial, el campo de la IA generativa (GenAI)...

Inteligencia Artificial

La Declaración de Bletchley de los países que asistieron a la Cumbre de Seguridad de la IA

Damos la bienvenida a los esfuerzos internacionales pertinentes para examinar y abordar el posible impacto de los sis...