L'explication classique de word2vec en tant qu'architecture Skip-gram à échantillon négatif dans l'article scientifique d'origine et d'innombrables articles de blog ressemble à ceci:
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) }
En effet, si vous google [skipgram word2vec], ce que nous voyons:
Mais toutes ces implémentations sont fausses .
L'implémentation originale de word2vec en C fonctionne différemment et est
fondamentalement différente de cela. Ceux qui implémentent professionnellement des systèmes avec des incorporations de mots à partir de word2vec font l'une des choses suivantes:
- Appelez directement l'implémentation d'origine de C.
- Utilisez l'implémentation
gensim
, qui est translittérée de la source C dans la mesure où les noms de variables correspondent.
En effet,
gensim
est la
seule véritable implémentation C que je connaisse .
Implémentation C
L'implémentation C prend en charge
deux vecteurs pour chaque mot . Un vecteur pour le mot est mis au point et le second pour le mot dans son contexte. (Cela vous semble familier? D'accord, les développeurs de GloVe ont emprunté une idée à word2vec sans mentionner ce fait!)
L'implémentation en code C est exceptionnellement compétente:
Pourquoi une initialisation aléatoire et nulle?
Encore une fois, comme cela n'est pas expliqué du tout dans les articles originaux
et partout sur Internet , je ne peux que spéculer.
L'hypothèse est que lorsque des échantillons négatifs proviennent de l'ensemble du texte et ne sont pas pondérés par la fréquence, vous pouvez choisir
n'importe quel mot , et le plus souvent un mot dont le
vecteur n'est pas du tout formé . Si ce vecteur a une signification, alors il mettra au hasard le mot vraiment important au point.
L'essentiel est de mettre tous les exemples négatifs à zéro, de sorte que
seuls les vecteurs qui se produisent plus ou moins souvent affectent la présentation d'un autre vecteur.
C'est en fait assez délicat, et je n'avais jamais pensé à l'importance des stratégies d'initialisation.
Pourquoi est-ce que j'écris ceci
J'ai passé deux mois de ma vie à essayer de reproduire word2vec comme décrit dans la publication scientifique originale et d'innombrables articles sur Internet, mais j'ai échoué. Je n'ai pas pu obtenir les mêmes résultats que word2vec, même si j'ai fait de mon mieux.
Je ne pouvais pas imaginer que les auteurs de la publication aient littéralement fabriqué un algorithme qui ne fonctionne pas, alors que l'implémentation fait quelque chose de complètement différent.
Finalement, j'ai décidé d'étudier la source. Pendant trois jours, j'étais confiant d'avoir mal compris le code, car littéralement tout le monde sur Internet parlait d'une implémentation différente.
Je ne sais pas pourquoi la publication et les articles originaux sur Internet ne disent rien sur le
véritable mécanisme de word2vec, j'ai donc décidé de publier moi-même ces informations.
Cela explique également le choix radical de GloVe de définir des vecteurs séparés pour le contexte négatif - ils ont juste fait ce que fait word2vec, mais en ont parlé aux gens :).
Est-ce une astuce scientifique? Je ne sais pas, une question difficile. Mais pour être honnête, je suis incroyablement en colère. Probablement, je ne pourrai plus jamais prendre au sérieux l'explication des algorithmes en machine learning: la prochaine fois j'irai
immédiatement regarder les sources.