词嵌入(Word Embedding)深度解析:从符号到向量的语义映射
- [词嵌入(Word Embedding)深度解析:从符号到向量的语义映射](#词嵌入(Word Embedding)深度解析:从符号到向量的语义映射)
-
- 一、为什么需要词嵌入?------传统方法的困境
-
- [1.1 传统表示方法的缺陷](#1.1 传统表示方法的缺陷)
- [1.2 人类理解语言的方式](#1.2 人类理解语言的方式)
- 二、词嵌入的数学本质:分布假设
-
- [2.1 向量空间的几何意义](#2.1 向量空间的几何意义)
- 三、词嵌入生成方法深度解析
-
- [3.1 Word2Vec(2013)------ 革命性突破](#3.1 Word2Vec(2013)—— 革命性突破)
-
- [(1) CBOW(Continuous Bag-of-Words)](#(1) CBOW(Continuous Bag-of-Words))
- [(2) Skip-Gram(更常用)](#(2) Skip-Gram(更常用))
- [Word2Vec 代码实现(PyTorch):](#Word2Vec 代码实现(PyTorch):)
- [3.2 GloVe(Global Vectors,2014)------ 全局统计](#3.2 GloVe(Global Vectors,2014)—— 全局统计)
- [3.3 FastText(2016)------ 解决未登录词](#3.3 FastText(2016)—— 解决未登录词)
- [3.4 上下文敏感嵌入(BERT, 2018+)](#3.4 上下文敏感嵌入(BERT, 2018+))
- 四、词嵌入转换全过程详解(以"cat"为例)
- 五、词嵌入的可视化与分析
-
- [5.1 降维可视化(t-SNE)](#5.1 降维可视化(t-SNE))
- [5.2 语义关系验证](#5.2 语义关系验证)
- 六、主流词嵌入工具实战
-
- [6.1 预训练模型加载(Gensim)](#6.1 预训练模型加载(Gensim))
- [6.2 Hugging Face Transformers(上下文嵌入)](#6.2 Hugging Face Transformers(上下文嵌入))
- 七、词嵌入的局限性与前沿发展
-
- [7.1 当前局限](#7.1 当前局限)
- [7.2 前沿方向](#7.2 前沿方向)
- 八、动手实践建议
-
- [8.1 本地快速体验](#8.1 本地快速体验)
- [8.2 代码实验](#8.2 代码实验)
- [8.3 进阶项目](#8.3 进阶项目)
- 九、结语:词嵌入的哲学意义
词嵌入(Word Embedding)深度解析:从符号到向量的语义映射
核心洞见 :词嵌入的本质是将离散的符号空间映射到连续的向量空间,使得语义相似的词在向量空间中距离相近。这突破了传统NLP中"词袋模型"的局限,为深度学习模型理解语言提供了数学基础。
一、为什么需要词嵌入?------传统方法的困境
1.1 传统表示方法的缺陷
-
独热编码(One-Hot Encoding):
python"猫" → [0, 0, 0, 1, 0, ..., 0] # 词表大小=50,000 "狗" → [0, 0, 0, 0, 1, ..., 0]问题:
- 维度灾难(50,000+维稀疏向量)
- 无法表示语义关系("猫"和"狗"的余弦相似度=0)
- 无泛化能力(未见过的词无法处理)
-
词袋模型(Bag-of-Words):
- 丢失词序信息
- 无法处理一词多义
1.2 人类理解语言的方式
当我们看到:
"苹果 发布了新手机 " vs "苹果 是一种水果"
人类能根据上下文区分"苹果"的含义。词嵌入的目标是让机器也能做到这一点。
二、词嵌入的数学本质:分布假设
分布假设 (Zellig Harris, 1954):
"具有相似上下文的词,具有相似的语义"数学表达 :
词 w w w的语义 = 其在大型语料库中出现的上下文分布
vec ( w ) = f ( context ( w ) ) \text{vec}(w) = f(\text{context}(w)) vec(w)=f(context(w))
2.1 向量空间的几何意义
在理想词向量空间中:
- 语义相似 ↔ 向量距离近
cosine_similarity("猫", "狗") > cosine_similarity("猫", "汽车") - 语义关系 ↔ 向量偏移
vec("国王") - vec("男人") + vec("女人") ≈ vec("女王")
三、词嵌入生成方法深度解析
3.1 Word2Vec(2013)------ 革命性突破
两种架构:
(1) CBOW(Continuous Bag-of-Words)
- 目标:通过上下文预测中心词
- 输入:上下文词向量的平均
- 输出:中心词的概率分布
- 数学过程 :
P ( w c ∣ w c − m , . . . , w c − 1 , w c + 1 , . . . , w c + m ) = softmax ( W ⋅ avg ( v w c − m , . . . , v w c + m ) ) P(w_c | w_{c-m},...,w_{c-1},w_{c+1},...,w_{c+m}) = \text{softmax}(W \cdot \text{avg}(v_{w_{c-m}},...,v_{w_{c+m}})) P(wc∣wc−m,...,wc−1,wc+1,...,wc+m)=softmax(W⋅avg(vwc−m,...,vwc+m))
(2) Skip-Gram(更常用)
- 目标:通过中心词预测上下文
- 输入:中心词向量
- 输出:上下文词的概率分布
- 数学过程 :
P ( w c + j ∣ w c ) = softmax ( W ′ ⋅ v w c ) for j ∈ [ − m , m ] , j ≠ 0 P(w_{c+j} | w_c) = \text{softmax}(W' \cdot v_{w_c}) \quad \text{for } j \in [-m, m], j\neq0 P(wc+j∣wc)=softmax(W′⋅vwc)for j∈[−m,m],j=0
训练技巧:
- 负采样(Negative Sampling) :替代 softmax 加速训练
log σ ( v w o ′ T v w c ) + ∑ i = 1 K E w i ∼ P n ( w ) [ log σ ( − v w i ′ T v w c ) ] \log \sigma(v_{w_o}'^T v_{w_c}) + \sum_{i=1}^K \mathbb{E}{w_i \sim P_n(w)}[\log \sigma(-v{w_i}'^T v_{w_c})] logσ(vwo′Tvwc)+i=1∑KEwi∼Pn(w)[logσ(−vwi′Tvwc)] - Hierarchical Softmax:使用霍夫曼树减少计算量
Word2Vec 代码实现(PyTorch):
python
import torch
import torch.nn as nn
class SkipGram(nn.Module):
def __init__(self, vocab_size, embedding_dim):
super().__init__()
self.embeddings = nn.Embedding(vocab_size, embedding_dim) # 中心词嵌入
self.output = nn.Embedding(vocab_size, embedding_dim) # 上下文词嵌入
def forward(self, center_words, context_words):
center_embed = self.embeddings(center_words) # [batch, embed_dim]
context_embed = self.output(context_words) # [batch, embed_dim]
scores = torch.sum(center_embed * context_embed, dim=1) # 点积
return torch.sigmoid(scores)
3.2 GloVe(Global Vectors,2014)------ 全局统计
核心思想:直接建模词共现矩阵的统计特性
- 共现矩阵 X X X: X i j X_{ij} Xij = 词 j j j出现在词 i i i上下文中的次数
- 优化目标 :
( w i − w j ) T w ~ k = log ( X i k ) − log ( X j k ) (w_i - w_j)^T \tilde{w}k = \log(X{ik}) - \log(X_{jk}) (wi−wj)Tw~k=log(Xik)−log(Xjk)
即:向量差异应反映共现概率比
优势:
- 利用全局统计信息,训练更稳定
- 对罕见词效果更好
3.3 FastText(2016)------ 解决未登录词
创新点:将词分解为字符n-gram
- 例:"apple" →
<ap,app,ppl,ple,le> - 词向量 = 所有n-gram向量的平均
- 优势 :
- 处理拼写错误:"aple" 仍有有效表示
- 支持形态丰富的语言(如德语、芬兰语)
3.4 上下文敏感嵌入(BERT, 2018+)
范式转变:词向量不再固定,而是依赖上下文
-
输入:整个句子
-
输出:每个词的动态向量
-
例 :
pythonvec1 = BERT("苹果发布了新手机")[0] # "苹果"≈公司 vec2 = BERT("我吃了一个苹果")[0] # "苹果"≈水果 cosine_similarity(vec1, vec2) ≈ 0.3 # 而静态嵌入≈0.8
四、词嵌入转换全过程详解(以"cat"为例)
步骤1:预处理与分词
python
text = "The quick brown fox jumps over the lazy cat."
tokens = ["<sos>", "the", "quick", "brown", "fox", "jumps",
"over", "the", "lazy", "cat", "<eos>"]
步骤2:构建词汇表(Vocabulary)
python
vocab = {
"<pad>": 0, "<unk>": 1, "<sos>": 2, "<eos>": 3,
"the": 4, "quick": 5, "brown": 6, "fox": 7,
"jumps": 8, "over": 9, "lazy": 10, "cat": 11,
...
}
vocab_size = 50000 # 典型值
步骤3:选择嵌入维度(Hyperparameter)
- 小型任务:50-100维
- 通用任务:300维(Word2Vec/GloVe标准)
- 大型模型:768+维(BERT-base)
步骤4:初始化嵌入矩阵(关键步骤)
python
import numpy as np
embedding_dim = 300
embedding_matrix = np.random.uniform(
-0.1, 0.1,
(vocab_size, embedding_dim)
) # Xavier初始化
步骤5:通过训练更新向量(Skip-Gram示例)
-
采样上下文窗口(窗口大小=2):
- 中心词:"cat" (ID=11)
- 上下文词:["lazy", "the"] → IDs [10, 4]
-
前向传播:
pythoncenter_vec = embedding_matrix[11] # [300] context_vecs = embedding_matrix[[10, 4]] # [2, 300] # 计算相似度 similarities = np.dot(context_vecs, center_vec) # [2] probabilities = softmax(similarities) # 预测概率 -
计算损失(负采样):
python# 正样本(真实上下文) positive_loss = -np.log(sigmoid(np.dot(context_vecs[0], center_vec))) # 负样本(随机采样) negative_samples = [23, 45, 67] # 非上下文词ID negative_loss = -np.sum(np.log(sigmoid(-np.dot(embedding_matrix[negative_samples], center_vec)))) total_loss = positive_loss + negative_loss -
反向传播更新向量:
python# 中心词向量梯度 grad_center = (1 - sigmoid(np.dot(context_vecs[0], center_vec))) * context_vecs[0] # 更新 embedding_matrix[11] += learning_rate * grad_center
步骤6:训练完成后的"cat"向量
python
cat_vector = embedding_matrix[11] # [0.25, -0.18, 0.73, ..., 0.02]
# 形状: [300]
五、词嵌入的可视化与分析
5.1 降维可视化(t-SNE)
python
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
# 提取常见词的向量
words = ["cat", "dog", "car", "apple", "banana", "king", "queen"]
vectors = [embedding_matrix[vocab[w]] for w in words]
# 降维到2D
tsne = TSNE(n_components=2, random_state=42)
embeddings_2d = tsne.fit_transform(vectors)
# 绘制
plt.figure(figsize=(10, 8))
for i, word in enumerate(words):
plt.scatter(embeddings_2d[i, 0], embeddings_2d[i, 1])
plt.annotate(word, (embeddings_2d[i, 0], embeddings_2d[i, 1]))
plt.show()
5.2 语义关系验证
python
# 计算"国王 - 男人 + 女人" ≈ "女王"
king = embedding_matrix[vocab["king"]]
man = embedding_matrix[vocab["man"]]
woman = embedding_matrix[vocab["woman"]]
result_vec = king - man + woman
# 找出最接近的词
similarities = np.dot(embedding_matrix, result_vec)
top_indices = np.argsort(-similarities)[:5] # 降序排序取前5
[top_words.append(reverse_vocab[idx]) for idx in top_indices]
# 输出: ["queen", "monarch", "princess", "empress", "royal"]
六、主流词嵌入工具实战
6.1 预训练模型加载(Gensim)
python
from gensim.models import KeyedVectors
# 加载Google News预训练模型 (300维)
model = KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)
# 获取"cat"的向量
cat_vec = model['cat'] # numpy array [300]
# 查找最相似词
similar_cats = model.most_similar('cat', topn=5)
# [('kitten', 0.76), ('dog', 0.68), ('pet', 0.65), ...]
# 语义运算
model.most_similar(positive=['king', 'woman'], negative=['man'], topn=1)
# [('queen', 0.71)]
6.2 Hugging Face Transformers(上下文嵌入)
python
from transformers import AutoTokenizer, AutoModel
import torch
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased")
# 两个不同上下文
texts = [
"I have a pet cat.",
"Apple released a new iPhone."
]
inputs = tokenizer(texts, return_tensors="pt", padding=True)
outputs = model(**inputs)
# 获取"cat"和"Apple"的向量
cat_token_index = (inputs['input_ids'][0] == tokenizer.convert_tokens_to_ids("cat")).nonzero().item()
apple_token_index = (inputs['input_ids'][1] == tokenizer.convert_tokens_to_ids("apple")).nonzero().item()
cat_vector = outputs.last_hidden_state[0, cat_token_index] # [768]
apple_vector = outputs.last_hidden_state[1, apple_token_index] # [768]
七、词嵌入的局限性与前沿发展
7.1 当前局限
| 问题 | 说明 | 解决方案 |
|---|---|---|
| 一词多义 | "bank"在金融/河岸场景相同 | BERT等上下文模型 |
| 领域偏移 | 医学术语在通用语料中表现差 | 领域适应(Domain Adaptation) |
| 文化偏见 | vec("doctor") - vec("man") + vec("woman") 偏向"nurse" |
偏见消减算法 |
| 罕见词 | "antidisestablishmentarianism"向量质量差 | FastText, Byte Pair Encoding |
7.2 前沿方向
- 知识增强嵌入 :融合知识图谱(如WikiData)
vec ( w ) = α ⋅ text_vec ( w ) + ( 1 − α ) ⋅ kg_vec ( w ) \text{vec}(w) = \alpha \cdot \text{text\_vec}(w) + (1-\alpha) \cdot \text{kg\_vec}(w) vec(w)=α⋅text_vec(w)+(1−α)⋅kg_vec(w) - 多模态嵌入:结合图像/音频(CLIP模型)
- 动态嵌入:随时间演化(如疫情期间"mask"语义变化)
- 稀疏嵌入:提高可解释性(如Google的SWEM)
八、动手实践建议
8.1 本地快速体验
bash
# 安装必要库
pip install gensim numpy matplotlib scikit-learn
# 下载预训练模型 (1.5GB)
wget https://s3.amazonaws.com/dl4j-distribution/GoogleNews-vectors-negative300.bin.gz
gunzip GoogleNews-vectors-negative300.bin.gz
8.2 代码实验
python
# 实验1: 观察动物聚类
animals = ["cat", "dog", "elephant", "tiger", "car", "phone"]
vectors = [model[w] for w in animals if w in model]
# 实验2: 偏见检测
print(model.similarity("programmer", "man")) # 0.35
print(model.similarity("programmer", "woman")) # 0.22
# 实验3: 比喻理解
model.most_similar(positive=["water", "cold"], negative=["hot"])
# 预期: ["ice", "frozen", ...]
8.3 进阶项目
- 领域适应:在医疗语料上微调Word2Vec
- 偏见消减:实现Hard Debiasing算法
- 可视化工具:构建交互式词向量探索器
九、结语:词嵌入的哲学意义
词嵌入不仅是技术突破,更是一种认知范式转变:
- 从符号到连续:打破"非0即1"的符号主义局限
- 从局部到全局:语义存在于整个向量空间关系中
- 从人工到涌现:复杂语义通过简单优化目标自然涌现
正如Yoshua Bengio所言:
"分布式表示是深度学习的基石,它让机器学会了人类式的泛化能力。"
延伸阅读:
- Word2Vec原论文 (Mikolov et al., 2013)
- GloVe: Global Vectors for Word Representation (Pennington et al., 2014)
- 《Natural Language Processing with PyTorch》(2019) 第4章
- Hugging Face词嵌入课程