2017-03-27 2 views
1

J'essaye de créer un algorithme qui est capable d'afficher les n premiers documents similaires à un document spécifique. Pour cela j'ai utilisé le gensim doc2vec. Le code est ci-dessous:Gensim docvecs.most_similar renvoie Id qui n'existent pas

model = gensim.models.doc2vec.Doc2Vec(size=400, window=8, min_count=5, workers = 11, 
dm=0,alpha = 0.025, min_alpha = 0.025, dbow_words = 1) 

model.build_vocab(train_corpus) 

for x in xrange(10): 
    model.train(train_corpus) 
    model.alpha -= 0.002 
    model.min_alpha = model.alpha 
    model.train(train_corpus) 

model.save('model_EN_BigTrain') 

sims = model.docvecs.most_similar([408], topn=10) 

Le sims var devrait me donner 10 tuples, le premier élément l'identifiant du document et le second le score. Le problème est que certains identifiants ne correspondent à aucun document dans mes données d'entraînement.

J'ai essayé depuis un certain temps maintenant de donner un sens aux identifiants qui ne sont pas dans mes données d'entraînement mais je ne vois aucune logique.

Ps: Voici le code que je l'ai utilisé pour créer mon train_corpus

def readData(train_corpus, jData): 

print("The response contains {0} properties".format(len(jData))) 
print("\n") 
for i in xrange(len(jData)): 
    print "> Reading offers from Aux array" 
    if i % 10 == 0: 
     print ">>", i, "offers processed..." 

     train_corpus.append(gensim.models.doc2vec.TaggedDocument(gensim.utils.simple_preprocess(jData[i][1]), tags=[jData[i][0]])) 
print "> Finished processing offers" 

Être chaque position du tableau aux un tableau dans witch la position 0 est un entier (que je veux être l'id) et la position 1 une description

Merci d'avance.

Répondre

1

Utilisez-vous des ID entiers unis comme tags, mais n'utilisez pas exactement tous les entiers de 0 à ce que votre MAX_DOC_ID est?

Si tel est le cas, cela pourrait expliquer l'apparition d'étiquettes dans cette plage. Quand vous utilisez des entiers simples, le DocsV2 de Docs évite de créer un mappage de dictée fourni aux positions d'index dans son vecteur-array interne - et utilise simplement les ints eux-mêmes.

Ainsi, cette matrice de vecteurs interne doit être allouée pour inclure MAX_DOC_ID + 1 lignes. Toutes les lignes correspondant à des identifiants inutilisés sont toujours initialisées comme des vecteurs aléatoires, comme toutes les positions, mais ne recevront aucune formation à partir d'exemples de texte réels pour les pousser dans des positions relatives significatives. Il est donc possible que ces vecteurs aléatoires-mais-non-formés puissent apparaître plus tard most_similar() résultats.

Pour éviter cela, utilisez uniquement des nombres contigus compris entre 0 et le dernier ID dont vous avez besoin. Ou, si vous pouvez vous permettre le coût de la mémoire du mappage chaîne-index, utilisez des balises de chaîne au lieu des entrées simples. Vous pouvez également conserver un enregistrement supplémentaire des ID valides et filtrer manuellement les ID indésirables des résultats.

séparément: en ne spécifiant pas iter=1 dans votre initialisation du modèle Doc2Vec, la valeur par défaut de iter=5 sera en vigueur, ce qui signifie chaque appel à train() fait 5 itérations sur vos données. Étrangement, aussi, votre xrange(10) for-loop inclut deux appels distincts à train() chaque itération (et le 1er utilise juste ce que alpha/min_alpha était déjà en place). Donc, vous êtes en train de faire 10 * 2 * 5 = 100 passes sur les données, avec un calendrier d'apprentissage impair.

Je suggère plutôt que si vous voulez 10 passe à qui se trouve juste iter=10, laissez défaut alpha/min_alpha intacte, puis appeler train() une seule fois. Le modèle effectuera 10 passages, en gérant de manière fluide l'alpha de ses valeurs de début à la fin.

+0

Salut gojomo, D'abord merci pour la réponse rapide. J'ai remarqué ce que vous expliquiez ici et oui, si le premier id que j'avais était 408, le vecteur avait 409 positions. Pour résoudre ce que j'ai utilisé l'id j'ai obtenu de la base de données en tant que chaînes et mon problème a été résolu. En ce qui concerne le modèle de doc2vec, j'avais spécifié l'iter à 1 mais j'ai oublié de changer cela sur ce code. J'ai vu ce cycle dans un didacticiel doc2vec et là, il a été dit qu'ils avaient de meilleurs résultats avec. Avez-vous une opinion à ce sujet? Est-il avantageux de faire le cycle ou de s'entraîner avec le modèle avec 10 ou 0? – JoaoSilva

+1

Il est peu probable que le fait de boucler vous-même, avec une décroissance du taux d'apprentissage moins régulière, donne de meilleurs résultats. Faire à tort 100 itérations quand vous pensez que vous ne faites que 10 peut créer une amélioration perçue - si vous comparez par erreur avec 'iter = 10' (et sans tenir compte du temps supplémentaire utilisé). Appeler 'train()' plusieurs fois avec un bricolage explicite alpha/min_alpha est généralement une complication sujette aux erreurs, et dans tous les cas, les deux 'train()' par itération semblent être un mauvais égarement. Donc, j'éviterais ce modèle. – gojomo

+0

Notez la clarification d'édition ci-dessus, qu'avec explicitement 'iter = 10', le' alpha'/'min_alpha' par défaut peut également être laissé en place. – gojomo

0

J'avais ce problème aussi bien, je me doc2vec Initialisation ce qui suit:

for idx,doc in data.iterrows(): 
    alldocs.append(TruthDocument(doc['clean_text'], [idx], doc['label'])) 

je passais une trame de données qui avait quelques indices wonk. Tout ce que j'avais à faire était.

df.reset_index(inplace=True)