静态词向量(Static Word Embeddings)预训练模型是自然语言处理(NLP)深度学习时代的早期基石。

静态:一个词在词表中对应一个固定不变的稠密向量,无论这个词出现在什么上下文中,它的向量表示都是完全相同的。

在深度学习爆发前,NLP 领域长久以来被“语义鸿沟”和“维度灾难”两座大山压制。

早期离散表示

One-Hot 独热编码

这是最简单、最基础的词表示方法。假设我们的词表大小为 V|V| (比如有 10 万个词),那么每个词都会被表示成一个长度为 10 万的向量。在这个向量中,只有该词对应的索引位置是 1,其他所有位置都是 0。

缺点:极其稀疏、向量正交(任意两词内积为 0,毫无语义关联)。

词袋模型 (BoW) & TF-IDF

词袋模型:One-Hot 是表示单个词的,如果要表示一整句话或一篇文章怎么办?最简单的做法就是把所有词的 One-Hot 向量加起来,这就是词袋模型。

BOW:把一段文本看作是一个装满词的“袋子”,完全无视词的顺序和语法,只关心每个词出现了多少次(词频)。

TF-IDF:由于 BoW 只是简单统计词频,会导致“的”、“是”、“在”这种没有实际意义的停用词(Stop words)占据极高的权重。TF-IDF 就是为了解决这个问题诞生的。

思想: 一个词的价值由两部分决定:

TF (Term Frequency): 这个词在这篇文档中出现的频率越高,越重要。

IDF (Inverse Document Frequency): 这个词在所有文档中出现的频率越低,它的区分度越高,越重要。(比如“原子能”比“的”具有高得多的信息量)。

缺点:丢失了所有语序信息。“猫吃老鼠”和“老鼠吃猫”在 BoW 模型中会得到完全相同的向量表示,这在复杂的语义理解任务中是灾难性的。

N-gram (N元语法模型)

为了解决 BoW 丢失语序的问题,N-gram 被提了出来。它不再以单个词为单位,而是以相邻的 N 个词为单位进行统计。

例子: “我 在 写 代码”

Bi-gram (N=2): ["我在", "在写", "写代码"]

Tri-gram (N=3): ["我在写", "在写代码"]

缺点:极度加剧了“维度灾难”和数据稀疏问题。如果词表是 10 万,那么 Bi-gram 的可能组合就是105×105=101010^5 \times 10^5 = 10^{10}(一百亿),这在早期的计算资源下是根本无法计算和存储的。

共现矩阵与 LSA

为了解决 One-Hot 无法捕获语义相似度的问题,学者们想到了一个绝妙的主意:统计一个词的上下文。

  • 思想: 构建一个巨大的 V×VV \times V 矩阵。矩阵的第 ii 行第 jj 列的值,代表词 ii 和词 jj 在同一个窗口内共同出现的次数。如果“猫”和“狗”经常和“宠物”、“吃”、“叫”共现,它们的行向量就会非常相似。

  • 降维 (SVD/LSA): 因为这个矩阵依然庞大且稀疏,数学家们使用奇异值分解(SVD)等矩阵分解技术,将高维稀疏矩阵降维成低维稠密矩阵(潜在语义分析 LSA)。

分布式词表示

分布式思想: 受到 Hinton 在 1986 年的启发,将词语的语义“分布”在一个低维、稠密的连续向量空间中。在这个空间里,语义相近的词距离更近。

V(King)V(Man)+V(Woman)V(Queen)V(\text{King}) - V(\text{Man}) + V(\text{Woman}) \approx V(\text{Queen})

我们来拆解一下这背后的空间逻辑:

  1. V(King)V(Man)V(\text{King}) - V(\text{Man}):在 NN 维的超空间里,把“国王”向量减去“男人”向量。这个减法操作,实际上是在数百个维度的组合中,抵消(剥离)掉了“男性”的语义特征,留下了一个纯粹代表“皇室统治者”的相对方向(或者说位移向量)。

  2. +V(Woman)+ V(\text{Woman}):接着,把“女人”的向量加到刚才那个纯粹的“皇室统治者”方向上,相当于给它注入了“女性”的语义特征

  3. 结果:经过这一通加减计算后,我们得到了一个新的 NN 维坐标点。当我们去词表中寻找离这个计算出来的新坐标点距离最近的那个词时,发现它恰好就是“Queen”。

有了将词语映射到连续空间的构想后,接下来的挑战是如何让计算机自动计算出这些高维向量。答案隐藏在大规模文本自身的分布规律中。 语义信息不再是字典里的一段解释,而是被转化为高维空间中的相对距离和方向。

自监督学习:模型不需要任何人工标注的标签,而是直接利用文本自带的上下文结构作为训练目标。

最经典的设定就是基础的“语言模型任务”:让机器阅读海量的句子,并不断尝试根据上下文预测缺失的词(例如给定前几个词,预测下一个词)。在这个反复计算误差并更新权重的过程中,模型为了提高预测的准确率,会被迫将词语之间的组合规律和语义关联压缩到连续的向量参数中。

语言模型

语言模型(LM)的核心目标是预测序列中下一个词的概率

P(wtwt1,wt2,...,wtn+1)P(w_t | w_{t-1}, w_{t-2}, ..., w_{t-n+1})
  • 传统 n-gram 模型:用统计方法估计概率,但受限于稀疏数据问题维度灾难

  • FF-NNLM 引入分布式词表示(词嵌入) + 神经网络,能捕捉词之间的相似性,提高泛化能力。

前馈神经网络语言模型(FF-NNLM)

该模型通过一个滑动窗口截取固定长度的局部上下文,首先利用一个共享的投影矩阵(实际上就是一张包含了语义信息的词向量表),将离散的词映射为低维稠密向量(即现代深度学习框架中常见的 Embedding 层),然后将这些向量拼接并送入全连接隐藏层,最终通过 Softmax 层预测下一个词的概率分布。

词嵌入

  • 每个历史词 wtiw_{t-i} 映射为一个稠密向量 e(wti)Rd\mathbf{e}(w_{t-i}) \in \mathbb{R}^d

  • 假设考虑前 n1n-1 个词作为上下文:

[wtn+1,wtn+2,...,wt1][w_{t-n+1}, w_{t-n+2}, ..., w_{t-1}]
  • 将它们的词向量拼接成一个长向量:

x=[e(wtn+1);e(wtn+2);...;e(wt1)]\mathbf{x} = [\mathbf{e}(w_{t-n+1}); \mathbf{e}(w_{t-n+2}); ...; \mathbf{e}(w_{t-1})]

注意:这里 FF-NNLM 是固定长度上下文,不像 RNN 那样可以处理任意长度。

然而,这种早期架构也存在明显的工程瓶颈。由于网络包含非线性的全连接隐藏层,且每次预测都需要在整个词表上计算 Softmax,导致其训练时间极其漫长,很难扩展到真正的大规模工业级语料上。

循环神经网络语言模型(RNNLM)

尽管 FF-NNLM 成功验证了词嵌入的有效性,但它存在一个根本的结构局限:它依赖于马尔可夫假设,只能通过一个固定大小的窗口观察前n1n-1 个词。然而在真实的自然语言中,词与词之间的依赖关系往往跨度很大(长程依赖)。为了解决这个问题,循环神经网络语言模型(RNNLM)应运而生。

RNNLM 的核心创新在于打破了固定上下文窗口的限制,引入了循环隐藏状态(Hidden State)机制。在模型处理序列的每一个时间步,网络隐藏层不仅接收当前词的向量输入,还会接收来自上一个时间步的隐藏状态。

从机制上看,这种设计赋予了模型一种“序列记忆”:当前时刻的隐藏状态,理论上压缩并包含了从句子开头到当前位置所有的历史上下文信息。这使得 RNNLM 能够比 FF-NNLM 更好地捕捉句子中长距离的语法和语义联系。

优点:

  1. 可以处理任意长度的上下文,不像 n-gram 模型受限于固定窗口。

  2. 参数共享(RNN 权重在每个时间步共享),更高效。

  3. 能学到词的分布式表示,结合 Embedding 表达能力强。

缺点:

  1. 训练时间长,尤其是大词表。

  2. 长序列仍可能丢失远距离信息。

  3. 对并行计算不友好(序列依赖限制了并行性)。

  4. 输出词表过大时,softmax 计算代价高。

SENNA

SENNA 全称是 Semantic/syntactic Extraction using a Neural Network Architecture,是由 Collobert et al., 2011 提出的 一体化 NLP 系统

SENNA 的核心理念是:抛弃繁琐的人工特征,用一个统一的前馈神经网络架构来处理多种不同的 NLP 任务。

它分为两个关键阶段:

  1. 高效的无监督预训练 (Pre-training): SENNA 没有采用 FF-NNLM 那种计算开销巨大的 Softmax 来预测下一个词。相反,它采用了一种对比学习(Contrastive Learning)的思路。模型会读取一个真实的合法文本窗口(如“猫 抓 老鼠”),然后随机替换掉中间的词,构造一个错误的负样本窗口(如“猫 桌子 老鼠”)。网络的训练目标非常简单:只需让真实窗口的打分高于错误窗口即可。 由于避免了全局 Softmax 计算,SENNA 能够在海量的无标注维基百科语料上快速训练,从而得到了一套高质量的共享词向量(Word Embeddings)。

  2. 下游任务的监督微调 (Fine-tuning): 在得到这套预训练的词向量后,SENNA 将其作为网络底层的初始化权重(Embedding Layer)。然后,针对具体的下游任务(如实体识别),再利用少量的有标签数据对整个网络进行微调。

Word2Vec

Word2Vec 是 NLP 领域非常经典的词向量训练方法,它并非传统意义上的深层神经网络,而是一个极其“浅”的线性模型。它包含两种训练架构:

  1. CBOW (Continuous Bag-of-Words):利用上下文的词汇来预测中心词(将上下文词向量取平均或求和)。

  2. Skip-gram:利用中心词去预测它周围的上下文词汇

它提出了两种优化 Softmax 计算的近似策略:

  • 负采样 (Negative Sampling):将原本在十几万词表上做全局概率分布的 Softmax,简化为多个独立的二分类问题。模型每次迭代只需更新当前正确词(正样本)和少量随机抽取的错误词(负样本)的权重,使得单次计算量成百上千倍地下降。

  • 层级 Softmax (Hierarchical Softmax):利用哈夫曼树(Huffman Tree)将词汇组织成二叉树结构,将高频词放在靠近根节点的位置,从而将查找与计算的复杂度从O(V)O(|V|) 降维到了O(log2V)O(\log_2|V|)

GloVe

Word2Vec 本质上是基于“局部滑动窗口”在进行迭代更新,它并没有充分利用语料库中宏观的全局统计特征。。而传统的矩阵分解方法(如 LSA 潜在语义分析)虽然利用了全局信息,但在词汇类比等细粒度语义任务上表现糟糕。因此,GloVe 的核心思路是:通过统计词与词共现的全局信息,学习词的向量表示(全局矩阵分解和局部上下文窗口)。

GloVe 最天才的地方,在于它没有直接去拟合两个词同时出现的概率,而是去拟合“两个词与第三个词共现概率的比值”。

我们来看 GloVe 论文中最经典的那个例子。假设我们有三个词:

  • ii = "ice"(冰)

  • jj = "steam"(蒸汽)

  • kk = 探针词(用来测试前两个词的)

定义P(ki)P(k|i) 为在词ii 的上下文中,出现词kk 的概率。我们来观察比值P(ki)P(kj)\frac{P(k|i)}{P(k|j)}

  1. kk = "solid"(固体)时:"solid" 和 "ice" 关系密切,和 "steam" 没啥关系。所以P(ki)P(k|i) 很大,P(kj)P(k|j) 很小。比值1\gg 1

  2. kk = "gas"(气体)时:"gas" 和 "steam" 关系密切。所以P(ki)P(k|i) 很小,P(kj)P(k|j) 很大。比值1\ll 1

  3. kk = "water"(水)时:"water" 跟冰和蒸汽都有关。两者概率都大。比值1\approx 1

  4. kk = "fashion"(时尚)时:跟两者都没关系。两者概率都很小。比值1\approx 1

结论: 相比于单独的概率P(ki)P(k|i)P(kj)P(k|j)它们的比值P(ki)P(kj)\frac{P(k|i)}{P(k|j)} 能够极其精准地过滤掉噪音,并提炼出iijj 之间最本质的语义差异!

GloVe 的目标就是:让词向量的数学运算结果,能够拟合这个概率比值。

假设我们有一个未知的映射函数FF,输入是三个词的向量wi,wj,w~kw_i, w_j, \tilde{w}_k,输出是它们的概率比值:

F(wi,wj,w~k)=PikPjkF(w_i, w_j, \tilde{w}_k) = \frac{P_{ik}}{P_{jk}}

为了让向量空间保持线性结构(也就是能做加减法),作者强制要求FF 的输入必须是向量差:

F(wiwj,w~k)=PikPjkF(w_i - w_j, \tilde{w}_k) = \frac{P_{ik}}{P_{jk}}

最终作者推导出了一个极其简洁的内积形式:

wiTw~k=log(Pik)=log(Xik)log(Xi)w_i^T \tilde{w}_k = \log(P_{ik}) = \log(X_{ik}) - \log(X_i)

(注:XikX_{ik}iikk 在全局语料中共现的次数,XiX_iii 出现的总次数)

因为公式需要满足对称性(iikk 的地位应该是平等的),作者巧妙地将log(Xi)\log(X_i) 吸收到一个偏置项bib_i 中,并为kk 也增加一个偏置项b~k\tilde{b}_k,最终得到了 GloVe 的核心目标等式

wiTw~k+bi+b~k=log(Xik)w_i^T \tilde{w}_k + b_i + \tilde{b}_k = \log(X_{ik})

这句话的意思是:两个词向量的内积,加上它们各自的偏置,应该等于它们在全局共现矩阵中同现次数的对数。

如果直接用上面的公式作为损失函数去优化,会有一个致命问题:“the”、“is” 这种极其高频的词,其共现次数XikX_{ik} 会大得离谱,导致模型全在拟合停用词,而忽略了真正有意义的低频词。

为了解决这个问题,GloVe 引入了一个精心设计的权重函数f(Xij)f(X_{ij})

这个函数有两个特点:

  1. 如果两个词共现次数是 0,权重就是 0(直接不计算,极大地提升了训练速度,因为共现矩阵是非常稀疏的)。

  2. 对于高频词,权重不会无限增大,而是被“截断”在了一个最大值(论文中通常取α=0.75\alpha = 0.75,最大阈值xmax=100x_{max} = 100)。

最终,GloVe 的全局损失函数JJ 定格为以下这个优美的平方损失公式:

J=i,j=1Vf(Xij)(wiTw~j+bi+b~jlogXij)2J = \sum_{i,j=1}^V f(X_{ij}) \left( w_i^T \tilde{w}_j + b_i + \tilde{b}_j - \log X_{ij} \right)^2