共计 1799 个字符,预计需要花费 5 分钟才能阅读完成。
词嵌入作为 NLP 领域的基石技术,能够将离散的词语转化为连续的向量表示,从而捕捉词语间的语义和语法关系。其中 CBOW(Continuous Bag-of-Words)模型因其简单高效的特点,成为词嵌入学习的经典方法。本文将带大家从数学原理到 Python 实现,逐步拆解 CBOW 模型的手算过程。

1. CBOW 模型数学原理
CBOW 模型的核心思想是通过上下文词语预测当前词语。假设我们有一个大小为 $2m$ 的上下文窗口(即左右各 $m$ 个词),模型结构主要分为三层:
-
输入层 :将上下文词语的 one-hot 表示 ${x_1, x_2, …, x_C}$($C=2m$)作为输入,每个 $x_i$ 是维度为 $V$ 的向量($V$ 为词汇表大小)
-
隐藏层 :
- 通过嵌入矩阵 $W_{V\times N}$($N$ 为嵌入维度)计算平均上下文向量:
$$h = \frac{1}{C} \sum_{i=1}^C W^T x_i$$ -
这里 $h$ 就是我们要学习的词向量表示
-
输出层 :
- 使用另一个矩阵 $W’_{N\times V}$ 计算得分:
$$u = W’^T h$$ - 通过 softmax 得到预测概率分布:
$$y_j = \frac{\exp(u_j)}{\sum_{k=1}^V \exp(u_k)}$$
2. Python 手写实现
下面我们用 NumPy 逐步实现 CBOW 模型的核心计算过程:
import numpy as np
# 参数设置
V = 10000 # 词汇表大小
N = 300 # 嵌入维度
m = 2 # 上下文窗口半宽
# 初始化权重矩阵
W = np.random.rand(V, N) * 0.1 # 输入到隐藏层
W_prime = np.random.rand(N, V) * 0.1 # 隐藏到输出层
# 模拟输入:3 个上下文词的 one-hot
context_words = [256, 512, 1024] # 词索引
x = np.zeros((len(context_words), V))
for i, idx in enumerate(context_words):
x[i, idx] = 1
# 前向传播
# 1. 输入层→隐藏层
h = np.mean([W.T.dot(x_i) for x_i in x], axis=0)
# 2. 隐藏层→输出层
u = W_prime.T.dot(h)
y = np.exp(u) / np.sum(np.exp(u)) # softmax
# 梯度检查(示例)target_word = 2048 # 目标词索引
target = np.zeros(V)
target[target_word] = 1
error = y - target
assert error.shape == (V,), "梯度维度不匹配"
3. CBOW vs Skip-gram
虽然两者都是 Word2Vec 的变体,但存在关键差异:
- 计算顺序相反 :
- CBOW 用上下文预测中心词
-
Skip-gram 用中心词预测上下文
-
计算复杂度 :
- CBOW 适合高频词(因上下文平均降低了方差)
-
Skip-gram 适合低频词(每个上下文词单独处理)
-
数学表达差异 :
- Skip-gram 的损失函数是多个 softmax 的乘积
- CBOW 是单个 softmax 输出
4. 工程实践要点
上下文窗口选择
- 通用场景:$m=2\sim5$
- 专业领域:可增大到 $m=10$
- 动态窗口:随训练轮次线性增加
高频词降采样
对词 $w_i$ 的采样概率:
$$P(w_i) = 1 – \sqrt{\frac{t}{f(w_i)}}$$
其中 $t$ 是阈值(通常 $10^{-5}$)
负采样加速
用以下概率分布采样负例:
$$P_n(w_i) = \frac{f(w_i)^{3/4}}{\sum_{j=1}^V f(w_j)^{3/4}}$$
实现示例:
def negative_sampling(probs, k=5):
return np.random.choice(len(probs),
size=k,
p=probs,
replace=False
)
5. 常见问题与优化
- 稀疏矩阵问题 :
- 使用稀疏矩阵格式存储 one-hot
-
仅计算非零索引的嵌入向量
-
学习率调整 :
- 初始值通常 0.025
-
线性衰减到 0.001
-
可视化技巧 :
- 先 TSNE 降维到 2D
- 对同类词用相同颜色标记
6. 局限性与思考
尽管 CBOW 简单高效,但仍存在明显局限:
- 生僻词处理 :低频词因样本不足导致嵌入质量差
- 上下文对称性 :无法区分左右位置信息
- 与 BERT 对比 :
- CBOW 是浅层双向模型
- BERT 通过 Transformer 捕获深层上下文
最后留给大家思考:在预训练时代,传统词嵌入方法是否还有不可替代的价值?欢迎在评论区分享你的见解。
