Word2Vec
- 1. 背景知识
- 2. CBOW, Skip-Gram介绍
- 2.1 以单个词语为输入的情况
- 2.2 CBOW
- 2.3 Skip-Gram
- 3. 优化计算效率的两种方法
- 3.1 Hierarchical Softmax
- 3.2 Negative Sampling
1. 背景知识
在NLP任务中,很多时候我们处理文本的细粒度的是词语,所以我们需要将词语转换成向量的形式以进行各式各样的计算。
最初也是最简单的一种词向量表达方式是 One-hot 编码词语,例如:
text: I love you
Vocab: { I: 0, love: 1, you: 2}Wordvector: {I:[1,0,0], love: [0,1,0], you: [0,0,1]}
可以看到这种表达方式很直观,但是有缺陷:
- 词向量的维度 = vocab中词语数量。后者在实际中往往是几万甚至几十几百万,因此会有维度爆炸
- 只能单纯的表示词语在vocab的索引,无法表示词语之间的内在联系
有许多研究者就词向量的获取方式作了改进,我们今天讲的word2vec便是其中一种。wordvec是google团队在2013年发布的一个训练获取词向量的工具包,包含了两种训练训练词向量的模型(skip-gram, COBW)和训练优化工具(negative samping, hierarchy softmax)
2. CBOW, Skip-Gram介绍
2.1 以单个词语为输入的情况
从最简单的情况开始讲起,假设输入的文本只有一个单词。我们设 V = vocab size,N = hidden size。Input layer是一个 (V*1) 大小的embedding layer : {}。为1代表该词语在输入文本中出现。以单个词语为输入时,意味着{}只有一个1值。
是input 和 hidden之间的权重矩阵,每一行代表一个与input word相关的N维向量,我们用表示。对于单个词语的输入,假设,我们有:
注意到,所以h其实就是W的第k行,便是输入词的向量表示。
通过hidden layer到output layer中的权重矩阵,我们可以计算出词汇表中每个词语的得分:
是的第j列,然后我们用softmax得到所有词语的后验概率:
便是对应output layer的第j个词。
我们注意到,对于输入词,他在W和W’中有两种向量形式:,接下来我们把分别称为词语输入向量(input vector)和输出向量(output vector)。
更新输出向量:
我们要最大化:
便是我们的损失函数, 是实际输出词语的index。然后反向传播更新输出向量:
从式子中可以看出,更新一次,我们要检查vocab中所有词的概率。
更新输入向量:
E对输入向量W求导,得到一个V*N的矩阵,因为只有一个输入词,所以该矩阵只有一行是非0的,值为,然后便可以对W进行更新:
注意,只有那一行得到了更新。
讲过多次训练,最终,输入词的词向量维
2.2 CBOW
直观来看,CBOW实际上是以上下文的方式来预测输出的词,我们需要设置一个上下文词语数量skip_window来决定窗口值C, 比如
Text: I love you three thousands.
Window size: skip_window = 2,C=2*skip_window+1=5
假设我们的输入词是 {I, love, three, thousands}, 我们的预测就应该是{you}。参数与2.1中的参数设置基本相同,hidden layer的值为:
C为窗口值5,损失函数也随即成了:
输出输入向量更新为:
注意,对于所有的输入词,输入向量都是同一个矩阵。
2.3 Skip-Gram
直观来看,skip-gram实际上利用单个词预测上下文。我们设置skip_window和num_skip两个参数,前者代表上文或者下文的个数,后者代表从窗口中选取输出词的数量。同样对于文本"I love you three thousand":
设 skip_window = 1, num_skip=3, 意味着我们的窗口值(包括输入词)为span = 2*1+1 = 5, 输出词个数为3,即:
Input: “you” output=[“I love you”, “love you three”, “you three thousand”)]
损失函数为:
其中
为输出层所有词的错误和。
输出向量更新公式:
输入向量更新公式:
3. 优化计算效率的两种方法
我们注意到,输入向量的学习是很轻松的,但是输出向量的更新却很繁重。对于每个训练示例(training instance),我们都需要遍历一遍vocab中的所有词语,计算每个词语的概率,损失,然后更新相对应输出向量,这对于动辄几万几十万的vocab来说计算成本巨大,所以有一个优化的思路是减少每次训练是需要更新的输出向量。
3.1 Hierarchical Softmax
Hierarchical Softmax是一个利用霍夫曼树来表示vocab中所有词来达到优化softmax计算的方法。首先,将原先模型的输出向量矩阵替代成如下的霍夫曼树:
白色的叶结点代表输出层的词,共V个; 黑色结点为内部节点,共V-1个。图中显示从隐藏层到输出层的路径,路径长度,代表该路径上的第i个内部节点。
原先用输出向量表示输出词,现在变成了用路径上每个节点表示。树中每一个内部节点都有一个输出向量,所以相应的,输出词的概率也变成了:
表示节点的左节点,
直观的理解就是预测值为实际值的概率是在的每一个节点都取左节点的概率。
更新的式子为:
其中
就是路径上每个词语的内部节点的预测error。我们根据词频构建霍夫曼树,出现频率越高的词拥有越短的路径(内部节点越少),所需要更新的也越少。因此,我们的更新参数时的计算复杂度从原来的O(V)减少到了O(logV)。当然,我们的总参数量并没有显著减少()。
3.2 Negative Sampling
Negative Sampling的优化思路简单暴力,我们称输出词为正样本,非输出词为负样本,我们基于经验选择特定的概率分布作为样本的噪音分布,基于选择K个负样本:
更新方程:
所以,每次更新,我们只需要更新正样本和K个负样本就好了,显著地减少了计算时间。
参考资料:
Rong, Xin. “word2vec parameter learning explained.” arXiv preprint arXiv:1411.2738 (2014).