共计 1501 个字符,预计需要花费 4 分钟才能阅读完成。
背景介绍
在自然语言处理(NLP)中,词嵌入是将词语映射到连续向量空间的技术,能够捕捉词语之间的语义和语法关系。词嵌入广泛应用于文本分类、机器翻译、情感分析等任务。CBOW(Continuous Bag of Words)是一种经典的词嵌入模型,它通过上下文预测当前词,适合处理大规模语料库。

算法原理
CBOW 模型的核心思想是利用上下文词语预测中心词。其结构包括输入层、投影层和输出层。具体步骤如下:
- 输入层 :将上下文词语转换为 one-hot 编码向量。
- 投影层 :通过词嵌入矩阵将 one-hot 向量转换为稠密向量,并求平均。
- 输出层 :使用 softmax 函数计算中心词的概率分布。
数学公式推导如下:
- 词嵌入矩阵 $W$ 将 one-hot 向量 $x_i$ 转换为词向量 $v_i$:
$$ v_i = W x_i $$ - 上下文词向量的平均值为:
$$ \bar{v} = \frac{1}{C} \sum_{i=1}^{C} v_i $$ - 输出层的概率分布为:
$$ P(w_t | w_{t-1}, …, w_{t-C}) = \text{softmax}(U \bar{v}) $$
手算实例
假设有一个简单的语料库:["the", "cat", "sat"],窗口大小为 1。
- 构建词汇表:
{"the": 0, "cat": 1, "sat": 2} - 初始化词嵌入矩阵(假设维度为 2):
$$
W = \begin{bmatrix}
0.1 & 0.2 \
0.3 & 0.4 \
0.5 & 0.6
\end{bmatrix}
$$ - 对于上下文
["the", "sat"]预测中心词"cat": - one-hot 向量:
x_the = [1, 0, 0],x_sat = [0, 0, 1] - 词向量:
v_the = [0.1, 0.2],v_sat = [0.5, 0.6] - 平均值:
\bar{v} = [0.3, 0.4] - 输出概率:通过 softmax 计算,选择概率最大的词作为预测结果。
代码实现
import numpy as np
# 初始化参数
vocab_size = 3
embedding_dim = 2
W = np.random.rand(vocab_size, embedding_dim)
U = np.random.rand(embedding_dim, vocab_size)
# CBOW 前向传播
def cbow_forward(context_indices, W, U):
# 获取上下文词向量
context_vectors = W[context_indices, :]
# 计算平均值
avg_vector = np.mean(context_vectors, axis=0)
# 计算输出概率
scores = np.dot(avg_vector, U)
probs = np.exp(scores) / np.sum(np.exp(scores))
return probs
# 示例
context_indices = [0, 2] # "the" 和 "sat"
probs = cbow_forward(context_indices, W, U)
print("预测概率:", probs)
性能考量
- 窗口大小 :较大的窗口捕捉更多上下文信息,但计算成本增加。
- 词向量维度 :维度越高,表达能力越强,但可能过拟合。
- 语料库规模 :大规模语料库能训练出更通用的词向量。
避坑指南
- 初始化问题 :词嵌入矩阵应随机初始化,避免全零。
- 梯度消失 :使用合适的激活函数和优化器。
- 计算效率 :对于大规模词汇表,使用负采样或层次 softmax 加速训练。
延伸思考
- CBOW vs Skip-gram:CBOW 适合高频词,Skip-gram 适合低频词。
- 实际应用 :结合具体任务调整超参数,如窗口大小和向量维度。
启发问题
- 如何评估词嵌入的质量?
- CBOW 模型在处理多义词时有哪些局限性?
- 如何将预训练的词嵌入应用到下游任务中?
正文完
