Saltar al contenido
Home » Desarrollo » Aprendiendo semántica en textos mediante word embedding

Aprendiendo semántica en textos mediante word embedding

El uso de redes neuronales artificiales (RNA) para problemas generales de procesamiento de lenguaje natural (NLP), se ha beneficiado ampliamente del desarrollo de word embedding. En post anteriores le hemos dado un vistazo al NLP y sus aplicaciones, así como acciones en la etapa de preprocesamiento para representar textos. Estas representaciones permiten que desde el punto de vista computacional podamos aplicar algoritmos de aprendizaje automático para resolver múltiples problemas que se abordan en textos.

Representaciones básicas de textos mediante Tokenización u One-hot encoding no son suficientes si deseamos que el modelo tenga información semántica a partir del contexto donde aparecen las palabras. Imaginemos por un momento que pudiésemos saber si una palabra es sinónimo de otra o qué tan distante está según su contexto con respecto a otras palabras en el texto. Para cualquier algoritmo de aprendizaje automático, saber esta información contribuiría a incrementar el desempeño de la tarea de minería de textos que se esté realizando. De ahí que estas representaciones se enfocan en el enriquecimiento del texto, lo que le aporta a un documento nuevas características a tener en cuenta.

Representación de palabras en espacios continuos

Los primeros enfoques utilizados con este fin tenían en cuenta la distribución de las palabras en un documento o colección de documentos (corpus). La distribución no es más que el número de veces o frecuencia que aparece una palabra en el texto. Con esta distribución, se estima la importancia de una palabra en el corpus, ya que una palabra que aparece poco se considera más importante. De estos enfoques se destaca el uso de Term frequency – Inverse document frequency (TF-IDF) y Bag of word, que le podremos dedicar más adelante un artículo. Estos enfoques son muy rápidos de aplicar a problemas de grandes volúmenes de textos, pero están limitados al no aprender semántica en los textos.

Para resolver este problema se desarrolló word embedding, los primeros aportes fueron en el año 2013 propuestos por Tomáš Mikolov en uno de sus artículos. Entre los beneficios de su propuesta era el uso de vectores densos y de baja dimensión (en comparación con la cantidad de palabras únicas). Ya que la mayoría de los conjuntos de herramientas de redes neuronales no se desenvuelven bien con vectores dispersos de muy alta dimensión. Con ello, podemos representar cada palabra como un vector de valores continuos (números reales) que almacena la información semántica de las palabras en su contexto. Su beneficio es el poder de generalización, ya que vale la pena proporcionar una representación que sea capaz de capturar estas similitudes.

Modelos de aprendizaje con redes neuronales: Word2vec

Word2Vec es un método estadístico para el aprendizaje eficiente de word embedding a partir de un corpus de texto. Fue desarrollado como respuesta para hacer más eficiente el entrenamiento basado en redes neuronales y desde entonces se ha convertido en el estándar de facto.

Se introdujeron dos modelos de aprendizaje diferentes que pueden utilizarse como parte del enfoque word2vec:

  • Continuous Bag-of-Words (CBOW).
  • Skip-Gram Model (SG).
Arquitecturas neuronales para entrenar ambos modelos de representación.

Podemos encontrar dichos modelos pre-entrenados en:


El entrenamiento de estas redes neuronales se realiza mediante aprendizaje no supervisado, utilizando como función de perdida la cross-entropy loss y con en método del gradiente descendente. Los patrones de entrenamiento de esta red neuronal se construyen a partir del contexto de las palabras:

Por ejemplo, dado el texto «The quick brown fox jumps over the lazy dog», se ha utilizado una ventana deslizante de tamaño dos. Cada palabra genera un contexto, «The» tiene como contexto a «quick» y «brown«, ya que solo abarca con la ventana dos palabras por la derecha. Sin embargo, observe como «brown» tiene dos palabras por ambos lados, ya que es lo que abarca su ventana. Eso crea para el modelo neuronal por cada palabra un patrón de entrenamiento. En CBOW, la entrada es el contexto y se intenta predecir la palabra y en SG la entrada es la palabra y se intenta predecir el contexto.

Implementemos nuestro propio word embedding

Para implementar nuestro propio word embedding haremos uso de la biblioteca NLTK y Gensim de Python. Esta última es una biblioteca especializada en esta tarea e incluye no solo word2vec sino además a Doc2Vec y FastText que son otras variantes de word embedding.

  • Importando lo escencial
import gensim
from nltk.corpus import brown
import multiprocessing

En este paso incluimos el módulo brown de NLTK, que contiene el corpus que utilizaremos durante el entrenamiento. Con multiprocessing permitiremos el procesamiento en paralelo durante el entrenamiento, aprovechando todos núcleos disponibles en el procesador.

  • Declaramos algunas variables importantes a utilizar durante el entrenamiento:
EMBEDDING_SIZE = 100 # Longitud del vector continuo de cada palabra
WINDOW = 5 # Tamaño de la ventana
MIN_COUNT = 5 # Mínima cantidad de veces que debe aparecer una palabra
NEGATIVE_SAMPLING= 15 # Un valor que afecta a la función de pérdida cross-entropy
EPOCHS = 10 # Cantidad de épocas de entrenamiento
SG = 1 # Con el valor en 1 usamos Skip-Gram y con 0 CBOW.
  • Comprobamos nuestro corpus para el entrenamiento:
print("Ejemplo de texto de para el entrenamiento")
print(brown.sents()[0])
['The', 'Fulton', 'County', 'Grand', 'Jury', 'said', 'Friday', 'an', 
'investigation', 'of', "Atlanta's", 'recent', 'primary', 'election', 
'produced', '``', 'no', 'evidence', "''", 'that', 'any', 'irregularities', 
'took', 'place', '.']
  • Entrenamos el modelo usando las variables declaradas:
model = gensim.models.Word2Vec(brown.sents(), size=EMBEDDING_SIZE, window=WINDOW, min_count=MIN_COUNT, negative=NEGATIVE_SAMPLING, iter=EPOCHS, workers=multiprocessing.cpu_count())
  • Salvamos el modelo e imprimimos algunas estadísticas:
model.save("mi_word2vec.model")
print("Created and saved word embedding model with:")
print("Tamaño del vector: {}".format(EMBEDDING_SIZE))
print(Cantidad de palabras únicas del diccionario: {}".format(len(model.wv.vocab)))
Tamaño del vector: 100
Cantidad de palabras únicas del diccionario: 15173
  • Cargando el modelo entrenado para hacerle algunas consultas:
model=gensim.models.Word2Vec.load("mi_word2vec.model")
print("Similitud entre boy y girl: ",model.wv.similarity("boy","girl"))
print("Top de palabras similares a water: ", model.wv.most_similar("water"))
print("Vector de la palabra man: ", model.wv.get_vector("man"))
Similitud entre boy y girl:  0.919191
Top de palabras similares a water:  
[('air', 0.83194899559021), ('ground', 0.8299639821052551), 
('dust', 0.8115057945251465), ('dry', 0.7994049787521362), 
('surface', 0.7900884747505188), ('ice', 0.7672476768493652), 
('hot', 0.7537508010864258), ('walls', 0.741437554359436), 
('wet', 0.7407264709472656), ('sun', 0.7356663942337036)]
Vector de la palabra man:  
[ 0.08895207  0.648118    1.7973229   2.807365   -0.6317992  -0.13499717
 -2.15859    -0.13862169 -0.12096232 -0.95102966 -0.59215033 -0.78646195
 -0.26564947  0.97024554  2.6854541   1.340262   -0.901827   -0.5066577
 -1.6477957  -1.2161238   0.681064   -0.03893075  1.1775268  -2.9097967
 -1.9022926   0.05355987  0.12212527  0.04620632 -1.5853409  -0.60269266
  0.13729249 -0.01820119  0.98207253  1.1646659   1.4513512   0.43504173
  1.4407879  -2.2422633   0.06211066 -2.002166    0.28309438 -1.0623416
 -0.44732487 -0.5322638   0.14595844  1.8399469  -1.0392781  -0.7425295
 -0.32241455  1.409138    0.5201483   0.5591094  -1.3432735   1.6159225
 -0.46725148  0.52446896 -0.9576332  -0.88540655  0.6642946   1.0675089
 -0.5902539  -0.1742977  -1.7271329  -0.12344054 -1.3329527   0.03779667
 -1.2939897  -0.744615    0.7937092  -2.9023168   1.8876182   0.31153622
  0.95729303 -0.53578573 -0.08545404 -3.1041908   3.0001442  -0.1862271
 -0.69908756 -0.19915059 -2.5418491   0.6050543  -1.4709882  -1.9290986
  0.17206691  0.9616539  -1.0647248  -1.316521    0.04690214  0.7707712
 -0.82591426  1.2038307  -2.6458154  -1.8953501  -0.6235685  -3.1435058
  0.10649446  1.2601565  -1.2547408  -1.1839168 ]

Puede observarse finalmente la cercana similitud que existe entre las palabras «boy» y «girl». Esta medida es la distancia de los vectores de las palabras calculadas por la medida de similitud del coseno. Si representamos una palabra como un vector multidimensional, a menor ángulo entre las palabras mayor valor de la similitud del coseno y más se acerca a 1. Lo que significa que esas dos palabras, hasta donde aprendió la red, son similares semánticamente.

De igual manera, podemos consultar el top de palabras similares y su distancia, al igual que conocer el vector denso de cada palabra. Este vector por palabras, sirve de entrada para el entrenamiento de algoritmos de aprendizaje automático en la minería de texto.

Los visto hasta el momento permite de manera no supervisada obtener una representación en un espacio continuo de las palabras en el texto, almacenando su semántica. Durante el entrenamiento de la red, lo importante no es el resultado de la función de pérdida en la optimización, sino los vectores de las palabras.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *