本文介绍两种更新一点的词向量,它们分别是 2014 年由 Stanford 团队发表的 Glove 和 2017 年由 Facebook 团队发表的 fastText
Glove
Glove 使用了词与词之间的共现(co-occurrence)信息。我们定义 $X$ 为共现词频矩阵,其中元素 $x_{ij}$ 表示词 $j$ 出现在词 $i$ 的环境(context)的次数。这里的 "环境" 有多种定义。举个例子,在一段文本序列中,如果词 $j$ 出现在词 $i$ 左边或者右边不超过 10 个词的距离,我们可以认为词 $j$ 出现在词 $i$ 的环境一次。令 $x_i=\sum_kx_{ik}$ 为任意词出现在词 $i$ 的环境的次数。那么
$$ P_{ij}=P(j\mid i)=\frac{x_{ij}}{x_i} $$
为词 $j$ 出现在词 $i$ 的环境的概率。这一概率也称为词 $i$ 和词 $j$ 的共现概率
共现概率比值
Glove 论文里展示了以下一组词对的共现概率与比值
$w_k$ | solid | gas | water | fashion |
---|---|---|---|---|
$p_1=P(w_k\mid \text{ice})$ | 0.00019 | 0.000066 | 0.003 | 0.000017 |
$p_2=P(w_k\mid \text{steam})$ | 0.000022 | 0.00078 | 0.0022 | 0.000018 |
$p_1/p_2$ | 8.9 | 0.085 | 1.36 | 0.96 |
我们可以观察到以下现象:
- 对于与 ice 相关而与 steam 不相关的词 $k$,例如 $k$=solid,我们期望共现概率比值 $\frac {P_{ik}}{P_{jk}}$ 较大,例如上面最后一栏的 8.9
- 对于与 ice 不相关而与 steam 相关的词 $k$,例如 $k$=gas,我们期望共现概率比值 $\frac {P_{ik}}{P_{jk}}$ 较小,例如上面最后一栏的 0.085
- 对于与 ice 和 steam 都相关的词 $k$,例如 $k$=water,我们期望共现概率比值 $\frac {P_{ik}}{P_{jk}}$ 接近 1,例如上面最后一栏的 1.36
- 对于与 ice 和 steam 都不相关的词 $k$,例如 $k$=fashion,我们期望共现概率比值 $\frac {P_{ik}}{P_{jk}}$ 接近 1,例如上面最后一栏的 0.96
由此可见,共现概率比值能比较直观的表达词之间的关系。Glove 试图用有关词向量的函数来表达共现概率比值
用词向量表达共现概率比值
Glove 的核心在于使用词向量表达共现概率比值。而任意一个这样的比值需要三个词 $i$、$j$ 和 $k$ 的词向量。对于共现概率 $P_{ij}=P (j\mid i)$,我们称词 $i$ 和词 $j$ 分别为中心词和背景词。我们使用 $\boldsymbol {v}$ 和 $\boldsymbol {\tilde {v}}$ 分别表示中心词和背景词的词向量
我们可以用有关词向量的函数 $f$ 来表达共现概率比值:
$$ f(\boldsymbol{v}_i,\boldsymbol{v}_j,\boldsymbol{\tilde{v}}_k)=\frac{P_{ik}}{P_{jk}} $$
需要注意的是,函数 $f$ 可能涉及的并不唯一。首先,我们用向量之差来表达共现概率的比值,并将上式改写成
$$ f(\boldsymbol{v}_i-\boldsymbol{v}_j,\boldsymbol{\tilde{v}}_k)=\frac{P_{ik}}{P_{jk}} $$
由于共现概率比值是一个标量,我们可以使用向量之间的内积把函数 $f$ 的自变量进一步改写
$$ f((\boldsymbol{v}_i-\boldsymbol{v}_j)^T\boldsymbol{\tilde{v}}_k)=\frac{P_{ik}}{P_{jk}} $$
由于任意一对词共现的对称性,我们希望以下两个性质可以同时被满足:
- 任意词作为中心词和背景词的词向量应该相等:对任意词 $i$,$\boldsymbol {v}_i=\boldsymbol {\tilde {v}}_i$
- 词与词之间共现次数矩阵 $X$ 应该对称:对任意词 $i$ 和 $j$,$x_{ij}=x_{ji}$
为了满足以上两个性质,一方面我们令
$$ f((\boldsymbol{v}_i-\boldsymbol{v}_j)^T\boldsymbol{\tilde{v}}_k)=\frac{f(\boldsymbol{v}_i^T\boldsymbol{\tilde{v}}_k)}{f(\boldsymbol{v}_j^T\boldsymbol{\tilde{v}}_k)} $$
并得到 $f (x)=\exp (x)$。以上两式右边联立
$$ \exp(\boldsymbol{v}_i^T\boldsymbol{\tilde{v}}_k)=P_{ik}=\frac{x_{ik}}{x_i} $$
上式两边取对数可得
$$ \boldsymbol{v}_i^T\boldsymbol{\tilde{v}}_k=\log(x_{ik})-\log(x_i) $$
另一方面,我们可以把上式中的 $\log (x_i)$ 替换成两个偏移项之和 $b_i+b_k$,得到
$$ \boldsymbol{v}_i^T\boldsymbol{\tilde{v}}_k=\log(x_{ik})-b_i-b_k $$
将索引 $i$ 和 $k$ 互换,我们可以验证对称性的两个性质可以同时被上式满足
因此,对于任意一对词 $i$ 和 $j$,用它们的词向量表达共现概率比值最终可以被简化为表达他们共现词频的对数:
$$ \boldsymbol{v}_i^T\boldsymbol{\tilde{v}}_k+b_i+b_k=\log(x_{ik}) $$
损失函数
上式中的共现词频是直接在训练数据上统计得到的,为了学习词向量和相应的偏移项,我们希望上式中的左边与右边越接近越好,给定词典大小 $V$ 和权重函数 $f (x_{ij})$,我们定义损失函数为
$$ \sum_{i,j=1}^{V}f(x_{ij})(\boldsymbol{v}_i^T\boldsymbol{\tilde{v}}_k+b_i+b_k-\log(x_{ik}))^2 $$
对于权重 $f (x)$,一个建议的选择是,当 $x<c$(例如 $c=100$),令 $f (x)=(x/c)^a$(例如 $a=0.75$),反之令 $f (x)=1$。需要注意的是,损失函数的计算复杂度与共现词频矩阵 $X$ 中非零元素的数目呈线性关系。我们可以从 $X$ 中随机采样小批量非零元素,使用随机梯度下降迭代词向量和偏移项。当所有词向量学习得到后,Glove 是用一个词的中心词向量与背景词向量之和作为该词的最终词向量
关于 Glove 的一些公式推导,其实并不严谨,它只是提出了一些设计思路,为了满足那两个条件,共现词频应该设计成什么样。所以如果某一步推导看不懂也很正常,忽略过去就行了,只要知道最终的损失函数的性质就行
fastText
fastText 在使用负采样的 skip-gram 模型基础上,将每个中心词视为子词(subword)的集合,并学习子词的词向量
以 where 这个词为例,设子词为 3 个字符,它的子词包括 "<wh"、"whe"、"her"、"ere"、"re>" 和特殊子词(整词)"<where>",其中 "<" 和 ">" 是为了将作为前后缀的子词区分出来。而且,这里的子词 "her" 与整词 "<her>" 也可被区分。给定一个词 $w$,我们通常可以把字符长度在 3 到 6 之间的所有子词和特殊子词的并集 $\mathcal {G}_{w}$ 取出。假设词典中任意子词 $g$ 的子词向量为 $\boldsymbol {z}_g$,我们可以把使用负采样的 skip-gram 模型的损失函数
$$ -\log P(w_o\mid w_c)=-\log\frac{1}{1+\exp(-\boldsymbol u_o^T\boldsymbol{v}_c)}-\sum_{k=1,w_k\sim P(w)}^K\log\frac{1}{1+\exp(\boldsymbol u_{i_k}^T\boldsymbol{v}_c)} $$
直接替换成
$$ \begin{aligned} &-\log P(w_o\mid w_c)=\\ &-\log\frac{1}{1+\exp(-\boldsymbol u_o^T\sum_{g\in \mathcal{G}_{w_c}}\boldsymbol{z}_g)}-\sum_{k=1,w_k\sim P(w)}^K\log\frac{1}{1+\exp(\boldsymbol u_{i_k}^T\sum_{g\in \mathcal{G}_{w_c}}\boldsymbol{z}_g)} \end{aligned} $$
我们可以看到,原中心词向量被替换成了中心词的子词向量的和。与整词学习(word2vec 和 Glove)不同,词典以外的新词的词向量可以使用 fastText 中相应的子词向量之和
fastText 对于一些特定语言较重要,例如阿拉伯语、德语和俄语。例如,德语中有很多复合词,例如乒乓球(英文 table tennis)在德语中叫 "Tischtennis"。fastText 可以通过子词表达两个词的相关性,例如 "Tischtennis" 和 "Tennis"
如果遇到一个新词,对于 fastText 来说,它可以从训练集中找出这个新词的所有子词向量,然后做个求和,就能算出这个新词的词向量了
博主,最上面提供的共现概率比值表,第一列都是 P (wk|ice) 吗?是不是写错了,有一个应该是 steam?
是的,感谢提醒,已修正