Die klassische Erklärung von word2vec als Skip-Gramm-Architektur mit negativem Beispiel im ursprünglichen wissenschaftlichen Artikel und in unzähligen Blog-Posts sieht folgendermaßen aus:
while(1) { 1. vf = vector of focus word 2. vc = vector of focus word 3. train such that (vc . vf = 1) 4. for(0 <= i <= negative samples): vneg = vector of word *not* in context train such that (vf . vneg = 0) }
In der Tat, wenn Sie [word2vec skipgram] googeln, was wir sehen:
Aber all diese Implementierungen sind falsch .
Die ursprüngliche Implementierung von word2vec in C funktioniert anders und unterscheidet sich
grundlegend davon. Diejenigen, die Systeme mit Worteinbettungen von word2vec professionell implementieren, führen eine der folgenden Aktionen aus:
- Rufen Sie direkt die ursprüngliche Implementierung von C auf.
- Verwenden Sie die
gensim
Implementierung, die von der Quelle C gensim
, gensim
die Variablennamen übereinstimmen.
In der Tat ist
gensim
die
einzige echte C-Implementierung, die mir bekannt ist .
C Implementierung
Die C-Implementierung unterstützt tatsächlich
zwei Vektoren für jedes Wort . Ein Vektor für das Wort steht im Fokus und der zweite für das Wort im Kontext. (Kommt Ihnen das bekannt vor? Richtig, GloVe-Entwickler haben eine Idee von word2vec ausgeliehen, ohne diese Tatsache zu erwähnen!)
Die Implementierung in C-Code ist außerordentlich kompetent:
Warum zufällige und Null-Initialisierung?
Noch einmal, da dies in den Originalartikeln
und irgendwo im Internet überhaupt nicht erklärt wird, kann ich nur spekulieren.
Die Hypothese ist, dass Sie, wenn negative Stichproben aus dem gesamten Text stammen und nicht nach Häufigkeit gewichtet werden, ein
beliebiges Wort auswählen
können , und meistens ein Wort, dessen
Vektor überhaupt nicht trainiert wird . Wenn dieser Vektor eine Bedeutung hat, verschiebt er das wirklich wichtige Wort zufällig in den Fokus.
Unter dem Strich werden alle negativen Beispiele auf Null gesetzt, sodass
nur Vektoren, die mehr oder weniger häufig auftreten , die Darstellung eines anderen Vektors beeinflussen.
Das ist eigentlich ziemlich knifflig und ich hatte nie darüber nachgedacht, wie wichtig Initialisierungsstrategien sind.
Warum schreibe ich das?
Ich habe zwei Monate meines Lebens damit verbracht, word2vec wie in der wissenschaftlichen Originalveröffentlichung und in unzähligen Artikeln im Internet beschrieben zu reproduzieren, bin aber gescheitert. Ich konnte nicht die gleichen Ergebnisse wie word2vec erzielen, obwohl ich mein Bestes versucht habe.
Ich konnte mir nicht vorstellen, dass die Autoren der Veröffentlichung buchstäblich einen Algorithmus erfunden haben, der nicht funktioniert, während die Implementierung etwas völlig anderes macht.
Am Ende entschied ich mich, die Quelle zu studieren. Drei Tage lang war ich zuversichtlich, den Code falsch verstanden zu haben, da buchstäblich alle im Internet über eine andere Implementierung sprachen.
Ich habe keine Ahnung, warum die Originalveröffentlichung und die Artikel im Internet nichts über den
tatsächlichen Mechanismus von word2vec aussagen. Deshalb habe ich beschlossen, diese Informationen selbst zu veröffentlichen.
Dies erklärt auch die radikale Entscheidung von GloVe, separate Vektoren für den negativen Kontext festzulegen - sie haben einfach das getan, was word2vec tut, aber den Leuten davon erzählt :).
Ist das ein wissenschaftlicher Trick? Ich weiß nicht, eine schwierige Frage. Aber um ehrlich zu sein, bin ich unglaublich wütend. Wahrscheinlich werde ich die Erklärung von Algorithmen beim maschinellen Lernen nie wieder ernst nehmen können: Beim nächsten Mal werde ich mir
sofort die Quellen ansehen.