深入理解CBOW模型的反向传播机制:从理论到代码实现

1次阅读
没有评论

共计 1991 个字符,预计需要花费 5 分钟才能阅读完成。

image.webp

1. CBOW 模型前向传播基础

CBOW(Continuous Bag-of-Words)是 Word2Vec 的两种经典架构之一,其核心思想是通过上下文词预测中心词。我们先来看一个简单的 4 词窗口示例(左右各 2 个上下文词):

深入理解 CBOW 模型的反向传播机制:从理论到代码实现

  • 输入层:四个 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 梯度计算关键步骤

  1. 首先计算输出层误差:

    e = y - \hat{y}

    其中 $y$ 是真实标签的 one-hot 向量,$\hat{y}$ 是预测概率分布。

  2. 隐藏层到输出层的梯度:

    \frac{\partial J}{\partial W_{output}} = h^T \cdot e

  3. 输入层到隐藏层的梯度:

    \frac{\partial J}{\partial h} = W_{output} \cdot e

  4. 最终词向量更新梯度(以第一个上下文词为例):

    \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. 避坑指南

  1. 维度不匹配:确保输入词向量和输出词向量维度一致
  2. 梯度爆炸:添加梯度裁剪(gradient clipping)
  3. 上下文窗口处理
  4. 遇到句子边界时要特殊处理
  5. 可变窗口大小需要动态调整平均操作
  6. 数值稳定性
  7. softmax 计算使用 log-sum-exp 技巧
  8. 添加微小 epsilon 避免除零错误

6. 延伸思考

尝试实现以下扩展功能:
1. 可变长度的上下文窗口(如 2 - 5 个词)
2. 加入 subsampling 高频词的优化
3. 比较负采样和层次 softmax 的效果差异

理解 CBOW 的反向传播机制是掌握词向量技术的重要一步。建议读者在实现基础版本后,可以进一步尝试优化训练效率和质量。

正文完
 0
评论(没有评论)