¿Cuál es la mejor implementación distribuida de Word2Vec: Gensim o Spark?

Según este documento, Sistema de capacitación de Word2vec distribuido eficiente en red para vocabularios grandes, junio de 2016, no existe una implementación distribuida verdaderamente eficiente de word2vec, aunque se podría implementar en la línea descrita en el documento

Las implementaciones actuales, citando textualmente textualmente con enlaces

Sistemas de máquinas individuales . Varios sistemas de entrenamiento word2vec existentes se limitan a ejecutarse en una sola máquina, aunque con múltiples hilos paralelos de ejecución que operan en diferentes segmentos de datos de entrenamiento.

Estos incluyen la implementación original de código abierto de word2vec (implementación original), así como las de Medallia (medallia / Word2VecJava) y Rehurek ( aprendizaje profundo con Word2Vec y gensi Deep learning con word2vec y gensim ) . Como se mencionó en la introducción, estos sistemas requerirían configuraciones de memoria mucho más grandes que las disponibles en los servidores típicos a escala comercial.

Datos paralelos distribuidos Un inconveniente similar se aplica a los sistemas de entrenamiento de datos paralelos distribuidos como los disponibles en Apache Spark MLLib Feature Extraction and Transformation – API basada en RDD y Deeplearning4j Neural Word Embeddings. En el primero, en cada iteración, el controlador Spark envía los últimos vectores a todos los ejecutores de Spark. Cada ejecutor modifica su copia local de vectores en función de su partición del conjunto de datos de entrenamiento, y el controlador luego combina modificaciones de vectores locales para actualizar los vectores globales. Requiere que todos los vectores se almacenen en la memoria de todos los ejecutores de Spark y, de manera similar a sus contrapartes de máquinas individuales, no es adecuado para vocabularios grandes. El sistema Deeplearning4j adopta un enfoque similar y, por lo tanto, presenta las mismas limitaciones, aunque sí permite el uso de GPU para acelerar el entrenamiento en cada máquina.

  • El problema fundamental de hacer distribuida la implementación de word2vec es el hecho de que el recuento único de palabras crece a 200 millones, se requeriría, para un vector de 300 dimensiones de flotantes (4 bytes) y con el vector de contexto para cada palabra, un total de 200 * 300 * 4 * 2 = 480 GB que está muy por encima de la capacidad de servidor típica disponible en la actualidad
  • Las implementaciones típicas abordan este problema al dividir el vocabulario en pequeños fragmentos y alojarlos en diferentes servidores.
  • Esto tiene un gran inconveniente en que el proceso de capacitación ( skipgram o CBOW ) requiere el cálculo del producto de puntos para cada vector de palabras en una ventana de palabras vecinas, que requiere la transmisión del vector de palabras a través de los servidores.
  • Este documento propone una implementación inteligente en la que, en lugar del nivel de vocabulario o la división en filas, realice una división en columnas de palabras.
  • Con este enfoque, todos los servidores tienen todas las palabras en vocabulario, excepto que alojan solo una parte del vector completo.
  • La operación principal en el entrenamiento de word2vec es el producto punto en dos vectores, y la operación del producto punto es susceptible de paralelismo ( ya que no hay dependencia como un bit de acarreo a través de las dimensiones ).
  • Entonces, un producto punto de dos vectores, se realizará en paralelo en todos los servidores de vectores, en porciones distintas de un vector.
  • La figura a continuación captura esta implementación.
  • La implementación descrita en el documento es solo para skipgram (no CBOW) aunque puede extenderse a CBOW.
  • También el pseudocódigo publicado en papel es para muestreo negativo y no para muestreo jerárquico

Figura anterior del documento Sistema de capacitación de Word2vec distribuido eficiente en red para vocabularios grandes

El caso de uso que motivó esta implementación distribuida fue la necesidad no solo de crear un servidor con un gran vocabulario, sino también de mantener el tiempo de capacitación dentro de un límite de una semana, esto fue para una plataforma de publicidad patrocinada de búsqueda que requería identificar palabras relacionadas semánticamente.

Para muchas otras aplicaciones, es posible que uno no alcance este límite de tamaño ( más de 200 millones de vocabulario, aunque la generación de frases de n-gramas (n> = 8) puede llegar rápidamente a uno incluso para un tamaño de cuerpo modesto ). Pero aún se pueden encontrar los pocos días que lleva generar una ejecución completa para todas las incrustaciones cada vez que se requiere una pequeña adición para corpus, incluso si solo en un solo servidor, es demasiado para ciertos casos de uso.

  • En tal escenario, uno podría escapar haciendo una ejecución incremental, simplemente preservando los vectores (vectores de palabras y de contexto ) de una ejecución completa y comenzando una ejecución incremental con el pequeño corpus entrante, aprovechando esos vectores ( nuevas palabras, en el caso de muestreo negativo podría inicializarse aleatoriamente para syn0 tal como lo hacemos con un corpus nuevo y ceros para syn1neg (vector de contexto ).
  • En la práctica, el uso de la distribución unigram del corpus pequeño para la ejecución incremental ( en oposición a la distribución unigram del corpus completo parece funcionar ). Luego, combine estos vectores ( simplemente elija los que están en el nuevo corpus tal como están y los que no están presentes, de la ejecución original ) con la ejecución original y active un servidor incremental.
  • Posteriormente, realice una ejecución completa del corpus con los nuevos datos, pero con submuestreo ajustado para que coincida con las necesidades de tiempo ( por ejemplo, 1e ^ -7 en lugar de 1e ^ -5 ).
  • La realización de esta operación una y otra vez para cada ejecución incremental y posterior ejecución completa submuestreada, en la práctica resulta ser similar a múltiples iteraciones en datos completos.
  • Este enfoque puede funcionar con implementaciones existentes que permiten que se ingresen syn0 (vectores de palabras) y syn1neg (vectores de contexto) para una ejecución (en el peor de los casos, el código original de word2vec C se puede modificar para hacer esto )

La implementación de gensim (una bajo LGPL) no se distribuye. Es paralelo usando el paralelo multiproceso de cython. (Lo del servidor gensim tiene una licencia no permisiva, pero eso puede distribuir cualquier código para gensim)
La implementación de Spark se distribuiría de manera predeterminada.

¿Has considerado deeplearning4j? Word2vec es una de nuestras redes neuronales más populares, lo cual es un poco irónico, ya que no es profundo …

La implementación de Spark afirma estar distribuida, lo cual no es completamente el caso.

Los datos se distribuyen, la capacitación no.
La capacitación aún se realiza en un solo ejecutor (donde desea dividir el cálculo en múltiples ejecutores).

Concluyendo, con grandes datos y solo necesitando almacenar los vectores, Spark es el camino a seguir.

Con datos más pequeños, pero gran memoria, Gensim es mejor.

Cuando utilicé el mismo conjunto de datos (texto8: alrededor de 100 MB), los mismos parámetros para el entrenamiento, Python se ejecuta 10 veces más rápido que la chispa en mi computadora portátil (2015 MacBook Pro 15 “)
Creo que el modelo Word2vec en chispa todavía tiene un largo camino por recorrer …
En cuanto al pequeño conjunto de datos (menos de 1 GB), Gensim es la mejor opción