La explicación clásica de word2vec como una arquitectura Skip-gram de muestra negativa en el artículo científico original y en innumerables publicaciones de blog se ve así:
while(1) { 1. vf = vector of focus word 2. vc = vector of focus word 3. train such that (vc . vf = 1) 4. for(0 <= i <= negative samples): vneg = vector of word *not* in context train such that (vf . vneg = 0) }
De hecho, si buscas en Google [word2vec skipgram], lo que vemos:
Pero todas estas implementaciones están mal .
La implementación original de word2vec en C funciona de manera diferente y es
fundamentalmente diferente de esto. Aquellos que implementan profesionalmente sistemas con incrustaciones de palabras de word2vec hacen uno de los siguientes:
- Llame directamente a la implementación original de C.
- Use la implementación
gensim
, que se transcribe desde la fuente C en la medida en que coincidan los nombres de las variables.
De hecho,
gensim
es la
única implementación verdadera de C que conozco .
Implementación C
La implementación de C en realidad admite
dos vectores para cada palabra . Un vector para la palabra está en foco, y el segundo para la palabra en contexto. (¿Parece familiar? Correcto, ¡los desarrolladores de GloVe tomaron una idea de word2vec sin mencionar este hecho!)
La implementación en el código C es excepcionalmente competente:
¿Por qué inicialización aleatoria y cero?
Una vez más, dado que esto no se explica en absoluto en los artículos originales
y en cualquier lugar de Internet , solo puedo especular.
La hipótesis es que cuando las muestras negativas provienen de todo el texto y no se ponderan por frecuencia, puede elegir
cualquier palabra , y con mayor frecuencia una palabra cuyo
vector no esté entrenado en absoluto . Si este vector tiene un significado, cambiará aleatoriamente la palabra realmente importante en foco.
La conclusión es establecer todos los ejemplos negativos en cero, de modo que
solo los vectores que ocurran con mayor o menor frecuencia afecten la presentación de otro vector.
Esto es realmente bastante complicado, y nunca había pensado en lo importantes que son las estrategias de inicialización.
¿Por qué estoy escribiendo esto?
Pasé dos meses de mi vida tratando de reproducir word2vec como se describe en la publicación científica original e innumerables artículos en Internet, pero fallé. No pude lograr los mismos resultados que word2vec, aunque hice mi mejor esfuerzo.
No podía imaginar que los autores de la publicación literalmente fabricaran un algoritmo que no funciona, mientras que la implementación hace algo completamente diferente.
Al final, decidí estudiar la fuente. Durante tres días estuve seguro de que entendí mal el código, ya que literalmente todos en Internet hablaron de una implementación diferente.
No tengo idea de por qué la publicación original y los artículos en Internet no dicen nada sobre el mecanismo
real de word2vec, así que decidí publicar esta información yo mismo.
Esto también explica la elección radical de GloVe de establecer vectores separados para el contexto negativo: simplemente hicieron lo que hace word2vec, pero le dijeron a la gente al respecto :).
¿Es este un truco científico? No sé, una pregunta difícil. Pero para ser honesto, estoy increíblemente enojado. Probablemente, nunca más podré volver a tomarme en serio la explicación de los algoritmos en el aprendizaje automático: la próxima vez iré
inmediatamente a ver las fuentes.