一、Glove简介
GloVe (Global Vectors for Word Representation) 是一种基于词共现矩阵的词向量生成方法,由斯坦福大学的 Jeffrey Pennington、Richard Socher 和 Christopher D. Manning 提出。与 Word2Vec 不同,GloVe 通过全局统计信息(词共现信息)来学习词嵌入,能够有效捕捉到语料库中单词与单词之间的全局共现关系。
1. 词共现
GloVe 的词共现处理
GloVe 通过直接构建 全局词共现矩阵 来学习词向量。这意味着 GloVe 模型在整个语料库中统计每个词对的共现次数,然后根据这些全局的共现统计来训练模型。
GloVe 的词共现特点
- 全局信息:GloVe 使用整个语料库中的词共现信息,构建一个包含所有词对的共现矩阵。
- 统计共现频率:词共现次数直接用于构建目标函数,最小化词向量之间的点积和共现信息的差异。
- 对数处理:GloVe 对共现次数取对数,减少了高频词的影响,帮助模型捕捉更丰富的词语义关系。
Word2Vec 的词共现处理
Word2Vec 通过局部上下文窗口 来处理词共现,但它并不直接构建词共现矩阵,而是通过 Skip-gram 或 CBOW 模型在训练过程中逐步学习。它利用每个目标词的局部上下文来进行模型优化。
Word2Vec 的词共现特点
- 局部上下文:Word2Vec 仅在每次训练时使用局部上下文的词共现信息,而不会显式地构建一个全局的词共现矩阵。
- 正样本和负样本:在 Skip-gram 中,Word2Vec 对目标词周围的上下文词作为正样本进行训练,并通过负采样选择随机的词作为负样本来优化模型。
- 隐式处理词共现:Word2Vec 并不存储词共现次数,而是通过训练优化词向量,使其在局部上下文中相似词的向量接近,不相似词的向量远离。
举例比较
GloVe 的词共现矩阵构建
假设有以下语料:
I love deep learning.
Deep learning is amazing.
Word2vec is great.
GloVe 首先会基于整个语料库构建一个共现矩阵。假设我们用窗口大小为 2,得到以下矩阵:
I | love | deep | learning | is | amazing | word2vec | great | |
---|---|---|---|---|---|---|---|---|
I | - | 1 | 0 | 1 | 0 | 0 | 0 | 0 |
love | 1 | - | 1 | 1 | 0 | 0 | 0 | 0 |
deep | 0 | 1 | - | 2 | 1 | 1 | 0 | 0 |
learning | 1 | 1 | 2 | - | 1 | 1 | 0 | 0 |
is | 0 | 0 | 1 | 1 | - | 1 | 1 | 1 |
amazing | 0 | 0 | 1 | 1 | 1 | - | 0 | 0 |
word2vec | 0 | 0 | 0 | 0 | 1 | 0 | - | 1 |
great | 0 | 0 | 0 | 0 | 1 | 0 | 1 | - |
- 这个共现矩阵记录了每对词在整个语料库中共现的次数。
- 例如,
deep
和learning
在两个句子中都出现了,所以共现次数为 2。 - 训练时,GloVe 通过最小化词向量的点积和这些共现次数的对数值之间的差异来生成词向量。
Word2Vec 的局部共现
对于同样的语料,Word2Vec 不会显式构建一个词共现矩阵,而是通过局部上下文进行训练。例如,假设我们训练目标词 deep
,上下文窗口为 2,那么:
deep
的上下文词是love
和learning
。- 模型会通过 Skip-gram 方法,训练
deep
来预测love
和learning
,同时通过负采样,避免处理整个词汇表中的所有词。
因此,Word2Vec 更侧重于局部上下文的词共现关系,而不是像 GloVe 那样全局处理所有词对的共现。
2. 词嵌入模型对比
GloVe 模型作为一种经典的词嵌入方法,与其相关或相似的模型有很多,尤其是在自然语言处理中词向量生成方面。以下是对 GloVe 及其相关模型的对比分析,包括 Word2Vec、FastText,以及后来的基于上下文的词嵌入模型(如 ELMo、BERT)。
1. GloVe vs. Word2Vec
相似点:
- 目的:两者都旨在通过学习词向量来捕捉词语的语义关系,使得相似的词在向量空间中更接近。
- 静态词向量:GloVe 和 Word2Vec 都属于静态词向量模型,这意味着一个词的向量是固定的,无论它在不同上下文中出现时语义是否有变化。
差异点:
特性 | GloVe | Word2Vec |
---|---|---|
核心思想 | 基于全局词共现矩阵构建词向量。 | 基于上下文窗口,使用预测任务(CBOW 或 Skip-gram)。 |
训练方式 | 通过统计词的共现频率来训练。 | 基于预测的方式,CBOW 预测中心词,Skip-gram 预测上下文词。 |
全局 vs. 局部 | 使用整个语料库的词共现信息,捕捉全局关系。 | 仅使用局部上下文窗口(固定窗口大小,通常为5或10)。 |
性能 | 在大语料上表现较好,能更好地捕捉全局关系。 | 在较小的语料上表现良好,特别是在训练速度和资源方面有优势。 |
训练目标 | 通过最小化点积和词共现概率之间的差异。 | 通过最大化中心词和上下文词的概率(Skip-gram)。 |
解释:
GloVe 是基于矩阵分解的模型,通过统计整个语料库的词共现信息构建词向量,能更好地捕捉到全局的语义关系。而 Word2Vec 使用局部上下文
的预测模型(CBOW 或 Skip-gram)来学习词向量,通过直接预测上下文词与目标词的关系。这使得 Word2Vec 更加高效,并且在较小数据集上可以表现良好,但它捕捉的是局部的上下文信息。
2. GloVe vs. FastText
相似点:
- 静态词向量:与 GloVe 一样,FastText 也是一种静态词向量生成模型,一个词在不同的上下文中拥有相同的向量表示。
- 目标:都致力于捕捉词语的语义关系,使得语义相近的词在向量空间中的距离较近。
差异点:
特性 | GloVe | FastText |
---|---|---|
核心思想 | 基于全局词共现信息,优化全局词汇表中的词向量。 | 基于 Word2Vec,增加了子词信息(n-gram),更好地处理稀有词和形态学。 |
词形处理 | 对每个词生成一个唯一的词向量,忽略子词信息。 | 对每个词生成多个子词(n-gram)的向量,词的向量是这些子词向量的组合。 |
稀有词表现 | 对于词表之外的稀有词没有处理方式。 | 通过子词分解,能更好地处理稀有词和未登录词(out-of-vocabulary)。 |
上下文依赖 | 不考虑词的形态特征。 | 考虑到词的内部结构,通过子词分解,捕捉更多语义信息。 |
解释:
FastText 的最大优势在于它引入了子词(n-gram)的概念,这使得它可以更好地处理那些不常见的词,尤其是对于形态丰富的语言(如德语、法语等),能够生成更加细粒度的词向量。而 GloVe 在处理稀有词时表现不如 FastText,因为它的词向量是基于整个词的,而不是子词。
3. GloVe vs. ELMo
相似点:
- 语义信息捕捉:两者都用于生成词的语义表示,但 GloVe 和 ELMo 在设计和使用上存在显著的区别。
差异点:
特性 | GloVe | ELMo |
---|---|---|
词向量性质 | 静态词向量,一个词无论上下文如何都有相同的向量。 | 动态词向量,根据上下文动态生成不同的词向量。 |
上下文依赖 | 不考虑上下文,词的向量是全局语料的统计结果。 | 考虑上下文,通过双向 LSTM 生成词的上下文表示。 |
复杂性 | 计算简单,训练相对快速,易于大规模应用。 | 计算复杂,使用深度学习模型(LSTM)生成向量,训练和推理成本更高。 |
应用场景 | 适合不需要上下文动态变化的 NLP 任务。 | 适合需要深度上下文理解的任务(如阅读理解、问答系统)。 |
解释:
ELMo 是一种基于上下文的词嵌入模型,每个词的向量是基于它在句子中的上下文生成的。这意味着同一个词在不同句子中的表示可能不同。例如,"bank"在"金融机构"和"河岸"两种上下文中会有不同的词向量。而 GloVe 则是静态的,一个词无论出现在任何上下文中,其词向量都是固定的。
4. GloVe vs. BERT
相似点:
- 用于生成词的语义表示:两者都用于生成词的向量表示,但 BERT 更强大,且基于深度上下文表示。
差异点:
特性 | GloVe | BERT |
---|---|---|
词向量性质 | 静态词向量,不考虑上下文变化。 | 动态词向量,依赖上下文双向表示。 |
训练方式 | 基于词共现矩阵的矩阵分解。 | 通过预训练任务(掩蔽语言模型和下一句预测)进行深度训练。 |
模型架构 | 无特定的深度网络架构。 | 基于 Transformer 架构,使用多层自注意力机制。 |
复杂性和能力 | 简单,适合快速构建词向量。 | 复杂,能够更好地捕捉深度语义关系,但计算成本更高。 |
语义表现 | 捕捉静态的语义信息,不能处理多义词等复杂现象。 | 动态捕捉上下文中的词义变化,能够处理多义词和长距离依赖。 |
解释:
BERT 是目前更先进的词嵌入模型,它不仅通过双向 Transformer 捕捉到词的上下文信息,还能对多义词、长距离依赖和句子间关系等进行更准确的语义建模。而 GloVe 更加简单,适合需要快速生成静态词嵌入的场景,但在复杂任务上表现不如 BERT。
总结
- GloVe 主要基于全局词共现信息,适合全局语义关系的捕捉,但无法处理动态上下文中的语义变化。
- Word2Vec 和 FastText 更注重局部上下文,FastText 通过子词分解增强了对稀有词的处理能力。
- ELMo 和 BERT 是基于上下文的词嵌入模型,能够捕捉词语在不同语境中的动态语义,特别是在多义词或需要深度上下文理解的任务中表现优异。
GloVe 适合处理那些不需要上下文敏感的任务,而对于需要更复杂语义建模的任务,如阅读理解和问答系统,基于上下文的模型如 ELMo 和 BERT 则更为强大。
二、Glove实现原理
1. 构建共现矩阵
共现矩阵顾名思义就是共同出现的意思。局域窗中的word-word共现矩阵可以挖掘语法和语义信息,例如:
I like deep learning.
I like NLP.
I enjoy flying
以上三句话设置滑窗为2,可以得到一个词典:{"I like","like deep","deep learning","like NLP","I enjoy","enjoy flying","I like"}。我们可以得到一个共现矩阵(对称矩阵):
中间的每个格子表示的是行和列组成的词组在词典中共同出现的次数,也就体现了共现的特性。
GloVe的共现矩阵
根据语料库(corpus)构建一个共现矩阵(Co-ocurrence Matrix) X X X,矩阵中的每一个元素 X i j X_{ij} Xij 代表单词 i i i 和上下文单词 j j j 在特定大小的上下文窗口(context window)内共同出现的次数。一般而言,这个次数的最小单位是1,但是GloVe不这么认为:它根据两个单词在上下文窗口的距离 d d d,提出了一个衰减函数(decreasing weighting): d e c a y = 1 / d decay=1/d decay=1/d 用于计算权重,也就是说距离越远的两个单词所占总计数(total count)的权重越小。
2. 词向量和共现矩阵的近似关系
构建词向量(Word Vector)和共现矩阵(Co-ocurrence Matrix)之间的近似关系,论文的作者提出以下的公式可以近似地表达两者之间的关系:
w i T w j ~ + b i + b j ~ = log ( X i j ) w_{i}^{T}\tilde{w_{j}} + b_i + \tilde{b_j} = \log(X_{ij}) wiTwj~+bi+bj~=log(Xij)
其中 w i T w_{i}^{T} wiT和 w j ~ \tilde{w_{j}} wj~是我们最终要求解的词向量, b i b_i bi和 b j ~ \tilde{b_j} bj~分别是两个词向量的bias term。问题来了,这个公式是如何来的?为了把这个问题说清楚,我们先定义一些变量:
- X i j X_{ij} Xij表示单词 j j j出现在单词 i i i的上下文中的次数
- X i X_{i} Xi表示单词 i i i的上下文中所有单词出现的总次数,即 X i = ∑ k X i k X_{i} = \sum^{k} X_{ik} Xi=∑kXik
- P i j = P ( j ∣ i ) = X i j / X i P_{ij} = P(j|i) = X_{ij}/X_{i} Pij=P(j∣i)=Xij/Xi,即表示单词 j j j出现在单词 i i i的上下文中的概率
有了这些定义之后,我们来看一个表格:
理解这个表格的重点在最后一行,它表示的是两个概率的比值(ratio),我们可以使用它观察出两个单词 i i i 和 j j j 相对于单词 k k k 哪个更相关(relevant)。
1. 引入共现概率与词语关系的例子
为了展示如何从词共现概率中提取语义,文中首先给出了一个例子。设定两个词 i i i 和 j j j,分别是 "ice"(冰)和 "steam"(蒸汽)。我们可以通过它们与探测词(probe words) k k k 的共现概率比值 P i k / P j k P_{ik} / P_{jk} Pik/Pjk 来探究它们之间的语义关系。
- 相关的探测词 :比如 k = s o l i d k = solid k=solid(固体)与 "ice" 更相关,与 "steam" 不相关,因此我们期望 P i k / P j k P_{ik} / P_{jk} Pik/Pjk 比较大。
- 不相关的探测词 :比如 k = g a s k = gas k=gas(气体)与 "steam" 更相关,与 "ice" 不相关,因此我们期望 P i k / P j k P_{ik} / P_{jk} Pik/Pjk 比较小。
- 通用探测词 :比如 k = w a t e r k = water k=water(水)或者 k = f a s h i o n k = fashion k=fashion(时尚),它们与 "ice" 和 "steam" 关系都比较少,或者是与两者都相关,因此期望 P i k / P j k P_{ik} / P_{jk} Pik/Pjk 比值接近 1。
这种共现概率的比值能够更好地区分出相关词与不相关词,也能更清晰地区分相关词的细微差别。因此,这个例子说明了共现概率比值比直接使用概率本身更有助于提取语义。
2. 从共现概率比值构建词向量模型
通过上述例子,推导出的结论是:词向量学习的合适起点应该是共现概率的比值,而不是直接使用共现概率。因此,我们定义了以下模型:
F ( w i , w j , w ~ k ) = P i k P j k , F(w_i, w_j, \tilde{w}k) = \frac{P{ik}}{P_{jk}}, F(wi,wj,w~k)=PjkPik,
其中 w i w_i wi 和 w j w_j wj 是词 i i i 和 j j j 的词向量, w ~ k \tilde{w}k w~k 是上下文词 k k k 的词向量, P i k P{ik} Pik 和 P j k P_{jk} Pjk 是词 i i i 和 j j j 与上下文词 k k k 的共现概率。
为了使模型能够表达词语之间的关系,我们希望函数 F F F 只依赖于两个目标词之间的向量差异。因此,我们将模型简化为:
F ( w i − w j , w ~ k ) = P i k P j k . F(w_i - w_j, \tilde{w}k) = \frac{P{ik}}{P_{jk}}. F(wi−wj,w~k)=PjkPik.
3. 将模型线性化
接下来,为了保持词向量模型的线性结构,我们通过向量点积将模型进一步简化:
F ( ( w i − w j ) T w ~ k ) = P i k P j k . F\left((w_i - w_j)^T \tilde{w}k\right) = \frac{P{ik}}{P_{jk}}. F((wi−wj)Tw~k)=PjkPik.
此处我们通过点积操作避免了向量维度混合,并确保模型能够处理词语的线性语义关系。
4. 引入对称性和偏置项
为了保持词向量和上下文词向量之间的对称性,我们进一步简化模型,要求它能够处理词语和上下文之间的角色对调。最终,模型形式化为以下表达式:
F ( ( w i − w j ) T w ~ k ) = F ( w i T w ~ k ) F ( w j T w ~ k ) , F\left((w_i - w_j)^T \tilde{w}_k\right) = \frac{F(w_i^T \tilde{w}_k)}{F(w_j^T \tilde{w}_k)}, F((wi−wj)Tw~k)=F(wjTw~k)F(wiTw~k),
这个等式的解是 F = exp F = \exp F=exp,因此我们得到:
w i T w ~ k = log ( P i k ) = log ( X i k ) − log ( X i ) , w_i^T \tilde{w}k = \log(P{ik}) = \log(X_{ik}) - \log(X_i), wiTw~k=log(Pik)=log(Xik)−log(Xi),
其中 X i k X_{ik} Xik 是词 i i i 和上下文词 k k k 的共现频次, X i X_i Xi 是词 i i i 的总共现次数。
接下来我们引入了偏置项 b i b_i bi 和 b k b_k bk,以捕捉词的全局频率信息,从而得到最终的模型:
w i T w ~ k + b i + b ~ k = log ( X i k ) . w_i^T \tilde{w}_k + b_i + \tilde{b}k = \log(X{ik}). wiTw~k+bi+b~k=log(Xik).
5. 避免对数发散问题
由于 log ( X i k ) \log(X_{ik}) log(Xik) 在 X i k = 0 X_{ik} = 0 Xik=0 时会发散,我们通过将 log ( X i k ) \log(X_{ik}) log(Xik) 替换为 log ( 1 + X i k ) \log(1 + X_{ik}) log(1+Xik) 来解决这一问题:
w i T w ~ k + b i + b ~ k = log ( 1 + X i k ) . w_i^T \tilde{w}_k + b_i + \tilde{b}k = \log(1 + X{ik}). wiTw~k+bi+b~k=log(1+Xik).
这一修改保持了共现矩阵 X X X 的稀疏性,同时避免了零值导致的发散问题。
6. 引入加权最小二乘回归
模型的另一个改进是解决稀有共现对(噪声数据)对模型训练的影响。文中引入了加权最小二乘回归模型 ,为每个词对 i i i 和 j j j 引入权重函数 f ( X i j ) f(X_{ij}) f(Xij),用于调节不同词对的影响权重,最终的目标函数为:
J = ∑ i , j f ( X i j ) ( w i T w ~ j + b i + b ~ j − log ( X i j ) ) 2 . J = \sum_{i,j} f(X_{ij}) \left( w_i^T \tilde{w}_j + b_i + \tilde{b}j - \log(X{ij}) \right)^2. J=i,j∑f(Xij)(wiTw~j+bi+b~j−log(Xij))2.
7. 权重函数的定义
权重函数 f ( X i j ) f(X_{ij}) f(Xij) 需要满足以下条件:
- f ( 0 ) = 0 f(0) = 0 f(0)=0:当 X i j → 0 X_{ij} \to 0 Xij→0 时,权重函数 f ( X i j ) f(X_{ij}) f(Xij) 应该趋于 0,以减少稀有共现对的影响。
- f ( x ) f(x) f(x) 是非递减的:确保稀有共现不会被过度加权。
- 对于大的 x x x, f ( x ) f(x) f(x) 应较小:防止频繁共现对过度影响模型。
权重函数定义为:
f ( x ) = { ( x x max ) α if x < x max 1 if x ≥ x max f(x) = \begin{cases} \left(\frac{x}{x_{\text{max}}}\right)^\alpha & \text{if } x < x_{\text{max}} \\ 1 & \text{if } x \geq x_{\text{max}} \end{cases} f(x)={(xmaxx)α1if x<xmaxif x≥xmax
其中, x max x_{\text{max}} xmax 和 α \alpha α 是控制权重分布的超参数。
权重函数 f ( x ) f(x) f(x) 的作用
这个函数的作用是根据词对的共现频次来调整它们在损失函数中的权重,从而平衡高频和低频词对的影响。具体分为以下两种情况:
1. 当词对的共现频次 x < x max x < x_{\text{max}} x<xmax 时
在这种情况下,权重函数是递增的,权重 f ( x ) = ( x x max ) α f(x) = \left( \frac{x}{x_{\text{max}}} \right)^\alpha f(x)=(xmaxx)α,它会随着词对共现次数的增加而增大,但增长速度由 α \alpha α 控制。对于低频词对,权重会相对较大,这样可以增强这些词对的影响。
2. 当词对的共现频次 x ≥ x max x \geq x_{\text{max}} x≥xmax 时
在这种情况下,权重函数的值固定为 1 1 1,意味着当共现次数超过阈值 x max x_{\text{max}} xmax 后,权重不再继续增加。这对于高频词对来说非常重要。
自然语言中的词汇具有长尾分布。少数词汇(如"the"、"and")非常高频,而大多数词汇(如专业名词、形容词)出现频率较低。如果不对这些词对的影响进行控制,那么高频词对会主导模型的训练,稀有词对则很难起到作用。
GloVe 的权重函数旨在平衡这些高频词对和低频词对:
- 对于低频词对,给予更高的权重,以确保它们对模型有足够的影响。
- 对于高频词对,限制它们的权重,避免它们主导模型的训练。
3. 举例说明
假设在一个大型文本语料中,我们有以下词对及其共现次数:
- "book" 和 "read" 共现 10 次
- "the" 和 "book" 共现 5000 次
- "library" 和 "book" 共现 5 次
设置 x max = 100 x_{\text{max}} = 100 xmax=100 和 α = 0.75 \alpha = 0.75 α=0.75,那么权重函数 f ( x ) f(x) f(x) 的影响如下:
对于"book" 和 "read"(共现 10 次)
由于 x = 10 < x max x = 10 < x_{\text{max}} x=10<xmax,我们使用权重函数 f ( x ) = ( 10 100 ) 0.75 = 0.1778 f(x) = \left( \frac{10}{100} \right)^{0.75} = 0.1778 f(x)=(10010)0.75=0.1778。
对于"the" 和 "book"(共现 5000 次)
由于 x = 5000 > x max x = 5000 > x_{\text{max}} x=5000>xmax,此时权重函数 f ( x ) = 1 f(x) = 1 f(x)=1。
对于"library" 和 "book"(共现 5 次)
由于 x = 5 < x max x = 5 < x_{\text{max}} x=5<xmax,我们使用权重函数 f ( x ) = ( 5 100 ) 0.75 = 0.0891 f(x) = \left( \frac{5}{100} \right)^{0.75} = 0.0891 f(x)=(1005)0.75=0.0891。
权重函数 f ( x ) f(x) f(x) 的主要作用是通过对共现频次进行调整,平衡高频词对和低频词对的影响:
- 对于低频词对:通过赋予较大的权重,增强其对模型的贡献。
- 对于高频词对:通过限制权重,防止它们对损失函数产生过大的影响。
这样可以使模型更好地处理自然语言中的长尾效应,保证长尾词汇的语义能够得到良好的捕捉。
3. 训练GloVe模型
虽然很多人声称GloVe是一种无监督(unsupervised learing)的学习方式(因为它确实不需要人工标注label),但其实它还是有label的,这个label就是公式中的 log ( X i j ) \log(X_{ij}) log(Xij),而公式中的向量 w w w和 w ~ \tilde{w} w~就是要不断更新学习的参数,所以本质上它的训练方式跟监督学习的训练方法没什么不一样,都是基于梯度下降的。
具体地,论文里的实验采用了AdaGrad的梯度下降算法,对矩阵 X X X中的所有非零元素进行随机采样,学习曲率(learning rate)设为0.05,在vector size小于300的情况下迭代了50次,其他大小的vectors上迭代了100次,直至收敛。最终学习得到的是两个vector是 w w w和 w ~ \tilde{w} w~,因为 X X X是对称的(symmetric),所以从原理上讲 w w w和 w ~ \tilde{w} w~是也是对称的,他们唯一的区别是初始化的值不一样,而导致最终的值不一样。所以这两者其实是等价的,都可以当成最终的结果来使用。但是为了提高鲁棒性,我们最终会选择两者之和 w + w ~ w + \tilde{w} w+w~作为最终的vector(两者的初始化不同相当于加了不同的随机噪声,所以能提高鲁棒性)。在训练了400亿个token组成的语料后,得到的实验结果如下图所示: