共计 1991 个字符,预计需要花费 5 分钟才能阅读完成。
1. CBOW 模型前向传播基础
CBOW(Continuous Bag-of-Words)是 Word2Vec 的两种经典架构之一,其核心思想是通过上下文词预测中心词。我们先来看一个简单的 4 词窗口示例(左右各 2 个上下文词):

- 输入层:四个 one-hot 编码的上下文词(如
[0,1,0,...,0]) - 投影层:将四个词的词向量求平均(实际操作是相加后除以 4)
- 输出层:通过 softmax 计算目标词的概率分布
数学表达为:
h = \frac{1}{C} \sum_{c=1}^C W_{input}^T x_c
其中 C 是上下文词数量,$W_{input}$ 是输入词向量矩阵。
2. 反向传播的数学推导
2.1 损失函数定义
使用负对数似然损失:
J = -\log P(w_o|w_{c1},...,w_{cC})
其中 $w_o$ 是目标词(中心词)。
2.2 梯度计算关键步骤
-
首先计算输出层误差:
e = y - \hat{y}其中 $y$ 是真实标签的 one-hot 向量,$\hat{y}$ 是预测概率分布。
-
隐藏层到输出层的梯度:
\frac{\partial J}{\partial W_{output}} = h^T \cdot e -
输入层到隐藏层的梯度:
\frac{\partial J}{\partial h} = W_{output} \cdot e -
最终词向量更新梯度(以第一个上下文词为例):
\frac{\partial J}{\partial W_{input}^{(1)}} = \frac{1}{C} \cdot \frac{\partial J}{\partial h} \cdot x_1
3. Python 实现核心代码
import numpy as np
class CBOW:
def __init__(self, vocab_size, embedding_dim):
# 初始化词向量矩阵
self.W_input = np.random.randn(vocab_size, embedding_dim) * 0.01
self.W_output = np.random.randn(embedding_dim, vocab_size) * 0.01
def forward(self, context_indices):
# context_indices: 上下文词的索引列表
h = np.mean([self.W_input[i] for i in context_indices], axis=0)
scores = np.dot(h, self.W_output)
probs = np.exp(scores) / np.sum(np.exp(scores))
return h, probs
def backward(self, context_indices, target_idx, learning_rate=0.01):
# 前向传播
h, probs = self.forward(context_indices)
# 计算误差
y = np.zeros_like(probs)
y[target_idx] = 1
e = probs - y
# 计算梯度
grad_W_output = np.outer(h, e)
grad_h = np.dot(self.W_output, e)
# 更新参数
self.W_output -= learning_rate * grad_W_output
for i in context_indices:
self.W_input[i] -= learning_rate * grad_h / len(context_indices)
# 返回当前损失
return -np.log(probs[target_idx])
4. 实现中的常见问题与解决
4.1 梯度消失问题
当词表很大时,softmax 计算可能导致梯度非常小。解决方案:
- 使用负采样(Negative Sampling)替代全 softmax
- 采用层次 softmax(Hierarchical Softmax)
4.2 学习率选择
经验法则:
- 初始学习率通常设置在 0.01-0.001 之间
- 随着训练进行线性衰减
- 可以使用学习率调度器动态调整
4.3 词向量初始化
不当的初始化可能导致:
- 训练不稳定:使用 Xavier/Glorot 初始化
- 收敛缓慢:初始值建议在 [-0.5/embedding_dim, 0.5/embedding_dim] 范围
5. 避坑指南
- 维度不匹配:确保输入词向量和输出词向量维度一致
- 梯度爆炸:添加梯度裁剪(gradient clipping)
- 上下文窗口处理:
- 遇到句子边界时要特殊处理
- 可变窗口大小需要动态调整平均操作
- 数值稳定性:
- softmax 计算使用 log-sum-exp 技巧
- 添加微小 epsilon 避免除零错误
6. 延伸思考
尝试实现以下扩展功能:
1. 可变长度的上下文窗口(如 2 - 5 个词)
2. 加入 subsampling 高频词的优化
3. 比较负采样和层次 softmax 的效果差异
理解 CBOW 的反向传播机制是掌握词向量技术的重要一步。建议读者在实现基础版本后,可以进一步尝试优化训练效率和质量。
正文完
