Word2Vec导学 — Skip-Gram模型
这个导学覆盖了基于词转向量(Word2Vec)的skip-gram神经网络结构。我的这篇导学文章的目的是为了能够跳过一些通常的介绍和抽象内容,而能够洞察词转向量(Word2Vec)的本质,并且能够获得更多相关的细节。特别的,这里我将深入skip-gram神经网络模型。
模型
实际上,skip-gram神经网络模型在他最基本的形式下简单得让人吃惊;我认为基于最基础形式的模型下所有的小改进和增强都让解释开始变得混乱不清。
下面我们开始来对我们将要做的事情进行一个高级的深入探索。词转向量(word2vec)使用到一个小技巧,这个小技巧你可能在其他的机器学习相关资料中看到过。我们训练一种仅仅具有一层隐藏层的简单神经网络来完成一个特定的任务,但是事实上我们并不使用训练好的神经网络模型!反而,我们的目标实际上仅仅是为了训练得到隐藏层的权重——我们将看到这些权重实际上就是我们试图去学习得到的“词向量”。
另外一个你可能看到过这个技巧的地方是无监督特征学习。也就是当你需要训练一个自动编码器来在隐藏层压缩一个输入向量,并且在输出层解压它回到原本的状态的时候会用到它。训练结束之后,你将输出层剔除(解压步骤)并且仅仅使用隐藏层——这种方式可以从那些没有标签并且具有好的特征的图像中进行学习的方式。
假任务
现在我们需要讨论一下我们需要创建神经网络来处理的“假”任务,然后我们将要回过头来讨论如何间接地得到我们需要的词向量。
我们将要训练神经网络来做如下事情。选择一个在句子中间的一个特定的单词(输入单词),观察它周围的单词,并且随机选择一个。网络就会告诉我们在词汇表中的每个单词成为我们选中的那个“相邻词”的概率是多少。
当我提到“相邻”这个词的时候,实际上是算法中一个“窗尺寸”的参数。一个特定的窗尺寸可能是5,以为着在输入单词的后面5个单词和前面5个单词(一共10个)
输出的概率与在输入单词附近找到每个单词的概率相关。例如,如果你训练网络的输入单词为“苏维埃”(“Soviet”),那么输出的在比如“联盟”(“Union”)和“俄罗斯”(”Russia“)这些单词的概率要比那些不相关的词高出很多,比如“西瓜”(“watermelon”)和“袋鼠”(“kangaroo”)这样不相关的词。
我们将通过喂给神经网络那些我们在训练文件中找到的单词对来达到这个目的。下面这个例子将展示一些训练样本(单词对),这些样本是我们从这句话中找出来的——“The quick brown fox jumps over the lazy dog.” 我在这个例子上面使用了尺寸为2的小窗口。单词被高亮成蓝色的是输入单词。
网络将对每个单词对出现的次数进行统计。所以,比如说网络很大程度上获得(”Soviet”, “Union”)的样本数目,会比(”Soviet”, “Sasquatch”)单词对的样本数目高得多。当训练结束之后,如果你将单词”Soviet”来作为输入,那么将输出对于”Union”,”Russia”这些单词的概率会远大于”Sasquatch”单词的概率。
模型细节
所以上面这些是怎么样来进行表示的呢?
首先,你知道你无法将一个文本字符形式的单词直接投给一个神经网络,所以我们需要一种能够将单词喂给网络的形式。为了达到这个目的,我们首先需要从我们的训练文档中建立一个单词表——假设我们拥有了一个10000个不同单词的词汇表。
我们将要一个输入的单词转化成一个one-hot形式的向量,比如说“ants”这个单词。转换成的向量有10000个组成元素(每一个元素代表了单词表中的一个单词),并且我们在对应“ants”的位置上面放置一个1,在其他位置上面都放置0。
网络的输出也是一个单一向量(也有10000个组成元素),对应了单词表中的每一个单词。我们随机选择的相邻单词的出现概率也是单词表里面的单词。
下面是我们神经网络的模型。
隐藏层的神经元没有激活函数,但是我们在输出神经元上面使用softmax函数。我们后面再回过头来谈论这个。
当我们使用成对的词来对这个网络进行训练的时候,输出向量是one-hot向量,它代表输入的单词;而输出向量也是one-hot向量,它代表着输出的单词。但是当你使用输入的单词来对训练好的网络进行评估的时候,输出的向量实际上将是概率分布。(换句话说,是一些浮点数值。而不是一个one-hot向量)。
隐藏层
对于我们的例子,我们将要通过一些300个特征的词向量来进行学习。所以,隐藏层是通过一个具有10000行(每一行对应着我妈单词表的每一个单词)和300列(一列对应着一个隐藏神经元)。
300个特征是谷歌之前发布的基于谷歌新闻数据集中进行训练的模型(你可以点击这里进行下载)。特征的数目称为“超参数”,你可以为你的应用来对其进行调整(也就是说,可以尝试不同的数值来看看哪个可以得到最好的结果)。
如果你从行的角度来看这个权重矩阵,那么它实际上就是我们的词向量。
所以我们最终的目的就是训练得到隐藏层的权重矩阵——并且我们将在我们完成之后抛弃输出层。
让我们回过头来看一下,完成我们需要进行训练模型的定义。
现在,你可能会问你自己—— “one-hot向量几乎都是0,这些0有什么用?” 如果你使用一个1 x 10000
维度的one-hot向量来乘以一个10000 x 300
维度的矩阵,那么将会输出向量中的对应“1”位置的矩阵的行。下面这个例子将给你一个直观的看法。
这意味着这个模型的隐藏层只是来作为一个查找表。隐藏层的输出也仅仅是输出的”词向量“
输出层
对应于”ant“这个单词的1 x 300
的词向量被反馈到输出层。输出层是一个softmax回归分类器。这里有一个关于Softmax回归的深入导学,它的主旨就是要将每一个输出神经元(每一个对应着我们单词表中的一个单词!)生成一个输出在0到1之间,并且输出数值总和为1的数。
特别地,每一个输出神经元都有一个权重向量,这个权重向量乘以来自隐藏层的词向量,然后再应用指数函数exp()来获得结果。最后为了得到综合为1的数,我们将结果除以所有10000个输出节点结果的总和。
下面这个是”car”这个单词在计算输出层的输出时的结果的示范。
注意到,神经网络并不知道输出字相对于输入字的偏移量。也就是说对于输入前的单词和输入后的单词来说,他学习的并不是一组不同的概率。为了理解这个含义,我们说在我们的训练语料库中,每个‘York’单词出现的总是与‘New’一起出现。也就是说,至少通过训练数据来看,有百分之一百的概率使得‘New’和‘York’单词相邻。然而,如果我们取‘York’周边的10个单词,并且随机从他们中间选择一个,那么这个单词是‘New’的概率并不是100%;你也许会选择到他周边的其他单词。
直觉
好了,你准备好对这个网络的一点儿深入洞察而兴奋了吗。
如果两个单词有非常相似的“上下文”(也就是出现在他们周边的单词),那么我们的模型会对这两个单词输出非常相似的结果。并且让网络输出非常相似的上下文预测的一种方式就是这两个词向量相似。所以,如果两个单词有非常相似的上下文,那么我们的网络将趋向于为这两个单词学习到相似的词向量!
那么,两个单词有相似的上下文又以为着什么呢?我认为你可以期待这两个词为同义词比如“intelligent”和“smart”,这两个词将有非常相似的上下文。或者是单词直接有相互联系的,比如“engine”和“transmission”,这也许也将会有相似的上下文。
这也或许能够让你抓住词干 —— 网络也将为如“ant”和“ants”单词学到相似词向量,因为他们应该会有一个相似的上下文。
下一步
你也许意识到了skip-gram神经网络包括了一个巨大的权重数目……比如说一个包括300个特征和10000个单词的词表,这在隐藏层和输出层中分别包含了3M的权重数!训练这么大的训练集是非常消耗资源的,所以词转向量的作者提供了一个思路来让训练变得更为可能。这些内容在这个导学的第二部分中被包括了
其他资源
我做了一个网站来连接到word2vec的其他相关学习资源、论文和工具。
网站
McCormick, C. (2016, April 19). Word2Vec Tutorial - The Skip-Gram Model. Retrieved from http://www.mccormickml.com·