python tensorflow nlp gensim doc2vec

python - gensim Doc2Vec vs tensorflow Doc2Vec



nlp (1)

Estoy tratando de comparar mi implementación de Doc2Vec (via tf) y la implementación gensims. Parece al menos visualmente que los gensim están funcionando mejor.

Ejecuté el siguiente código para entrenar el modelo gensim y el siguiente para el modelo tensorflow. Mis preguntas son las siguientes:

  1. Es mi implementación tf de Doc2Vec correcta. Básicamente se supone que concatena los vectores de palabras y el vector de documentos para predecir la palabra del medio en un contexto determinado.
  2. ¿El parámetro window=5 en gensim significa que estoy usando dos palabras en cada lado para predecir el medio? O es 5 en cualquier lado. La cosa es que hay bastantes documentos que son más pequeños que la longitud 10.
  3. ¿Alguna idea de por qué Gensim tiene un mejor rendimiento? ¿Mi modelo es diferente de cómo lo implementan?
  4. Teniendo en cuenta que esto es efectivamente un problema de factorización de la matriz, ¿por qué el modelo TF incluso está obteniendo una respuesta? Hay infinitas soluciones para esto, ya que es un problema de rango deficiente. <- Esta última pregunta es simplemente una bonificación.

Gensim

model = Doc2Vec(dm=1, dm_concat=1, size=100, window=5, negative=10, hs=0, min_count=2, workers=cores) model.build_vocab(corpus) epochs = 100 for i in range(epochs): model.train(corpus)

TF

batch_size = 512 embedding_size = 100 # Dimension of the embedding vector. num_sampled = 10 # Number of negative examples to sample. graph = tf.Graph() with graph.as_default(), tf.device(''/cpu:0''): # Input data. train_word_dataset = tf.placeholder(tf.int32, shape=[batch_size]) train_doc_dataset = tf.placeholder(tf.int32, shape=[batch_size/context_window]) train_labels = tf.placeholder(tf.int32, shape=[batch_size/context_window, 1]) # The variables word_embeddings = tf.Variable(tf.random_uniform([vocabulary_size,embedding_size],-1.0,1.0)) doc_embeddings = tf.Variable(tf.random_uniform([len_docs,embedding_size],-1.0,1.0)) softmax_weights = tf.Variable(tf.truncated_normal([vocabulary_size, (context_window+1)*embedding_size], stddev=1.0 / np.sqrt(embedding_size))) softmax_biases = tf.Variable(tf.zeros([vocabulary_size])) ########################### # Model. ########################### # Look up embeddings for inputs and stack words side by side embed_words = tf.reshape(tf.nn.embedding_lookup(word_embeddings, train_word_dataset), shape=[int(batch_size/context_window),-1]) embed_docs = tf.nn.embedding_lookup(doc_embeddings, train_doc_dataset) embed = tf.concat(1,[embed_words, embed_docs]) # Compute the softmax loss, using a sample of the negative labels each time. loss = tf.reduce_mean(tf.nn.sampled_softmax_loss(softmax_weights, softmax_biases, embed, train_labels, num_sampled, vocabulary_size)) # Optimizer. optimizer = tf.train.AdagradOptimizer(1.0).minimize(loss)

Actualizar:

Mira el cuaderno jupyter here ( here tengo ambos modelos trabajando y probados). Todavía se siente como que el modelo gensim está funcionando mejor en este análisis inicial.


Una vieja pregunta, pero una respuesta sería útil para futuros visitantes. Así que aquí están algunos de mis pensamientos.

Hay algunos problemas en la implementación de tensorflow :

  • window tiene un tamaño de 1 lado, por lo que la window=5 sería 5*2+1 = 11 palabras.
  • Tenga en cuenta que con la versión PV-DM de doc2vec, el batch_size del batch_size sería el número de documentos. Así, la forma de train_word_dataset sería batch_size * context_window , mientras que train_doc_dataset y train_labels shapes sería batch_size .
  • Más importante aún, sampled_softmax_loss no es negative_sampling_loss . Son dos aproximaciones diferentes de softmax_loss .

Entonces para las preguntas listadas de OP:

  1. Esta implementación de doc2vec en tensorflow está funcionando y es correcta a su manera, pero es diferente tanto de la implementación gensim como del papel.
  2. window tiene un tamaño de 1 lado como se dijo anteriormente. Si el tamaño del documento es menor que el tamaño del contexto, entonces se usaría el más pequeño.
  3. Hay muchas razones por las gensim implementación de gensim es más rápida. En primer lugar, gensim fue optimizado en gran medida, todas las operaciones son más rápidas que las operaciones ingeniosas de python, especialmente la E / S de datos. En segundo lugar, algunos pasos de preprocesamiento como min_count filtra en gensim reducirían el tamaño del conjunto de datos. Más importante aún, gensim usa negative_sampling_loss , que es mucho más rápido que sampled_softmax_loss , supongo que esta es la razón principal.
  4. ¿Es más fácil encontrar algo cuando hay muchos de ellos? Es una broma ;-)
    Es cierto que hay muchas soluciones en este problema de optimización no convexa, por lo que el modelo solo encontraría un óptimo local. Curiosamente, en la red neuronal, la mayoría de los óptimos locales son "lo suficientemente buenos". Se ha observado que el descenso de gradiente estocástico parece encontrar mejores óptimos locales que un descenso de gradiente de lotes mayor, aunque esto sigue siendo un enigma en la investigación actual.