web-dev-qa-db-de.com

Passende Wörter und Vektoren im gensim Word2Vec-Modell

Ich habe die gensimWord2Vec Implementierung einige Word - Einbettungen für mich berechnen lassen. Soweit ich das beurteilen kann, lief alles fantastisch. Jetzt sammle ich die erstellten Word-Vektoren in der Hoffnung, einige semantische Gruppierungen zu erhalten. 

Als nächsten Schritt möchte ich die Wörter (und nicht die Vektoren) in jedem Cluster betrachten. D.h. Wenn ich den Vektor der Einbettungen [x, y, z] habe, würde ich gerne herausfinden, welches tatsächliche Wort dieser Vektor darstellt. Ich kann die Wörter/Vocab-Elemente abrufen, indem Sie model.vocab und die Word-Vektoren über model.syn0 aufrufen. Ich konnte aber keinen Ort finden, an dem diese explizit übereinstimmen. 

Das war komplizierter als ich erwartet hatte und ich glaube, dass ich die offensichtliche Art und Weise vermisse. Jede Hilfe wird geschätzt!

Problem:

Verwenden Sie Wörter, um Vektoren einzubetten, die von Word2Vec () erstellt wurden. Wie mache ich das? 

Mein Ansatz:

Nach dem Erstellen des Modells (Code unter *) möchte ich nun die Indizes, die jedem Wort zugewiesen wurden (während der Phase build_vocab()), an die als model.syn0..__ ausgegebene Vektormatrix anpassen

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
  • Gibt es einen besseren Weg, z. indem Sie den Vektor in das Modell eingeben, um das Wort zu finden?

  • Bekommt ich überhaupt korrekte Resultate?

* Mein Code zum Erstellen der Word-Vektoren:

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")

Ich habe diese Frage gefunden, die ähnlich ist, aber nicht wirklich beantwortet wurde. 

17
patrick

So fand ich einen einfachen Weg, dies zu tun, wobei nmodel der Name Ihres Modells ist. 

#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]

Dies basiert auf dem gensim-Code . Bei älteren Versionen von gensim müssen Sie möglicherweise die wv nach dem Modell löschen. 

5
patrick

Ich habe lange gesucht, um die Zuordnung zwischen der syn0-Matrix und dem Vokabular zu finden ... hier ist die Antwort: use model.index2Word ist einfach die Liste der Wörter in der richtigen Reihenfolge!

Dies ist nicht in der offiziellen Dokumentation (warum?), Aber es ist direkt im Quellcode zu finden: https://github.com/RaRe-Technologies/gensim/blob/3b9bb59dac0d55a1cd6ca8f984cead38b9cb0860/gensim/models/Word2vec.py# L441

9
Arcyno

Wenn Sie nur ein Word einem vector zuordnen möchten, können Sie einfach den []-Operator verwenden, z. model["hello"] gibt Ihnen den Vektor, der hallo entspricht.

Wenn Sie ein Wort aus einem Vektor wiederherstellen müssen, können Sie die Liste der Vektoren durchlaufen und nach einer Übereinstimmung suchen, wie Sie es vorschlagen. Dies ist jedoch ineffizient und nicht Pythonic. Eine bequeme Lösung ist die Verwendung der similar_by_vector-Methode des Word2vec-Modells wie folgt:

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)

welche Ausgänge:

[('survey', 1.0000001192092896)]

wobei die Zahl die Ähnlichkeit darstellt.

Diese Methode ist jedoch immer noch ineffizient, da immer noch alle Word-Vektoren durchsucht werden müssen, um nach dem ähnlichsten zu suchen. Die beste Lösung für Ihr Problem besteht darin, einen Weg zu finden, um Ihre Vektoren zu verfolgen während des Clustering-Prozesses, damit Sie sich nicht auf teure Reverse-Mappings verlassen müssen.

4
bpachev

Wie @bpachev erwähnt hat, hat gensim die Möglichkeit, nach Vektoren zu suchen, nämlich similar_by_vector.

Es führt jedoch eine lineare Suche nach roher Kraft durch, d. H. Es berechnet eine Cosinusähnlichkeit zwischen einem gegebenen Vektor und Vektoren aller Wörter im Vokabular und gibt die obersten Nachbarn aus. Eine alternative Option, wie im anderen answer erwähnt, besteht darin, einen ungefähren Nachbarsuchalgorithmus wie FLANN zu verwenden.

Eine Gist teilen, die dasselbe demonstriert: https://Gist.github.com/kampta/139f710ca91ed5fabaf9e6616d2c762b

0
kampta