词向量是现代自然语言处理(NLP)最基础、最核心的语义表征单元,也是知识表示、语义推理、文本分类、机器翻译等下游任务不可或缺的底层基础工具。计算机无法直接理解人类自然语言文字,必须先将离散文字转化为可参与矩阵运算的数值向量,而词向量正是解决这一转化问题的核心方案。
本文将从文字数字化的基础方案演进脉络入手,依次讲解字典序编码、独热编码的固有缺陷,引出分布式词嵌入(Word Embedding)的核心理论 —— 分布假设;再依托语言模型的发展路线,梳理传统统计 N-gram 语言模型、早期神经网络语言模型 NNLM 的建模思路与局限;最后聚焦工业界经典轻量化词向量工具 word2vec,拆解 CBoW、Skip-gram 两大模型结构、负采样加速训练原理,并解释词向量经典语义类比运算的内在可解释逻辑,完整梳理词向量技术从诞生到落地的完整演进链条。
1. 基本概念
在知识表示与推理章节,我们了解到需要把人类长期总结得到的知识转化为机器能够识别和认识的结构化表示。人类的文字对于计算机来说就是一个个鬼画符,计算机看不懂,也无法直接处理。
计算机可直接处理的是二进制数,二进制数字的组合可以进一步表示各类型数字,因此一种自然而然的思路是想办法将文字映射为数字来表示。
思考:有哪些将文字映射为数字的方式?
(1)计算机系统会将汉字转换为特殊的字符串编码,如:utf-8、GB2312 等 (2)摩尔斯电码(点线可用0/1表示,中文用4位数字表示一万汉字、字母和符号) (3)字典中对每一个字(词)都有一个先后顺序排序1.1. 字典序
我们先看最简单的文字数字化方案:字典序编码(标签编码)。以英文为例,单词 aback 在英文字典排序中排第 $1$ 位,它的字典序编号就是 $1$。我们可以给全部单词分配唯一字典序号,示例如下:
1
2
3
4
5
6
aback - 1
abandon - 2
abasement - 3
...
zythum - 171475
zyzzyva - 171476
把词转换成数字序号,看似完成了 “让计算机看懂文字” 的第一步,但在机器学习、深度学习场景下,仅使用字典序编码存在严重缺陷,无法直接送入模型训练:
- 字典序只代表各个文本之间的字典顺序,实际并无具体意义。很明显这种数字上的关系在很多场景下会带来大量的错误信息,因为每个字词本身在不同语境下都有着不同的意义:
- 如:
apple苹果:可以指一种水果,也可以指代苹果公司;
- 如:
- 单词属于纯离散分类特征,序号仅代表文字在字典里的先后顺序,单词之间不存在大小、差值、远近的数学关系,但模型会默认把序号当作连续数值解读,产生完全错误的语义理解:
- 如:
abasement(3)− abandon(2)= aback(1),模型会错误解读为 “abasement 减去 abandon 等于 aback”,默认二者存在可计算的数值差距; - 再比如 “zoo” 编号远大于 “abandon”,模型会误以为 “zoo” 的语义权重、特征强度远高于 “abandon”,强行给无关文字赋予虚假大小关系,最终导致模型收敛困难、预测结果失真。
- 如:
1.2. 独热编码(one-hot)
为了解决字典序所带来的问题,我们可以使用 独热(one-hot)编码。其原理为:构建一个由 $n$ 个 $0$ 组成的序列 ($n$ 是字典总数),其中将第 “字典序” 个 $0$ 换成 $1$ 作为该汉字对应的编码。
例如:对于《牛津词典》单词个数有 $V = 171476$ 个,则其中所有单词对应的 one-hot 编码有
1
2
3
4
aback - 0001: [0 0 0 0 0 0 0 0 0 0 0 0 ... 0 0 1]
abandon - 0002: [0 0 0 0 0 0 0 0 0 0 0 0 ... 0 1 0]
...
zyzzyva - 171476: [1 0 0 0 0 0 0 0 0 0 0 0 ... 0 0 0]
独热编码的优势有:
-
每个单词都会生成长度固定的编码向量,向量中有且仅有一位数值为 $1$ ,其余均为 $0$。不会像直接用数字序号编码那样,让模型误以为词汇间存在字典序大小、远近的数值关系,彻底规避离散类别数字化后产生的误导问题;
-
将独热编码的每一个维度看作离散特征,取值仅为 $0$ 或 $1$。当模型训练中将该特征视作数值型输入时,$0$ 代表特征未出现、$1$ 代表特征出现,天然可以直观表征该类别/词汇的存在概率,适配多数机器学习、深度学习模型的运算逻辑。
但注意到,独热编码的向量长度与词库/类别总量完全相等,一旦词表规模较大,会生成极度稀疏的向量:向量绝大部分维度都是 $0$,仅单一维度为有效数值 $1$。大量零元素会占用存储空间,同时增加矩阵运算、梯度计算的开销,极大浪费算力与存储资源,模型训练效率大幅下降。
1.3. 词向量(Word Embedding)
独热编码虽然规避了字典序带来的数值误导问题,但仍存在高维稀疏、不承载语义、算力消耗大三大痛点。为了让模型能够真正 “理解” 文本语义,我们引入更高效的文本表征方案:词向量(Word Embedding,也称词嵌入)。
我们理想中的词向量,需要同时满足两类核心特性,弥补字典序、独热编码的全部缺陷:
-
表征轻量化:不再是仅含 $0/1$ 的高维稀疏向量,而是低维、由连续浮点数构成的稠密向量,向量维度远小于词表总量 $V$,大幅降低存储与计算成本; 如:$[000000000000000 \cdots 0001]\in \mathbb{R}^{171476}$ ⇒ $[ 0.1187, 1.658, -0.258, …… 0.494 ]\in \mathbb{R}^{200}$
- 语义可建模:向量空间中自带语义关联,语义相近的词语在空间中距离更近;
![word-embedding-distance]()
-
运算有意义:向量具备近似线性特性,向量加减可对应语义特征的增删,经典类比示例如下:
1 2 3 4 5
「human」: - 「male」= 减去男性特征; +「female」= 加上女性特征; +「king」的皇室、统治者特征; ≈「queen」
想要训练出具备上述稠密、低维、线性语义特性的词向量,我们唯一可利用的原始资源,只有海量无标注自然语料。这就需要一套无监督学习框架,仅依靠文本上下文自动学习词汇的数值表征。
而这套学习框架的底层理论支撑,来自语言学领域的重要假设 —— 分布假设:
分布假设表明,若两个词语频繁出现在高度重合的上下文窗口中,二者的语义角色、词义天然具备相似性。例如:
需要区分『近义词』和『语义相近』的联系和区别,近义词一般都具备语义相似的特点(如橙子、橘子);语义相近的词不一定是近义词(如苹果、香蕉),但它们在该语境下具有高度相似的语义角色。正因如此,我们希望它们词向量空间中被映射到相近的位置,体现出上下文相似 → 向量相似的特点。
另一个直观例子,在句子结构:
**
**
**
其中,“牙”、“手机”、“题” 并不是严格意义上的『近义词』,但它们在该语境下具有高度相似的语义角色,也即『语义相近』。正因如此,它们在词向量空间中会被映射到相近的位置,体现出上下文相似 → 向量相似的特点。
2. 语言模型
仅依靠分布假设做理论支撑仍较为抽象,想要落地设计可训练的词向量模型,我们还需要一套具象化的建模思路,同时明确模型的输入、输出与待求解目标。
顺着分布假设的核心逻辑进一步推导,我们可以提炼出三类贯穿语言建模的基础问题,也正是后续各类模型的设计出发点:
- 词语语义由上下文决定,那么给定一段上下文,能否求解窗口中心位置词语出现的条件概率?概率最大的词汇,是否就是该语境下最通顺、最符合语义逻辑的候选词?
- 反向推导,若已知某一个中心词,能否推算出它前后窗口内各类上下文词汇的出现概率?
- 针对一整段连续词语构成的文本序列,我们是否能够量化整条句子在自然语言中的生成联合概率?概率最高的文本序列,是否代表最贴合母语表达习惯、现实中更常见的通顺语句?
三类问题层层递进,而整条文本序列的联合概率计算是所有上下文预测任务的底层根基:无论是根据上下文预测中心词,还是由中心词反推周边词汇,本质上都依赖词语间条件概率的联合运算。
因此,学界优先从第三个核心问题切入,提出通过构建 语言模型,依托大规模真实文本语料拟合各类词语条件概率。语言模型属于概率生成模型,输入是由有序词汇组成的文本序列,输出为该序列的生成概率,即序列内全部词汇共同出现的联合概率(joint probability)。
对于一段文本序列
\[S=\omega_1,\omega_2,...,\omega_T\]它的概率可以表示为
\[P(S) = P(\omega_1,\omega_2,...,\omega_T) = \prod_{t=1}^T p(\omega_t\vert \omega_1,\omega_2,...,\omega_{t-1})\]该式的核心逻辑是:第 $t$ 个单词 $w_t$ 的生成,依赖它之前全部单词 $w_1$ 到 $\omega_{t-1}$ 的共同影响。模型的求解难点,转化为如何估算连乘项中每一项给定前置词汇下的条件概率。
但这种完整条件概率的计算方式存在两处明显缺陷:
- 参数空间规模极大:
- 条件概率 $p(\omega_t\vert \omega_1,\omega_2,…,\omega_{t-1})$ 的参数量随序列长度呈指数级增长
- 假设词汇表大小为 $V$
- 前 $t−1$ 个词,每个位置都有 $V$ 种取值,共有 $V^{t−1}$ 种不同历史上下文
- 预测第 $t$ 个词有 $V$ 种可能
- 因此存储条件概率总共需要 $V^{t}$ 个独立参数
- 数据稀疏问题严重:
- 长序列词汇共现组合在语料中极少甚至完全不存在,对应条件概率直接为 0
- 序列越长该问题越突出
为了解决这个问题,人们进一步提出 N-gram 模型。
2.1. 统计语言模型(N-gram)
N-gram 模型的核心是引入马尔科夫假设(Markov Assumption):一个词的出现仅与它之前的有限个词有关,则有:
\[p(\omega_t\vert \omega_1,\omega_2,...,\omega_{t-1}) = p(\omega_t\vert \omega_{t-N+1},...,\omega_{t-1})\]一般取 $N=2$ 或者 $N=3$,分别对应 Bi-gram 和 Tri-gram 模型,前者认为每个词只与前面一个词有关,后者认为与前两个词有关。比如一个句子,I love deep learning 分别分解为:
1
2
Bi-gram : {I, love}, {love, deep}, {deep, learning}
Tri-gram : {I, love, deep}, {love, deep, learning}
2.2. 神经网络语言模型(NNLM)
在 N-gram 的基础上,Bengio 在 2003 年提出神经网络语言模型(Neural Network based Language Model, NNLM),该工作开创性地实现了词向量分布式表征的建模思路,虽未正式使用 “word embedding” 这一名称,但首次完整提出词嵌入的核心构想。
NNLM 是结构简洁的前馈神经网络,整体分为四层:输入层、嵌入投影层、隐藏层与输出层。模型输入为长度固定为 $n$ 的由独热编码构成的上下文词序列,输出词典中每个候选词作为下一词的预测概率;其核心任务是学习一个映射函数,完成从独热编码词序列到下一词条件概率分布的转换,模型结构如下图所示:
下面详细分析 NNLM 模型的前向传播过程:
-
嵌入投影层(线性查表映射)
-
模型先对输入的 $n−1$ 个独热编码上下文词做线性投影,借助共享权重矩阵 $C\in \mathbb{R}^{v\times m}$,映射为 $n−1$ 个,将每个独热向量转换为低维稠密的分布式词向量(distributed vector)。其中,$v$ 代表词典总规模,$m$ 为预先设定的词向量维度(超参数)。
-
矩阵 $C$ 内部存储的正是我们最终需要学习得到的词向量。举个直观例子:假设词典大小 $v=6$,词向量维度 $m=3$,输入 $2$ 个独热编码词向量,那么单层的神经网络前向传播就等效于查表操作 —— 提取独热编码中值为 $1$ 的位置所对应的 $C$ 矩阵行向量,作为该词的稠密分布特征,如下图所示:
- 由此可见,训练语言模型的过程,同时也是迭代优化权重矩阵 $C$ 和学习词向量表征的过程;词向量并非预定义常量,而是和网络其他参数一同参与训练更新。
-
-
隐藏层与输出层概率预测
- 将查表得到的 $n−1$ 个词向量拼接为一维长向量,送入后续前馈网络:先经过以 $\tanh$ 为激活函数的隐藏层,隐藏层维度为 $h=(n-1)\cdot m$;再接入维度等同于词典大小 $v$ 的 $\text{softmax}$ 输出(分类)层,最终输出目标此词 $w_t$ 对应的归一化条件概率。
- 整套网络将拼接后的上下文词向量映射为长度 $v$ 的概率分布向量,以此预估词典内所有词汇在给定上下文下出现的可能性。
模型训练采用带正则项的交叉熵损失函数,通过最小化全局损失更新全部网络参数:
\[L(\theta) = -\frac{1}{T}\sum_t \log f(\omega_{t-n+1},...,\omega_{t-1})+R(\theta)\]在每次用 SGD 学习更新模型的参数时,并不是所有的权重参数都会进行调整,只有当前 context 包含词的词向量才会被更新(因为映射层的输出只会得到这些词的输出,并参与接下来的运算)。真正的计算瓶颈主要是在 softmax 层的归一化函数上(需要对词典中所有的 $v$ 个词汇计算一遍条件概率)。
NNLM 解决了语言模型中的以下两个问题:
- 提供了高效求解条件概率 $p(\omega_t \vert \text{context})$ 的建模方案(也即神经网络拟合),缓解传统 N-gram 的数据稀疏问题;
-
给出了词的稠密连续分布式表征,完善向量空间模型(Vector Space Model, VSM)的词表达体系。
补充背景:稠密词向量分布式表征的思想早在信息检索领域已有应用,对应的理论框架即为向量空间模型 VSM。VSM 建立在两大基础假设之上:
- 词袋假设:文档核心主题由词频决定,与词汇顺序无关;
- 分布假设:和前文所述一致,上下文语境重合的词汇,语义天然相近。
NNLM模型仍然存在一系列问题:
- 仅支持固定长度上下文:底层为全连接前馈网络,输入窗口长度 $n$ 固定,无法灵活处理任意长度文本序列;
- 训练成本极高、收敛缓慢:模型整体参数量庞大,即便在百万级语料、40 核 CPU 集群环境下,完整训练一轮仍需数周才能得到可用效果;面对当下千万、亿级规模的海量真实语料,纯 NNLM 几乎不具备工程落地可行性。
针对第一个(定长输入)问题,Mikolov 在 2010 年提出 RNNLM 模型:用循环神经网络 RNN 替换 NNLM 中的全连接隐藏层。改进后优势十分突出:模型参数量更少、训练速度显著提升、能够接收无固定长度限制的文本输入,且可利用全部历史上下文信息建模。同时 RNN 架构具备极强拓展性,后续衍生出 LSTM、BiLSTM、GRU 等变体,能够针对时序文本建模做更精细化的优化。
3. 词向量模型(word2vec)
针对 NNLM 的训练成本极高的问题,Mikolov 注意到,原始的 NNLM 模型的训练其实可以拆分成两个步骤:
- 用一个简单模型训练出连续且稠密的词向量;
- 基于词向量训练一个 N-gram 神经网络预测模型。
而 NNLM 模型的 计算瓶颈主要是在第二步。但事实上,**我们根本不关心第二步预测任务,我们只是想得到第一步连续稠密的词向量!**因此可以考虑对第二步里的神经网络模型进行简化,甚至不关心网络实际输出的功能。而第二步基于训练数据建模的过程,我们给它一个名字叫 “Fake Task”,意味着建模并不是我们最终的目的。
上面提到的这种方法实际上会在无监督特征学习(unsupervised feature learning)中见到,最常见的就是自编码器(auto-encoder):通过在隐层将输入进行编码压缩,继而在输出层将数据解码恢复初始状态,训练完成后,我们会将输出层 “砍掉”,仅保留隐层。
2013年,Mikolov 一口气发表了两篇论文,并开源了一款计算词向量的模型工具 —— word2vec。词向量模型要做的事情是:学习一个从高维稀疏离散向量到低维稠密连续向量的映射。该映射的特点是,语义相近的词向量的距离比较小,词向量之间的加减法有实际物理意义。
word2vec 是一种特殊的语言模型,其具体包含以下两类模型:
-
『Skip-gram 模型』:输入一个词语,预测它周围的上下文
-
『CBoW 模型(Continues Bag-of-Words Model)』:输入上下文,预测词语本身
3.1. CBoW
CBoW(Continuous Bag-of-Words,连续词袋模型)是 word2vec 的经典模型之一,其核心思路是:用中心词的上下文词汇预测中心词本身,在预测过程中训练得到高质量的词向量,整体结构与 NNLM(神经网络语言模型)相似但更简洁高效。
如图所示,CBoW 模型结构如下:
- 输入层:图中 $x_{i-c},\cdots,x_{i+c}\in\mathbb{R}^{V\times 1}$ 表示中心词 $x_i$ 的前后 $c$ 个上下文的独热编码向量;
- 嵌入层:将独热编码向量输入词向量矩阵 $W\in\mathbb{R}^{D\times V}$ 完成 “查表” 映射,其中 $V$ 为词表的大小,$D$ 为自定义的词向量的维度,最终得到上下文词的低维词向量; \(x^\prime_{i-c} = W x_{i-c} \;\in \mathbb{R}^{D\times 1}\)
- 求和层:对所有上下文词的词向量直接累加求和然后取平均,得到融合上下文信息的特征向量 $h$,实际上可以结合上一步嵌入层通过先求和后矩阵乘法的方式计算; \(h = \frac{1}{2C}\sum_{i=-C,i\neq 0}^{C} x_i^\prime = \frac{1}{2C}W\cdot \sum_{i=-C,i\neq 0}^{C} x_i \;\in \mathbb{R}^{D\times 1}\)
- 输出层:通过 $W^\prime \in \mathbb{R}^{V\times D}$ 的权重矩阵,将特征向量 $h$ 映射为词表维度的输出 $p$,再经过 softmax 得到归一化的预测独热编码向量。 \(\begin{aligned} p &=W^\prime h =[p_1, p_2, \cdots, p_V]^\top \in \mathbb{R}^{V\times 1}\\ p^\prime &= \text{softmax}(p) = \frac{\exp(p_i)}{\sum_{k=1}^V \exp(p_k)}\in \mathbb{R}^{V\times 1} \end{aligned}\)
反向传播时,采用交叉熵损失函数,比较预测词的归一化概率向量 $p^\prime$ 与正确的独热编码监督标签 $T$ 之间的误差。
\[\mathcal{L} = -\sum_{j=1}^V T_j\log p^\prime_j\quad \frac{\partial \mathcal{L}}{\partial W^\prime} = (p^\prime - T)h^\top\]注意,当词典规模庞大时,模型输出层 计算量极大,体现在:
- 前向传播 softmax 归一化必须使用全部单词的得分求和;
- 反向梯度更新会修改输出矩阵 $W^\prime$ 的全部 $V$ 行权重。
后续通过负采样技巧进行优化。
训练完毕后,模型的输入权重矩阵 $W$ 的每一列(与矩阵行列定义维度有关)就是每个词的低维稠密词向量。
绝大多数教材 / 论文将输入嵌入矩阵定义为 $W\in\mathbb{R}^{V\times D}$,对应词向量为矩阵的行。前面分析时仅为了与贴图保持一致,与传统定义方式相反。
CBoW 与 NNLM 的核心区别在于:
- 完全移除 NNLM 中的隐层(tanh 激活函数),减少计算量,提升训练效率;
- 嵌入层结果直接求和(NNLM 采用向量拼接),弱化上下文词的顺序影响,聚焦整体语义;
- 同时纳入上文+下文词汇,真正实现双向语境建模(NNLM 仅能使用目标词前 $n-1$ 个上文,为单向语境)。
-
3.2. Skip-gram
跳字模型(Skip-gram)是 word2vec 的另一核心模型,其核心思路是用单个中心词预测其上下文所有词汇,与 CBoW 形成 “反向预测” 关系,在小语料、低频词上表现更优。
Skip-gram 模型结构与 CBoW 高度同源,包含输入层、嵌入层(伪隐层)、输出层三层结构:
经过神经网络隐层的计算,输入词会从一个 $1\times V$ 的 独热编码向量变成 $1\times N$ 的向量,再被输入到输出层。输出层经过 $1\times N$ 权重矩阵,将词向量重新映射回 $V$ 维,然后经过 softmax 编码得到归一化概率向量。
注意到,虽然 Skip-gram 结构图画成「单个中心词输入、多个上下文词输出」,但这只是宏观示意。假设整个词序列为 $w_1, w_2, w_3, w_4, w_5,\cdots$,选取中心词为 $w_c=w_2$,假设单向窗口为 $C$,即希望同时预测前后 $2C$ 个上下文词,那么会拆出 $2C$ 条独立的样本:
\[(w_c, w_{o1}), (w_c, w_{o2}), \cdots, (w_c, w_{oC})\]真实训练时每次只输入一组词对 $(w_c, w_{oi})$,一次只预测一个上下文词,并同样采取交叉熵损失函数进行反向传播训练。
Skip-gram 模型同样存在因词典规模引起的计算量爆炸问题。
3.3. 负采样训练
前面已经提到,不论是 CBoW 模型还是 Skip-gram 模型,在模型输出层存在随词典规模剧增引起的计算量爆炸的问题。为了解决该问题,word2vec 引入一种负采样(Negative Sampling) 优化策略来提高训练效率,缓解在大规模数据集上非常低效的计算瓶颈。其核心操作为:
- 设计正样本:每次训练时,对于给定的目标词独热编码 $w_t$ 和上下文词独热编码 $w_c$ ,计算二者稠密词向量:
- 选取负样本:从词汇表中随机选择 $K$ 个不相关的词作为负样本,可通过随机选取输出矩阵 $W^\prime$ 的 $K$ 行(或列)转置得到(选取词典维度 $V$ 对应的维度)。
- 调整损失函数:负采样采用了一个简化的 log-sigmoid 损失函数,它对于正样本和负样本分别进行处理。负采样放弃全局 softmax,改用二分类近似,将任务转化为「区分真实上下文词(正例)与随机采样无关词(负例)」,目标最大化正样本 sigmoid 得分、最小化负样本 sigmoid 得分
对于正样本 $(w_t, w_c)$ 和 $K$ 个负样本 $(w_t, w_{\text{neg}_i}), i=1,2,\cdots, K$,负采样损失函数如下:
\[\mathcal{L} = -\log \sigma(v_{w_t}^\top v_{w_c})-\sum_{i=1}^K\log \sigma(-v_{w_t}^\top v_{w_{\text{neg}_i}})\]其中:
- $\sigma$ 是 sigmoid 函数;
- $v_{w_t}, v_{w_c}$ 分别是目标词和上下文词的词向量;
- $v_{w_{\text{neg}_i}}$ 是第 $i$ 个负样本词的词向量;
- $K$ 是负样本数量,通常取值 $K=5\sim 20$;
- 第一项是正样本损失,它的目标是最大化目标词 $w_t$ 和上下文词 $w_c$ 的内积,从而提高它们的相关性;
- 第二项是是负样本的损失,它的目标是最小化目标词 $w_t$ 和负样本词 $w_{\text{neg}_i}$ 之间的内积,从而降低它们的相关性。
在实际的负样本采样中,假设每个单词 $w$ 出现的词频为 $f(w)$,为了避免高频出现的词(如 “one”、“好” 等)过多被选作负样本,该词被选中作为负样本的频率设计为:
\[P(w_i) = \frac{f(w)^{3/4}}{\sum_{w^\prime} f(w^\prime)^{3/4}}\]常数 $3/4$ 保证幂函数是下凸曲线,- 高频词幂运算后数值被压低,降低采样权重;低频词相比原始频次,权重被相对抬升,更容易被抽成负样本;同时词频相对顺序保持不变,不会颠倒高低频关系。
注意,实际操作中还会把高频虚词(如 “a”、“the” 等)过滤掉,这里不再赘述。
在训练过程中,模型前后两个矩阵权重更新的区别在于:
- 输入矩阵 $W$:只更新上下文词对应的列(对于Skip-gram来说就只中心词那一列,对于CBoW来说有多列);
- 输出矩阵 $W^\prime$:只更新正样本 + $K$ 个负样本对应的行,其余单词完全不计算梯度,规避了庞大的计算。
举例:窗口 c=1,句子
I love cat样本:中心词
love,上下文I、cat
- CBOW 样本:上下文是
I、cat,预测 lov`e
- W 更新
I、cat两列;- W′ 更新正样本
love+ K 个负样本行。- Skip-Gram 会拆两条独立样本:
- 样本 1:上下文
love,预测I
- W 只更新
love一列;- W′ 更新正样本
I+ K 个负样本行。- 样本 2:上下文
love,预测cat
- W 只更新
love一列;- W′ 更新正样本
cat+ K 个负样本行。
负采样的优点
-
提高计算效率: 负采样的核心优势是显著降低了每次训练时的计算量。与传统的 softmax 需要计算词汇表中每个词的概率不同,负采样只需要计算目标词和负样本的概率。因此,训练过程中只涉及 $K+1$ 次计算,显著加速了训练过程。
-
有效处理大规模数据集: 对于大规模的词汇表,负采样使得在每次训练中只需要考虑小规模的负样本,而不需要计算所有词汇的概率,这对于大规模语料库来说尤为重要。
-
优化模型性能: 负采样不仅能够加速训练过程,还能在某些情况下提高模型的性能。通过引入负样本,模型学会了更加准确地区分上下文词和非上下文词,从而得到更精确的词向量。
-
内存占用少: 负采样的实现不需要将整个词汇表的词向量都加载到内存中,而是只加载目标词和负样本的词向量,大大节省了内存占用。
-
稠密词向量的不同语义维度会自动趋向近似正交、解耦: 比如:一维编码「性别」,一维编码「皇室身份」,一维编码「年龄」; 维度之间几乎互不干扰,修改一个特征不会污染其他特征。
负采样的缺点
-
需要选择负样本: 负采样的性能依赖于负样本的选择。尽管随机选择负样本可以加速训练,但选择的负样本质量会影响模型效果。若负样本选择不当,可能会导致模型无法有效学习。
-
并不能捕捉所有语义信息: 负采样只关心目标词和负样本之间的区别,忽略了对整个词汇表的细粒度学习,可能会错过某些细节的语义信息。
-
损失函数的简化: 负采样通过简化的损失函数来减少计算量,但这种简化也导致了模型在某些复杂任务中的表现不如传统的 softmax。
3.4. 语义加减的可解释性分析
经由前文整套建模逻辑推导,我们已经能借助词向量模型得到低维连续稠密的词语表征,但尚未解释这类向量为何支持具备语义意义的线性加减运算。实际上,word2vec 训练产出的词向量天然满足该特性,背后由三层核心原因共同支撑:
- word2vec 的优化目标仅采用线性内积衡量词语相似度,在训练过程中,输入侧词向量不会经过任何非线性变换,向量空间整体保持线性结构;
- 举例:模型计算
国王与男人的关联程度、女王与女人的关联程度时,只直接做向量点积,不存在 tanh、ReLU 这类非线性函数扭曲向量数值。向量之间的加减、差值关系不会被破坏,不会出现线性关系失真的情况。
- 举例:模型计算
- 海量文本中大量平行语义类比样本持续参与训练,使得同一类语义差异最终收敛为空间中统一的平移向量;
- 举例:语料中大量存在
国王 - 男人 = 女王 - 女人、王子 - 男孩 = 公主 - 女孩这类平行语义模式,反复训练后,“皇室女性化” 这一语义变化会固定成同一个向量差值。无论输入哪一组皇室词汇,执行相同的加减操作都能得到符合语义的结果。
- 举例:语料中大量存在
- 各语义维度趋于正交、相互解耦,是线性训练目标与充足语义样本共同作用带来的衍生结果。
- 举例:词向量中会自动拆分出独立维度,分别代表「性别」「皇室身份」「年龄」等语义特征,各维度近似互不干扰。修改 “性别” 维度的数值,几乎不会改变 “皇室身份” 维度的信息;做
国王 - 男人 + 女人运算时,仅替换性别特征,统治者、皇室相关特征完整保留,不会出现语义混杂错乱。
- 举例:词向量中会自动拆分出独立维度,分别代表「性别」「皇室身份」「年龄」等语义特征,各维度近似互不干扰。修改 “性别” 维度的数值,几乎不会改变 “皇室身份” 维度的信息;做
3.5. 小结
通过前述分析可以看出:
- CBoW:一次输入全部 $C$ 个上下文,单次前向只预测 1 个中心词,一对多输入、单一输出;
- Skip-gram:对上下文进行样本拆分,训练是一对一逐样本计算,单次只输入 1 个中心词,单次只预测 1 个上下文词。
两者本质上都是学习一个从高维稀疏离散表示到低维稠密连续向量的映射。这种词向量映射具有两个重要特性:
- 语义相近的词,向量距离更小;
- 词向量之间的加减运算具有可解释的语义意义。
4. 全局向量模型(GloVe)
在 2013 年 Tomas Mikolov 等人提出 word2vec 之后,2014年,斯坦福大学的 Jeffrey Pennington, Richard Socher, Christopher D. Manning 三人提出了全局向量模型 (https://nlp.stanford.edu/projects/glove/ )。
4.1. 基本概念
在传统上,实现 word embedding(词嵌入)主要有两种方法:
- 矩阵分解方法(Matrix Factorization Methods)
- 基于浅窗口的方法(Shallow Window-Based Methods)
矩阵分解方法基于 全局词 - 词共现统计矩阵,对大规模全局共现计数矩阵做奇异值分解(SVD)降维得到词向量。典型代表为 LSA 潜在语义分析,其优劣为:
- 优势:
- 直接利用整个语料库全部文本的 全局共现信息,天然建模词语在全局语境下的共现关联;数学理论完备,可解释性强。
- 缺陷:
- 计算成本极高:共现矩阵维度等于词汇量,百万级词汇下矩阵极度稀疏,SVD 分解算力开销巨大,难以适配大语料;
- 忽略局部窗口语义:仅统计全局共现频次,不区分词语在局部上下文窗口内的邻近关系,无法捕捉局部上下文细微语义;
- 向量表达效果差,生成的词向量类比、语义推理能力弱。
浅窗口类方法通过滑动固定大小局部窗口遍历文本,仅使用 局部窗口内上下文 预测中心词(CBOW)或用中心词预测上下文(Skip-gram),通过单层浅层神经网络梯度下降优化词向量。典型代表为前述 word2vec 方法,其优劣为:
- 优势:
- 训练高效、易工程落地:无超大稀疏矩阵分解,负采样 / 分层霍夫曼树大幅降低计算量,适配海量文本;
- 精细捕捉局部上下文语义:聚焦窗口内邻近词语的搭配关系,词语类比、局部语义匹配效果显著优于矩阵分解法。
- 缺陷:
- 完全丢失全局共现统计信息。模型只学习滑动窗口内局部配对,不会利用整个语料库中词语全局共现频次;无法区分 “低频偶然共现” 和 “全局高频稳定共现”,全局语义建模存在天然盲区。
二者分别各有优缺点,而 GloVe 结合了两者之间的优点。
4.2. 建模过程
GloVe 全称 Global Vectors for Word Representation,核心设计目标就是统一整合矩阵分解的全局共现统计、word2vec 类浅窗口模型的局部上下文优势,弥补两类传统方法各自的短板。
设语料词汇表大小为 $V$,定义 词-词共现矩阵 $X\in\mathbb{R}^{V\times V}$,且有:
- $X_{ij}$:词 $j$ 出现在词 $i$ 的上下文窗口内的总次数;
- $X_i = \sum_{k=1}^V X_{ik}$:词 $i$ 所有上下文共现总次数;
- $P_{ij} = \frac{X_{ij}}{X_i}$:给定中心词 $i$,上下文出现词 $j$ 的条件概率。
GloVe 核心洞察是关注 共现概率比值 $\frac{P_{ik}}{P_{jk}}$ 的大小。以
\[i=\text{ice}, j=\text{steam}, k=\text{solid}\]为例,从语义上来看,冰(ice)相较于蒸汽(steam)肯定与固体(solid)更相关,共现概率更高,所以肯定有
\[\frac{P_{ik}}{P_{jk}} \gg 1\]思考:若 $k=\text{gas}$ 或者 $k=\text{water}$ ,共现概率比值如何变化?
- $k=\text{gas}$ 时比值远小于1;
- $k=\text{water}$ 时比值接近1。
共现概率比可以很好的从不相关词汇( water 或 fashion)中区分相关的词汇(solid 和 gas)。也可以很好的区分两个相关词汇。
我们希望词向量能复现共现概率比,而不是它们的共现概率本身。设词 $i$ 向量为 $w_i\in\mathbb{R}^d$,上下文词向量 $\tilde{w}_k\in\mathbb{R}^d$。则我们希望构建一个词向量模型 $F(w_i,w_j,\tilde{w}_k)$ 去拟合共现概率比,即:
\[F(w_i,w_j,\tilde{w}_k) = \frac{P_{ik}}{P_{jk}}\]下面进入原作者的数学直觉操作,最终目标是为了得到一个便于优化的损失函数。
第一个数学直觉:语义差值对应向量差值
- 语义上:
i - j的语义偏移,等价于向量 ${w}i - {w}_j$(比如 $w{\text{king}}-w_{\text{man}} \approx w_{\text{queen}}-w_{\text{woman}}$); - 线性空间假设:词嵌入处于线性向量空间,词语间的语义差可以直接用向量减法表达;
- 分离变量:把「区分
i、j的语义差」$({w}_i-{w}_j)$ 和「参考词k的上下文向量」$\tilde_k$ 拆分成两个独立输入,方便后续计算二者关联。
因此有:
\[F(w_i-w_j,\tilde{w}_k) = \frac{P_{ik}}{P_{jk}}\]第二个数学直觉:内积天然衡量向量相似度,输出标量匹配概率比
- 我们最终要拟合的 $\frac{P_{ik}}{P_{jk}}$ 是单个实数标量;
- 需要找一个运算把两个向量映射为一个标量,向量内积 $a^\top b$ 简直完美;
- 语义层面,内积大小代表向量相似度,恰好能对应 “两个词关联强弱” 的共现概率逻辑。
因此有
\[F\left((w_i-w_j)^\top\tilde{w}_k\right) = \frac{P_{ik}}{P_{jk}}\]展开左侧内积:
\[({w}_i - {w}_j)^\top \tilde_k = {w}_i^\top \tilde_k - {w}_j^\top \tilde_k\]注意到,等式左侧对应语义比值 $\frac{P_{ik}}{P_{jk}}$ 是分式结构,为了凑出 $F(a-b) = \frac{F(a)}{F(b)}$ 成立,只有指数函数 $F(x)=\exp(x)$ 满足要求:
\[\exp(a-b) = \frac{\exp(a)}{\exp(b)}\]因此有:
\[\frac{\exp({w}_i^\top \tilde_k)}{\exp({w}_j^\top \tilde_k)} = \frac{P_{ik}}{P_{jk}}\]交叉相乘变形,整理可得:
\[\frac{\exp({w}_i^\top \tilde_k)}{P_{ik}} = \frac{\exp({w}_j^\top \tilde_k)}{P_{jk}}\]第三个数学直觉:下标遍历等式不变
- 等式左边只和 $i,k$ 有关,等式右边只和 $j,k$ 有关,且对词汇表里随便选哪一个 $j$,左右两边永远相等。
- 唯一能满足「右边对任意 $j$ 取值都不变」的情况,就是:右边整个分式本身是一个只依赖 $k$、而和 $j$ 完全无关的常数。
- 设这个仅依赖 $k$ 的常数为 $C_k$,对于左边有:
移项,两边取对数后得到:
\[\begin{aligned} {w}_i^\top \tilde_k &= \log(P_{ik}) + \log(C_k)\\ &=\log(X_{ik}) - \log(X_i) + \log(C_k) \end{aligned}\]在模型训练时,$\log(C_k)$ 直接用上下文偏置 $b_k$ 拟合,$-\log(X_i)$ 用中心词偏置 $b_i$ 拟合,最终等式简化为以下对数双线性模型:
\[{w}_i^\top \tilde_k + b_i + b_k = \log(X_{ik})\]至此我们就可以设计均方差损失函数来最小化等式左右的差(将 $k$ 替换为 $j$):
\[\mathcal{L} = \sum_{i,j=1}^V \left({w}_i^\top \tilde_j + b_i + b_j - \log(X_{ij})\right)^2\]注意到,上述损失函数还存在一些局限:
- 不论共现词频率如何,都均等考虑。但对于不常见或偶尔出现的组合,很可能都是噪声,也对其拟合显然不利于模型的鲁棒性;我们希望权重能够随着共现词频率增加而递增,当频率超过一定阈值时保持不变,以保证频繁出现的组合不会给过多的权重;
- 共现词实际上是较为稀疏的,大多数情况下 $X_{ij}=0$,这会引起 $\log$ 计算无意义,因此需要给取对数计算增加额外的冗余;
因此对损失函数改进如下:
$$ \mathcal{L} = \sum_{i,j=1}^V f(X_{ij})\left({w}_i^\top \tilde_j + b_i + b_j - \log(X_{ij}+1)\right)^2 $$其中,权重函数为:
\[\begin{aligned} f(X_{ij})=\left\{ \begin{matrix} (x/x_{max})^\alpha\quad x<x_{max}\\ x_{max}\quad \text{otherwise} \end{matrix} \right. \end{aligned}\]函数图像如下:
论文实测 $\alpha = 3/4$ 效果好于 $\alpha = 1$,选用 $x_{\max}=100$。
GloVe 模型之所以能统一整合矩阵分解的全局共现统计、word2vec 类浅窗口模型的局部上下文优势,在于:
- 借鉴矩阵分解思想:显式引入全局词 - 词共现计数矩阵,以共现频次对数比值作为模型核心监督信号,完整利用整个语料库的全局词语统计关系,解决 word2vec 丢失全局信息的问题;
- 借鉴浅窗口 word2vec 的局部建模思路:模型基于滑动窗口产生的词对构建损失,保留局部上下文邻近语义的建模能力,规避传统 SVD 忽略局部搭配的缺陷;
- 通过对数双线性模型设计损失函数,将全局共现统计与局部窗口预测统一到同一个优化目标中,不再割裂全局与局部信息。
论文实验结果佐证了该融合思路的有效性:在词语相似度、语义类比、文本分类等标准评测任务上,GloVe 词向量稳定优于仅使用局部窗口信息的 word2vec,同时大幅超越传统矩阵分解类 LSA 等词嵌入方法,实现了两类经典范式优势的结合。
4.3. 模型结构
根据前述损失函数定义,我们可以敏锐地注意到,GloVe 模型本质是一个双线性回归模型,用神经网络来建模的话,可以是一个浅层双线性回归网络。只有两组可学习嵌入向量 + 偏置,没有激活函数、没有 softmax / 负采样、没有分类输出层,任务是拟合全局共现对数(回归任务)。
训练样本是一对中心词 $i$、上下文词 $j$ 的独热编码;分别查表两套不共享的嵌入矩阵 $W, \tilde{W}$,得到稠密向量 $w_i, \tilde{w}j$,再做内积回归拟合 $\log X{ij}$。
思考:为何不共用隐层权重矩阵?
</summary>
因为共现矩阵 $X$ 是非对称矩阵,一套权重无法拟合不对称关系。定义:
- $X_{ij}$:$j$ 出现在 $i$ 的窗口内的次数
- $X_{ji}$:$i$ 出现在 $j$ 的窗口内的次数
绝大多数场景下 $X_{ij}\neq X_{ji}$,共现关系是单向、不对称的。
假设只共用一套权重 $W$,那么模型预测项变为:
$$y^{ij}=w_i^\top w_j+b_i+b_j$$
交换 $i,j$ 得到:
$$y^{ji}=w_j^\top w_i+b_j+b_i$$
由于内积交换律 $w_i^\top w_j=w_j^\top w_i$,必然推出 $y^{ij}=y^{ji}$。但真实标签 $\log X_{ij}\neq \log X_{ji}$,出现矛盾。
</details>
训练收敛后,最终词向量为两个权重矩阵逐元素加和得到,论文也尝试单独使用两个权重矩阵作为词向量矩阵,但效果不如加和后好。
5. 总结
word2vec 通过嵌入一个线性的投影矩阵(projection matrix),将原始的独热编码向量映射为一个稠密的连续向量,并通过一个语言模型的任务去学习这个向量的权重,而这个过程可以看作是无监督或称为自监督的,其词向量的训练结果与语料库是紧密相关的,因此通常不同的应用场景需要用该场景下的语料库去训练词向量才能在下游任务中获得最好的效果。这一思想后来被广泛应用于包括 word2vec 在内的各种 NLP 模型中,从此之后不单单是词向量,我们也有了句向量、文档向量,从 Word Embedding 走向了World Embedding 的新时代。
word2vec 非常经典,但也有其明显的局限性,其主要在以下几个方面:
-
在模型训练的过程中仅仅考虑context中的局部语料,没有考虑到全局信息;对于英文语料,对于什么是词,怎样分词并不是问题(单个词就是独立的个体)。而对于中文而言,我们在训练词向量之前首先要解决分词的问题,而分词的效果在很多情况下将会严重影响词向量的质量(如分词粒度等)。因此,从某些方面来说 word2vec 对中文不是那么的友好;
-
在 2018 年以前,对于 word2vec 及其一系列其他的词向量模型都有一个相同的特点:其embedding矩阵在训练完成后便已经是固定了的,这样我们可以轻易从网上获取到大量预训练好的词向量并快速应用到我们自己任务中。但从另一个角度来说,对于同一个词,在任意一个句子,任意一个环境下的词向量都是固定的,这对于一些歧义词来说是存在较大问题的,这也是限制类似 word2vec、Glove 等词向量工具性能的一个很重要的问题。
在模型训练的过程中仅仅考虑context中的局部语料,没有考虑到全局信息;对于英文语料,对于什么是词,怎样分词并不是问题(单个词就是独立的个体)。而对于中文而言,我们在训练词向量之前首先要解决分词的问题,而分词的效果在很多情况下将会严重影响词向量的质量(如分词粒度等)。因此,从某些方面来说 word2vec 对中文不是那么的友好;
在 2018 年以前,对于 word2vec 及其一系列其他的词向量模型都有一个相同的特点:其embedding矩阵在训练完成后便已经是固定了的,这样我们可以轻易从网上获取到大量预训练好的词向量并快速应用到我们自己任务中。但从另一个角度来说,对于同一个词,在任意一个句子,任意一个环境下的词向量都是固定的,这对于一些歧义词来说是存在较大问题的,这也是限制类似 word2vec、Glove 等词向量工具性能的一个很重要的问题。






