J'ai eu la gensimWord2Vec implémentation de calculer quelques embarquements Word pour moi. Pour autant que je sache, tout s'est passé de façon fantastique. maintenant, je regroupe les vecteurs Word créés, dans l’espoir d’obtenir des regroupements sémantiques.
Dans une prochaine étape, j'aimerais examiner les mots (plutôt que les vecteurs) contenus dans chaque grappe. C'est à dire. si j’ai le vecteur d’embeddings [x, y, z]
, je voudrais savoir quel mot ce vecteur représente. Je peux obtenir les mots/éléments de vocabulaire en appelant model.vocab
et les vecteurs Word via model.syn0
. Mais je ne pouvais pas trouver un endroit où ceux-ci sont explicitement appariés.
C’était plus compliqué que prévu et j’ai le sentiment que je pourrais rater la façon évidente de le faire. Toute aide est appréciée!
Faites correspondre les mots aux vecteurs d'incorporation créés par Word2Vec ()
- comment puis-je le faire?
Après avoir créé le modèle (code ci-dessous *), je voudrais maintenant faire correspondre les index attribués à chaque mot (au cours de la phase build_vocab()
) avec la matrice de vecteurs sortie sous le nom model.syn0
.
for i in range (0, newmod.syn0.shape[0]): #iterate over all words in model
print i
Word= [k for k in newmod.vocab if newmod.vocab[k].__dict__['index']==i] #get the Word out of the internal dicationary by its index
wordvector= newmod.syn0[i] #get the vector with the corresponding index
print wordvector == newmod[Word] #testing: compare result of looking up the Word in the model -- this prints True
Existe-t-il un meilleur moyen de le faire, par exemple en introduisant le vecteur dans le modèle pour correspondre au mot?
Est-ce que cela me donne même des résultats corrects?
* Mon code pour créer les vecteurs Word:
model = Word2Vec(size=1000, min_count=5, workers=4, sg=1)
model.build_vocab(sentencefeeder(folderlist)) #sentencefeeder puts out sentences as lists of strings
model.save("newmodel")
J'ai trouvé cette question qui est similaire mais qui n'a pas vraiment reçu de réponse.
J'ai donc trouvé un moyen simple de procéder, où nmodel
est le nom de votre modèle.
#Zip the two lists containing vectors and words
zipped = Zip(nmodel.wv.index2Word, nmodel.wv.syn0)
#the resulting list contains `(Word, wordvector)` tuples. We can extract the entry for any `Word` or `vector` (replace with the Word/vector you're looking for) using a list comprehension:
wordresult = [i for i in zipped if i[0] == Word]
vecresult = [i for i in zipped if i[1] == vector]
Ceci est basé sur le code gensim . Pour les anciennes versions de gensim, vous devrez peut-être supprimer la variable wv
après le modèle.
Je cherchais depuis longtemps le mappage entre la matrice syn0 et le vocabulaire ... voici la réponse: utilisez model.index2Word
qui est simplement la liste des mots dans le bon ordre!
Ce n'est pas dans la documentation officielle (pourquoi?) Mais on peut le trouver directement dans le code source: https://github.com/RaRe-Technologies/gensim/blob/3b9bb59dac0d55a1cd6ca8f984cead38b9cb0860/gensim/models/Word2vec.p L441
Si vous souhaitez uniquement mapper un Word sur un vector, vous pouvez simplement utiliser l'opérateur []
, par exemple. model["hello"]
vous donnera le vecteur correspondant à bonjour.
Si vous avez besoin de récupérer un mot à partir d'un vecteur, vous pouvez parcourir votre liste de vecteurs et rechercher une correspondance, comme vous le proposez. Cependant, c'est inefficace et non pas Pythonic. Une solution pratique consiste à utiliser la méthode similar_by_vector
du modèle Word2vec, comme suit:
import gensim
documents = [['human', 'interface', 'computer'],
['survey', 'user', 'computer', 'system', 'response', 'time'],
['eps', 'user', 'interface', 'system'],
['system', 'human', 'system', 'eps'],
['user', 'response', 'time'],
['trees'],
['graph', 'trees'],
['graph', 'minors', 'trees'],
['graph', 'minors', 'survey']]
model = gensim.models.Word2Vec(documents, min_count=1)
print model.similar_by_vector(model["survey"], topn=1)
qui produit:
[('survey', 1.0000001192092896)]
où le nombre représente la similitude.
Cependant, cette méthode est toujours inefficace, car il lui reste à analyser tous les vecteurs Word pour rechercher le plus similaire. La meilleure solution à votre problème consiste à trouver un moyen de garder une trace de vos vecteurs pendant le processus de mise en cluster afin que vous n'ayez pas à compter sur des mappages inverses coûteux.
Comme @bpachev l'a mentionné, gensim dispose d'une option de recherche par vecteur, à savoir similar_by_vector
.
Cependant, il met en œuvre une recherche linéaire par force brute, c’est-à-dire calcule la similarité en cosinus entre un vecteur donné et les vecteurs de tous les mots du vocabulaire, et dégage les premiers voisins. Une autre option, comme mentionné dans l'autre answer consiste à utiliser un algorithme approximatif de recherche du plus proche voisin tel que FLANN.
Partage d'un résumé démontrant la même chose: https://Gist.github.com/kampta/139f710ca91ed5fabaf9e6616d2c762b