¿Es un bug en ReduceVocab() o me estoy perdiendo algo?
Aquí hay un fragmento de código de word2vec
que he descargado de google word2vec.c:
“`c++
// Reduce el vocabulario eliminando tokens infrecuentes
void ReduceVocab() {
int a, b = 0;
unsigned int hash;
for (a = 0; a < vocab_size; a++) if (vocab[a].cn > min_reduce) {
vocab[b].cn = vocab[a].cn;
vocab[b].word = vocab[a].word;
b++;
} else free(vocab[a].word);
vocab_size = b;
}
for (a = 0; a < vocab_hash_size; a++) vocab_hash[a] = -1;
for (a = 0; a < vocab_size; a++) {
// El hash se volverá a calcular, ya que no es actual
hash = GetWordHash(vocab[a].word);
while (vocab_hash[hash] != -1) hash = (hash + 1) % vocab_hash_size;
vocab_hash[hash] = a;
}
fflush(stdout);
min_reduce++;
“`
que se llama en la función LearnVocabFromTrainFile
.
Supongamos que min_reduce=5
.
Entonces, si el archivo de entrada no es tan bueno, me refiero a si una palabra como “hello” aparece 4 veces cuando se llama a ReduceVocab
, y el vocab
eliminará “hello” de sí mismo.
Más tarde, cuando ReduceVocab
se llama nuevamente y por suerte “hello” aparece 5 veces… y parece que ReduceVocab
eliminará “hello” nuevamente.
En realidad, “hello” apareció 9 veces y debería estar en el vocab
, pero el código anterior lo eliminó.
No es un gran problema ya que parece que la situación ocurre raramente. Solo me pregunto si mi análisis es correcto o si me he perdido algo en el código.
Gracias por cualquier consejo.
davy.ai
Explicación del Código
El código dado es parte de la implementación de
word2vec
de Google. Define una función llamadaReduceVocab()
que reduce el vocabulario eliminando tokens infrecuentes. La función itera sobre todo el vocabulario y elimina las palabras cuya cuenta (almacenada envocab[a].cn
) es menor que un umbral predefinidomin_reduce
. Las palabras eliminadas se liberan de la memoria utilizando la funciónfree()
.Después de eliminar las palabras infrecuentes, la función actualiza el tamaño del vocabulario (
vocab_size
) y vuelve a calcular la tabla hash (vocab_hash
) para las palabras restantes. La tabla hash es una estructura de datos que asigna cada palabra a su índice en el array de vocabulario.La función
LearnVocabFromTrainFile
es el punto de entrada para el aprendizaje de vocabulario en el algoritmoword2vec
. Lee un archivo de entrenamiento y registra la cuenta de cada palabra en el vocabulario. Una vez que se construye el vocabulario, se llama a la funciónReduceVocab
para eliminar las palabras infrecuentes. Este proceso se repite varias veces con umbrales crecientes (min_reduce
), hasta que el tamaño del vocabulario alcanza un límite deseado.Análisis del Código
La duda planteada en la pregunta se refiere a la posibilidad de perder algunas palabras del vocabulario debido a las llamadas repetidas a
ReduceVocab
. Específicamente, si una palabra aparece menos demin_reduce
veces en el archivo de entrenamiento en el primer paso, será eliminada. Si aparece exactamentemin_reduce
veces en un paso posterior, será eliminada nuevamente.Este comportamiento es una consecuencia de cómo se define la función
ReduceVocab
. Elimina las palabras cuya cuenta es menor o igual a un umbral, sin tener en cuenta su historial pasado. Por lo tanto, una palabra puede ser eliminada incluso si era frecuente en el pasado o es probable que sea frecuente en el futuro.Para solucionar este problema, se puede modificar la función
ReduceVocab
para tener en cuenta todo el historial de cuentas de cada palabra, en lugar de solo la cuenta actual. Esto se puede lograr almacenando las cuentas pasadas de cada palabra en una estructura de datos separada y actualizándola cada vez que se elimina una palabra. Las cuentas actualizadas luego se pueden utilizar para decidir si mantener o eliminar una palabra en pasos posteriores.Otra opción es utilizar una tabla hash dinámica que pueda crecer o reducirse a medida que cambia el vocabulario. Esto evitaría la necesidad de recalcular la tabla hash después de cada paso y permitiría que las palabras infrecuentes se mantengan en memoria hasta que su cuenta alcance un umbral determinado.
En conclusión, el código dado es una implementación básica de reducción de vocabulario en
word2vec
que puede llevar a perder algunas palabras debido a las llamadas repetidas aReduceVocab
. Sin embargo, este problema se puede solucionar mediante el uso de técnicas más avanzadas que tengan en cuenta el historial de cuentas de las palabras o que utilicen una tabla hash dinámica.