55 votes

gensim Doc2Vec vs tensorflow Doc2Vec

J'essaie de comparer mon implémentation de Doc2Vec (via tf) et celle de gensims. Il semble, du moins visuellement, que celles de gensim soient plus performantes.

J'ai exécuté le code suivant pour entraîner le modèle gensim et celui qui suit pour le modèle tensorflow. Mes questions sont les suivantes :

  1. Mon implémentation tf de Doc2Vec est-elle correcte ? En fait, elle est censée concaténer les vecteurs de mots et le vecteur de document pour prédire le mot central dans un certain contexte ?
  2. Est-ce que le window=5 dans gensim signifie que j'utilise deux mots de chaque côté pour prédire celui du milieu ? Ou est-ce que c'est 5 de chaque côté. Le fait est qu'il y a pas mal de documents qui sont plus petits que la longueur 10.
  3. Avez-vous une idée de la raison pour laquelle Gensim est plus performant ? Mon modèle est-il différent de la façon dont ils le mettent en œuvre ?
  4. Étant donné qu'il s'agit effectivement d'un problème de factorisation matricielle, pourquoi le modèle TF obtient-il une réponse ? Il y a une infinité de solutions à ce problème puisqu'il s'agit d'un problème de déficience de rang. <- Cette dernière question est simplement un bonus.

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)

Mise à jour :

Consultez le carnet de notes jupyter ici (J'ai les deux modèles en fonctionnement et testés ici). Il semble toujours que le modèle gensim soit plus performant dans cette première analyse.

3 votes

Une discussion approfondie à ce sujet se trouve ici : groups.google.com/forum/#!topic/gensim/0GVxA055yOU

1 votes

Selon la documentation - "la fenêtre est la distance maximale entre le mot prédit et les mots du contexte utilisés pour la prédiction dans un document". Donc, c'est 5 mots de chaque côté. Par ailleurs, pouvez-vous me dire ce que signifie l'expression negative ou num_sampled ? Je n'ai pas bien compris.

1 votes

L'approche de l'échantillonnage négatif est décrite dans l'un des ouvrages de Mikolov. documents . En outre, il réduit le nombre de paramètres qui sont mis à jour à chaque étape d'apprentissage.

21voto

THN Points 1057

Vieille question, mais une réponse serait utile pour les futurs visiteurs. Voici donc quelques-unes de mes réflexions.

Il y a quelques problèmes dans le tensorflow mise en œuvre :

  • window est la taille d'un côté, donc window=5 serait 5*2+1 = 11 mots.
  • Notez qu'avec la version PV-DM de doc2vec, l'option batch_size serait le nombre de documents. Ainsi, train_word_dataset La forme serait batch_size * context_window alors que train_doc_dataset et train_labels Les formes seraient batch_size .
  • Plus important encore, sampled_softmax_loss n'est pas negative_sampling_loss . Ce sont deux approximations différentes de softmax_loss .

Donc, pour les questions de l'OP :

  1. Cette mise en œuvre de doc2vec sur tensorflow fonctionne et est correcte à sa manière, mais elle est différente de l'approche de la gensim la mise en œuvre et le document.
  2. window est la taille d'un côté comme indiqué ci-dessus. Si la taille du document est inférieure à celle du contexte, c'est la plus petite qui sera utilisée.
  3. Il y a de nombreuses raisons pour lesquelles gensim est plus rapide. Premièrement, gensim a été fortement optimisé, toutes les opérations sont plus rapides que les opérations naïves de Python, en particulier les entrées/sorties de données. Deuxièmement, certaines étapes de prétraitement telles que min_count filtrage dans gensim réduirait la taille de l'ensemble de données. Plus important encore, gensim utilise negative_sampling_loss ce qui est beaucoup plus rapide que sampled_softmax_loss Je pense que c'est la raison principale.
  4. Est-il plus facile de trouver quelque chose quand il y en a beaucoup ? Je plaisante ;-)
    Il est vrai qu'il existe de nombreuses solutions dans ce problème d'optimisation non convexe, de sorte que le modèle ne trouverait qu'un optimum local. Il est intéressant de noter que dans un réseau neuronal, la plupart des optima locaux sont "suffisamment bons". Il a été observé que la descente de gradient stochastique semble trouver de meilleurs optima locaux que la descente de gradient par lots plus importants, bien que cela reste une énigme dans la recherche actuelle.

1 votes

"dans un réseau neuronal, la plupart des optima locaux sont "assez bons"". Je pense qu'il est plus correct de dire que dans les problèmes à haute dimension, comme dans les réseaux neuronaux, la plupart des minima locaux sont en fait des points de selle, donc ils sont faciles à franchir, surtout lorsqu'on utilise des étapes plus stochastiques.

0 votes

En effet, dans les problèmes de haute dimension, la plupart des points critiques sont des points de selle, mais la dynamique stochastique conduit les solutions à des optima locaux plutôt qu'à des points de selle, sauf peut-être des points de selle très plats et larges. Le fait est que la plupart des optima locaux trouvés sont suffisamment bons, car il a été démontré empiriquement que différents optima locaux trouvés ont généralement presque la même performance de généralisation, ce qui est très intéressant. La réponse à cette question réside peut-être dans la dynamique stochastique qui conduit également les solutions vers des optima locaux plats et larges au lieu d'optima locaux pointus et étroits.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X