共计 2055 个字符,预计需要花费 6 分钟才能阅读完成。
词嵌入的核心价值与模型选型
词嵌入是 NLP 领域的基石技术,它将离散的词语映射到连续的向量空间。这种表示不仅能捕捉词语间的语义关系(如 ’ 国王 - 女王≈男人 - 女人 ’),还能让机器学习模型更好地处理文本数据。相较于传统的 one-hot 编码,词嵌入解决了维度灾难和语义鸿沟两大难题。
在 Word2Vec 框架下,CBOW 和 Skip-gram 是两种经典模型:
- CBOW:通过上下文预测中心词,训练速度快,适合小型数据集
- Skip-gram:通过中心词预测上下文,擅长处理低频词,适合大规模语料

词嵌入矩阵的数学表示
词嵌入矩阵本质是一个查找表,其中每行对应一个词的向量表示。数学上可表示为:
$$ \mathbf{E} \in \mathbb{R}^{V \times D} $$
- $V$:词汇表大小
- $D$:嵌入维度(通常 50-300)
PyTorch 实现基础架构
矩阵初始化
import torch
import torch.nn as nn
class CBOW(nn.Module):
def __init__(self, vocab_size, embedding_dim):
super().__init__()
# 正态分布初始化,均值 0,标准差 0.1
self.embeddings = nn.Embedding(vocab_size, embedding_dim)
nn.init.normal_(self.embeddings.weight, mean=0, std=0.1)
# 投影层将上下文向量求和后映射回词汇空间
self.projection = nn.Linear(embedding_dim, vocab_size)
上下文窗口处理
def get_context(window_size, text_ids):
"""
text_ids: 已转换为 ID 序列的文本
返回: (中心词, 上下文词) 对生成器
"""
for i in range(window_size, len(text_ids)-window_size):
center = text_ids[i]
context = torch.cat([text_ids[i-window_size:i],
text_ids[i+1:i+window_size+1]
])
yield center, context
训练优化关键技术
负采样加速训练
import math
def negative_sampling(weights, num_samples):
"""
weights: 词频统计的权重列表
实现 log-uniform 分布的负采样
"""
z = 0.5 # 平滑系数
probs = torch.tensor([math.log(w + z) for w in weights])
probs = probs / probs.sum()
return torch.multinomial(probs, num_samples, replacement=True)
学习率策略对比
# 余弦退火比线性衰减更适合词嵌入训练
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=100, eta_min=0.0001)
可视化验证
from sklearn.manifold import TSNE
def visualize_embeddings(embeddings, words):
"""用 TSNE 降维展示词向量空间"""
tsne = TSNE(n_components=2)
reduced = tsne.fit_transform(embeddings)
plt.figure(figsize=(12,8))
for i, word in enumerate(words):
plt.scatter(reduced[i,0], reduced[i,1])
plt.annotate(word, (reduced[i,0], reduced[i,1]))
生产环境实战技巧
OOV 词处理三剑客
- UNK 令牌 :为低频词设置统一标记
- 子词单元 :采用 BPE 或 WordPiece 分解单词
- 字符级嵌入 :组合字符特征生成词向量
百万词汇内存优化
- 哈希分桶 :用哈希函数减少矩阵维度
- 混合精度训练 :FP16 节省显存
- 梯度检查点 :时间换空间
多 GPU 训练要点
model = nn.DataParallel(model) # 包装模型
# 梯度会自动在 GPU 间同步
loss.backward()
optimizer.step()
思考与延伸
课后思考题
- 如何设计实验验证词向量确实捕捉到了 ” 国王 - 男人≈女王 - 女人 ” 这类关系?
- 当遇到像 ” 苹果 ”(水果 / 公司)这样的多义词时,单一向量表示存在什么缺陷?ELMo 等上下文嵌入模型如何解决这个问题?
实践建议
建议读者在 20newsgroups 等小数据集上先跑通流程,再尝试维基百科等大规模语料。关键是要观察:
- 随着训练进行,近义词是否在向量空间中逐渐靠近
- 不同维度下词相似度的变化规律
- 负采样数量对训练速度和效果的影响
最后提醒:词嵌入只是 NLP 大厦的第一块砖,后续可以尝试结合 LSTM/Transformer 等更复杂的架构。
正文完
