全局向量的词嵌入(GloVe) :label: 上下文窗口内的词共现可以携带丰富的语义信息。例如,在一个大型语料库中,“固体”比“气体”更有可能与“冰”共现,但“气体”一词与“蒸汽”的共现频率可能比与“冰”的共现频率更高。此外,可以预先计算此类共现的全局语料库统计数据:这可以提高训练效率。为了利用整个语料库中的统计信息进行词嵌入,让我们首先回顾 :numref: 中的跳元模型,但是使用全局语料库统计(如共现计数)来解释它。
🏷sec_glove
上下文窗口内的词共现可以携带丰富的语义信息。例如,在一个大型语料库中,“固体”比“气体”更有可能与“冰”共现,但“气体”一词与“蒸汽”的共现频率可能比与“冰”的共现频率更高。此外,可以预先计算此类共现的全局语料库统计数据:这可以提高训练效率。为了利用整个语料库中的统计信息进行词嵌入,让我们首先回顾 :numref:subsec_skip-gram中的跳元模型,但是使用全局语料库统计(如共现计数)来解释它。
🏷subsec_skipgram-global
用q_{ij}表示词w_j的条件概率P(w_j\mid w_i),在跳元模型中给定词w_i,我们有:
其中,对于任意索引i,向量\mathbf{v}_i和\mathbf{u}_i分别表示词w_i作为中心词和上下文词,且\mathcal{V} = \{0, 1, \ldots, |\mathcal{V}|-1\}是词表的索引集。
考虑词w_i可能在语料库中出现多次。在整个语料库中,所有以w_i为中心词的上下文词形成一个词索引的多重集\mathcal{C}_i,该索引允许同一元素的多个实例。对于任何元素,其实例数称为其重数。举例说明,假设词w_i在语料库中出现两次,并且在两个上下文窗口中以w_i为其中心词的上下文词索引是k, j, m, k和k, l, k, j。因此,多重集\mathcal{C}_i = \{j, j, k, k, k, k, l, m\},其中元素j, k, l, m的重数分别为2、4、1、1。
现在,让我们将多重集\mathcal{C}_i中的元素j的重数表示为x_{ij}。这是词w_j(作为上下文词)和词w_i(作为中心词)在整个语料库的同一上下文窗口中的全局共现计数。使用这样的全局语料库统计,跳元模型的损失函数等价于:
:eqlabel:eq_skipgram-x_ij
我们用x_i表示上下文窗口中的所有上下文词的数量,其中w_i作为它们的中心词出现,这相当于|\mathcal{C}_i|。设p_{ij}为用于生成上下文词w_j的条件概率x_{ij}/x_i。给定中心词w_i, :eqref:eq_skipgram-x_ij可以重写为:
:eqlabel:eq_skipgram-p_ij
在 :eqref:eq_skipgram-p_ij中,-\sum_{j\in\mathcal{V}} p_{ij} \log\,q_{ij}计算全局语料统计的条件分布p_{ij}和模型预测的条件分布q_{ij}的交叉熵。如上所述,这一损失也按x_i加权。在 :eqref:eq_skipgram-p_ij中最小化损失函数将使预测的条件分布接近全局语料库统计中的条件分布。
虽然交叉熵损失函数通常用于测量概率分布之间的距离,但在这里可能不是一个好的选择。一方面,正如我们在 :numref:sec_approx_train中提到的,规范化q_{ij}的代价在于整个词表的求和,这在计算上可能非常昂贵。另一方面,来自大型语料库的大量罕见事件往往被交叉熵损失建模,从而赋予过多的权重。
有鉴于此,GloVe模型基于平方损失 :cite:Pennington.Socher.Manning.2014对跳元模型做了三个修改:
整合代码,训练GloVe是为了尽量降低以下损失函数:
:eqlabel:eq_glove-loss
对于权重函数,建议的选择是:当x < c(例如,c = 100)时,h(x) = (x/c) ^\alpha(例如\alpha = 0.75);否则h(x) = 1。在这种情况下,由于h(0)=0,为了提高计算效率,可以省略任意x_{ij}=0的平方损失项。例如,当使用小批量随机梯度下降进行训练时,在每次迭代中,我们随机抽样一小批量非零的x_{ij}来计算梯度并更新模型参数。注意,这些非零的x_{ij}是预先计算的全局语料库统计数据;因此,该模型GloVe被称为全局向量。
应该强调的是,当词w_i出现在词w_j的上下文窗口时,词w_j也出现在词w_i的上下文窗口。因此,x_{ij}=x_{ji}。与拟合非对称条件概率p_{ij}的word2vec不同,GloVe拟合对称概率\log \, x_{ij}。因此,在GloVe模型中,任意词的中心词向量和上下文词向量在数学上是等价的。但在实际应用中,由于初始值不同,同一个词经过训练后,在这两个向量中可能得到不同的值:GloVe将它们相加作为输出向量。
我们也可以从另一个角度来理解GloVe模型。使用 :numref:subsec_skipgram-global中的相同符号,设p_{ij} \stackrel{\mathrm{def}}{=} P(w_j \mid w_i)为生成上下文词w_j的条件概率,给定w_i作为语料库中的中心词。 :numref:tab_glove根据大量语料库的统计数据,列出了给定单词“ice”和“steam”的共现概率及其比值。
:大型语料库中的词-词共现概率及其比值(根据 :cite:Pennington.Socher.Manning.2014中的表1改编)
| 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 |
🏷tab_glove |
从 :numref:tab_glove中,我们可以观察到以下几点:
由此可见,共现概率的比值能够直观地表达词与词之间的关系。因此,我们可以设计三个词向量的函数来拟合这个比值。对于共现概率{p_{ij}}/{p_{ik}}的比值,其中w_i是中心词,w_j和w_k是上下文词,我们希望使用某个函数f来拟合该比值:
:eqlabel:eq_glove-f
在f的许多可能的设计中,我们只在以下几点中选择了一个合理的选择。因为共现概率的比值是标量,所以我们要求f是标量函数,例如f(\mathbf{u}_j, \mathbf{u}_k, {\mathbf{v}}_i) = f\left((\mathbf{u}_j - \mathbf{u}_k)^\top {\mathbf{v}}_i\right)。在 :eqref:eq_glove-f中交换词索引j和k,它必须保持f(x)f(-x)=1,所以一种可能性是f(x)=\exp(x),即:
现在让我们选择\exp\left(\mathbf{u}_j^\top {\mathbf{v}}_i\right) \approx \alpha p_{ij},其中\alpha是常数。从p_{ij}=x_{ij}/x_i开始,取两边的对数得到\mathbf{u}_j^\top {\mathbf{v}}_i \approx \log\,\alpha + \log\,x_{ij} - \log\,x_i。我们可以使用附加的偏置项来拟合- \log\, \alpha + \log\, x_i,如中心词偏置b_i和上下文词偏置c_j:
:eqlabel:eq_glove-square
通过对 :eqref:eq_glove-square的加权平方误差的度量,得到了 :eqref:eq_glove-loss的GloVe损失函数。
Pennington.Socher.Manning.2014的第4.2节。