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:
- 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.
- ¿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. - ¿Alguna idea de por qué Gensim tiene un mejor rendimiento? ¿Mi modelo es diferente de cómo lo implementan?
- 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 lawindow=5
sería5*2+1
=11
palabras. - Tenga en cuenta que con la versión PV-DM de doc2vec, el
batch_size
delbatch_size
sería el número de documentos. Así, la forma detrain_word_dataset
seríabatch_size * context_window
, mientras quetrain_doc_dataset
ytrain_labels
shapes seríabatch_size
. - Más importante aún,
sampled_softmax_loss
no esnegative_sampling_loss
. Son dos aproximaciones diferentes desoftmax_loss
.
Entonces para las preguntas listadas de OP:
- Esta implementación de
doc2vec
entensorflow
está funcionando y es correcta a su manera, pero es diferente tanto de la implementacióngensim
como del papel. -
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. - Hay muchas razones por las
gensim
implementación degensim
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 comomin_count
filtra engensim
reducirían el tamaño del conjunto de datos. Más importante aún,gensim
usanegative_sampling_loss
, que es mucho más rápido quesampled_softmax_loss
, supongo que esta es la razón principal. - ¿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.