共计 1862 个字符,预计需要花费 5 分钟才能阅读完成。
背景介绍
CBOW(Continuous Bag of Words)模型是 Word2Vec 的两种主要架构之一,它通过上下文词汇预测当前词来学习词向量。与 Skip-gram 模型不同,CBOW 更适合处理小型数据集,且在小规模语料上收敛更快。其核心思想是:给定一个中心词周围的上下文窗口,模型学习预测该中心词。这种方法的优势在于能有效捕捉词汇的语义和语法关系,广泛应用于词义相似度计算、文本分类等下游任务。

核心计算步骤
1. 词向量初始化
- 为词汇表中的每个词随机初始化两个向量:
- 输入向量(context vector):当词作为上下文时使用
- 输出向量(target vector):当词作为目标词时使用
- 假设词汇表大小为 V,嵌入维度为 d,则初始化两个 V×d 的矩阵 W 和 W ’
2. 上下文窗口处理
- 定义窗口大小 k(通常取 2 -5),对每个中心词取其前后各 k 个词作为上下文
- 对上下文词进行 one-hot 编码,形成向量 x_i ∈ R^V
- 计算上下文词向量的平均值:
h = (1/C) * Σ(W^T * x_i)其中 C 是上下文词数量
3. 前向传播
- 将平均向量 h 与输出矩阵 W ’ 相乘得到分数向量:
u = W' * h - 通过 softmax 计算预测概率分布:
ŷ = softmax(u)
4. 损失计算
- 使用交叉熵损失函数:
L = -Σ y_i * log(ŷ_i)其中 y 是真实标签的 one-hot 向量
5. 梯度反向传播
- 计算输出层梯度:
∂L/∂u = ŷ - y - 更新输出矩阵 W ’:
∂L/∂W' = h * (ŷ - y)^T - 计算隐藏层梯度:
∂L/∂h = W' * (ŷ - y) - 更新输入矩阵 W:
∂L/∂W = (1/C) * Σ x_i * (∂L/∂h)^T
Python 实现示例
import numpy as np
# 超参数设置
V = 10000 # 词汇表大小
d = 300 # 嵌入维度
lr = 0.01 # 学习率
# 初始化权重矩阵
W = np.random.randn(V, d) * 0.01 # 输入矩阵
W_prime = np.random.randn(d, V) * 0.01 # 输出矩阵
# 模拟数据:上下文词索引和中心词索引
context_indices = [10, 20, 30] # 假设窗口大小为 3
center_index = 15 # 目标词索引
# 前向传播
# 1. 构造上下文向量
context_vectors = W[context_indices, :] # 获取上下文词向量
h = np.mean(context_vectors, axis=0) # 平均上下文向量
# 2. 计算分数
u = np.dot(W_prime.T, h)
# 3. softmax 计算
exp_u = np.exp(u - np.max(u)) # 数值稳定处理
y_hat = exp_u / np.sum(exp_u)
# 构造真实标签
Y = np.zeros(V)
Y[center_index] = 1
# 计算损失
loss = -np.sum(Y * np.log(y_hat + 1e-10)) # 加小量防止 log(0)
# 反向传播
# 1. 输出层梯度
du = y_hat - Y
# 2. 更新输出矩阵
W_prime -= lr * np.outer(h, du)
# 3. 隐藏层梯度
dh = np.dot(W_prime, du)
# 4. 更新输入矩阵
for idx in context_indices:
W[idx, :] -= lr * (1/len(context_indices)) * dh
性能考量
- 计算复杂度分析 :
- softmax 计算复杂度为 O(V),当词汇表很大时成为瓶颈
-
每次更新需要修改 |C|+ 1 个词向量(上下文词 + 中心词)
-
优化方法 :
- 负采样:将 softmax 替换为多个二分类问题
- 层次 softmax:使用霍夫曼树减少计算量
- 异步 SGD:允许并行更新不同词向量
- 向量化实现:利用 numpy 广播机制加速矩阵运算
避坑指南
- 数值不稳定问题 :
- 在计算 softmax 时先减去最大值
-
对 log 计算添加小量(如 1e-10)防止 NaN
-
梯度爆炸 / 消失 :
- 初始化权重时使用较小方差(如 0.01)
-
实施梯度裁剪(gradient clipping)
-
收敛缓慢 :
- 适当增大学习率(尝试 0.025-0.05)
-
使用 Adagrad 或 Adam 优化器
-
效果不佳 :
- 检查窗口大小是否合适(常用 5)
- 确保训练迭代次数足够(通常需要 5 -50 个 epoch)
总结与延伸
通过手动实现 CBOW 模型,我们深入理解了词嵌入的训练机制。对于大规模应用,建议:
1. 使用 gensim 或 TensorFlow 等框架的优化实现
2. 尝试在大型语料(如 Wikipedia)上训练
3. 结合 subword 信息处理 OOV 问题
4. 探索与 BERT 等新型架构的对比差异
CBOW 作为词嵌入的基础模型,其思想在当今预训练模型中仍有体现。理解其计算过程有助于掌握更复杂的 NLP 模型。
正文完
