NLP 词向量有哪些方法?Word2Vec、GloVe 到 BERT 演进详解
词向量就是把词映射成一段连续的实数向量(通常 50-300 维),让语义相近的词在向量空间中距离也近。计算机不认识"苹果"和"橘子",但它们对应的向量夹角很小——"苹果"和"汽车"的向量夹角大。这个"距离近=语义近"的性质,是一切下游 NLP 任务的基础。
词向量方法经历了三代演进:静态词向量(每个词固定一个向量)→ 上下文词向量(同一个词在不同语境中有不同向量)→ 大模型嵌入(深层语义表示)。
静态词向量:Word2Vec / GloVe / FastText
Word2Vec(2013)的核心思想:上下文相似的词,语义也相似。两种训练方式——CBOW 用上下文预测中心词(快,适合常用词),Skip-gram 用中心词预测上下文(慢,但稀有词效果更好)。训练出的向量支持类比运算:king - man + woman ≈ queen。
GloVe(2014)换了个思路:不靠上下文窗口,而是利用全局的词-词共现矩阵。最小化 w_i · w_j + b_i + b_j - log(X_ij) 的差距,本质上是对共现矩阵做分解。在大规模语料上比 Word2Vec 更稳。
FastText(2016)在 Word2Vec 基础上加了子词(subword)信息:把 "apple" 拆成 <ap, app, ppl, ple, le> 这些 n-gram,向量是所有子词向量的和。这解决了 OOV 问题——遇到 "apples" 虽然没见过,但子词 <app, ppl> 见过,也能算出合理的向量。对形态丰富的语言(德语、芬兰语)效果提升明显。
静态词向量的共同局限:一词一义。"苹果"的水果义和公司义共用一个向量,无法区分。
上下文词向量:ELMo → BERT
ELMo(2018)用双向 LSTM 在大规模语料上训练语言模型,然后取各层隐藏状态的加权和作为词向量。同一个"苹果",在"吃了一个苹果"和"苹果发布了新手机"中会得到不同的向量——第一次解决了一词多义问题。缺点是 LSTM 架构慢,且不是真正的深度双向。
BERT(2018)换成 Transformer 编码器,用 Masked Language Model 实现真正的双向上下文。取出最后一层的隐藏状态就是上下文词向量,效果全面超越 ELMo。BERT 的词向量不只是"词向量"了——它是整个句子的深度语义表示。
python# 用 transformers 获取 BERT 词向量 from transformers import AutoModel, AutoTokenizer tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased") model = AutoModel.from_pretrained("bert-base-uncased") inputs = tokenizer("Apple released iPhone", return_tensors="pt") outputs = model(**inputs) # outputs.last_hidden_state 就是每个 token 的上下文向量
现代方向:句子嵌入和大模型
纯词向量在检索、聚类场景下不够用——需要把整句话编码成一个向量。SimCSE 用对比学习训练 BERT,同一句话两次过 dropout 得到正例对,不同句互为负例,简单但效果极好。BGE 和 E5 是当前中文文本嵌入的 SOTA,支持直接算句子相似度做检索。
大模型(GPT、LLaMA)的隐藏状态也可以当词向量用,但因为自回归只有单向上下文,做句子嵌入通常不如双向模型。实际项目中文本检索优先用 BGE/E5,词级别分析用 BERT,不需要上下文时 Word2Vec 仍然够用。
追问
Word2Vec 和 GloVe 怎么选?
数据量小(<1亿 token)用 Word2Vec,训练快、效果好。数据量大用 GloVe,全局统计信息更充分。实践中两者效果差距不大,选择更多取决于你有没有预训练好的向量可以直接下载——GloVe 提供了基于 Common Crawl 的预训练向量,覆盖面广。
静态词向量还有用吗?
有,但场景在缩小。计算资源极度受限(嵌入式设备)、只需要词级别相似度(同义词挖掘)、或者做特征工程的基线时,静态词向量仍然是性价比最高的选择。训练快、推理零开销。但如果你的任务需要理解上下文,直接上 BERT 就对了。