共计 2303 个字符,预计需要花费 6 分钟才能阅读完成。
背景介绍
词嵌入是自然语言处理(NLP)中的一项核心技术,它将词语映射到一个连续的向量空间中,使得语义相似的词在向量空间中的距离也相近。词嵌入技术广泛应用于文本分类、机器翻译、情感分析等任务中。CBOW(Continuous Bag of Words)模型是一种经典的词嵌入方法,它通过上下文词语预测中心词来学习词向量。

CBOW 模型原理解析
CBOW 模型的核心思想是利用上下文词语来预测中心词。给定一个中心词 $w_t$ 和其上下文窗口大小为 $m$,模型的目标是最大化以下概率:
$$ P(w_t | w_{t-m}, …, w_{t-1}, w_{t+1}, …, w_{t+m}) $$
模型的结构可以分为以下几个部分:
- 输入层 :将上下文词语的 one-hot 向量输入模型。
- 隐藏层 :通过词嵌入矩阵将 one-hot 向量转换为词向量,并求平均值。
- 输出层 :通过另一个矩阵将隐藏层的输出转换为词汇表的概率分布。
手写实现步骤
1. 数据预处理与上下文窗口构建
首先,我们需要对文本进行预处理,包括分词、构建词汇表等。然后,我们需要构建上下文窗口,即对于每个中心词,收集其前后 $m$ 个词作为上下文。
2. 初始化词嵌入矩阵
词嵌入矩阵 $W$ 的维度为 $V \times d$,其中 $V$ 是词汇表的大小,$d$ 是词向量的维度。我们可以随机初始化这个矩阵。
import numpy as np
vocab_size = 10000 # 词汇表大小
embedding_dim = 300 # 词向量维度
W = np.random.randn(vocab_size, embedding_dim) * 0.01
3. 前向传播计算
对于每个上下文窗口,我们将上下文词语的 one-hot 向量与词嵌入矩阵相乘,得到词向量,然后求平均值作为隐藏层的输出。
context_words = [1, 2, 3] # 上下文词语的索引
context_vectors = W[context_words, :]
hidden_layer = np.mean(context_vectors, axis=0)
4. 损失函数定义
CBOW 模型通常使用交叉熵损失函数来衡量预测结果与真实标签之间的差异。
$$ L = -\sum_{i=1}^{V} y_i \log(\hat{y}_i) $$
其中 $y_i$ 是真实标签的 one-hot 向量,$\hat{y}_i$ 是模型的预测概率。
5. 反向传播与矩阵更新
通过反向传播算法计算梯度,并使用梯度下降法更新词嵌入矩阵。
learning_rate = 0.01
gradient = ... # 计算梯度
W -= learning_rate * gradient
完整 Python 代码实现
以下是一个简单的 CBOW 模型的实现代码:
import numpy as np
class CBOW:
def __init__(self, vocab_size, embedding_dim):
self.vocab_size = vocab_size
self.embedding_dim = embedding_dim
self.W1 = np.random.randn(vocab_size, embedding_dim) * 0.01
self.W2 = np.random.randn(embedding_dim, vocab_size) * 0.01
def forward(self, context_words):
hidden_layer = np.mean(self.W1[context_words, :], axis=0)
output_layer = np.dot(hidden_layer, self.W2)
return output_layer
def train(self, context_words, target_word, learning_rate=0.01):
# 前向传播
hidden_layer = np.mean(self.W1[context_words, :], axis=0)
output_layer = np.dot(hidden_layer, self.W2)
softmax = np.exp(output_layer) / np.sum(np.exp(output_layer))
# 计算梯度
grad_output = softmax
grad_output[target_word] -= 1
grad_W2 = np.outer(hidden_layer, grad_output)
grad_hidden = np.dot(self.W2, grad_output)
grad_W1 = np.zeros_like(self.W1)
for word in context_words:
grad_W1[word, :] += grad_hidden / len(context_words)
# 更新矩阵
self.W1 -= learning_rate * grad_W1
self.W2 -= learning_rate * grad_W2
性能优化建议
- 向量化计算 :尽量使用矩阵运算代替循环,以提高计算效率。
- 学习率调整 :可以使用动态学习率,如随着训练轮数增加逐渐减小学习率。
- 批量训练 :将多个样本一起训练,可以减少计算量。
常见问题与解决方案
- 梯度消失 :可以通过使用更好的初始化方法(如 Xavier 初始化)来缓解。
- 稀疏矩阵处理 :可以使用稀疏矩阵存储和计算来节省内存。
延伸思考
- 更大的语料库 :可以考虑使用分布式训练或增量训练来处理更大的语料库。
- 预训练词向量 :可以使用预训练的词向量作为初始值,加速训练过程。
进一步学习的资源推荐
通过本文的学习,你应该已经掌握了 CBOW 模型的基本原理和实现方法。希望你能在此基础上进一步探索词嵌入技术的更多应用和优化方法。
