原始科学文章和无数博客文章中对word2vec作为否定样本Skip-gram体系结构的经典解释如下:
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) }
的确,如果您用谷歌搜索[word2vec skipgram],我们将看到:
但是所有这些实现都是错误的 。
C语言中word2vec的原始实现工作原理不同,并且
根本不同 。 那些专业地使用word2vec中的单词嵌入来实现系统的人员,可以执行以下任一操作:
- 直接调用C的原始实现。
- 使用
gensim
实现,该实现从源C进行音译 ,直到变量名称匹配。
实际上,
gensim
是
我所知道的
唯一真正的C实现 。
C实现
C实现实际上
为每个单词支持
两个向量 。 这个词的一个向量是焦点,第二个向量是上下文。 (似乎很熟悉?对,GloVe开发人员从word2vec借用了一个想法,而没有提到这个事实!)
用C代码实现的能力异常出色:
为什么随机和零初始化?
再一次,由于原始文章
和Internet上的任何地方都没有对此进行解释,所以我只能推测。
假设是,当否定样本来自整个文本并且不按频率加权时,您可以选择
任何单词 ,并且通常选择一个其
向量根本没有经过训练的单词。 如果此向量具有含义,则它将随机移动真正重要的单词。
底线是将所有否定示例设置为零,以便
仅出现或多或少出现的向量会影响另一个向量的表示。
这实际上很棘手,而且我从未想过初始化策略有多重要。
我为什么要写这个
我花了两个月的时间来尝试复制word2vec,如原始的科学出版物和互联网上无数的文章所述,但是失败了。 尽管我已尽力而为,但我无法达到与word2vec相同的结果。
我无法想象该出版物的作者实际上制造了一种行不通的算法,而实现却完全不同。
最后,我决定研究来源。 三天以来,我确信自己误解了代码,因为实际上互联网上的每个人都在谈论另一种实现。
我不知道为什么Internet上的原始出版物和文章没有对word2vec的
真正机制说什么,所以我决定自己发布此信息。
这也解释了GloVe的根本选择,即为否定语境设置单独的向量-他们只是做了word2vec所做的,但是告诉了人们:)。
这是科学诀窍吗? 我不知道,这是一个难题。 但是说实话,我非常生气。 可能,我将永远无法再认真对待机器学习中的算法解释:下次,我将
立即查看源代码。