共计 1761 个字符,预计需要花费 5 分钟才能阅读完成。
背景介绍
CBOW(Continuous Bag-of-Words)模型是 Word2Vec 的两种主要架构之一,广泛应用于自然语言处理中的词向量学习。与 Skip-gram 模型不同,CBOW 通过上下文词预测当前词,特别适合处理小型数据集。

在 CBOW 模型中,损失函数的设计至关重要,它直接影响模型的学习效率和词向量的质量。一个优秀的损失函数不仅能加速训练过程,还能提升词向量的语义表达能力。
数学原理
CBOW 模型的标准 Softmax 损失函数定义如下:
$$L = -\log p(w_o|w_c) = -\log \left(\frac{\exp(v_{w_o}^T v_{w_c})}{\sum_{i=1}^V \exp(v_{w_i}^T v_{w_c})} \right)$$
其中:
– $w_o$ 是目标词
– $w_c$ 是上下文词
– $V$ 是词汇表大小
– $v_{w_o}$ 和 $v_{w_c}$ 分别是目标词和上下文词的向量表示
这个公式虽然直观,但计算复杂度为 $O(V)$,当词汇表很大时(例如百万级),计算会变得极其昂贵。
优化方案
负采样(Negative Sampling)
负采样通过只更新少数负样本(而非整个词汇表)来近似完整的 Softmax。其损失函数为:
$$L = -\log \sigma(v_{w_o}^T v_{w_c}) – \sum_{k=1}^K \log \sigma(-v_{w_k}^T v_{w_c})$$
其中 $K$ 是负样本数量,通常 5 -20 个就足够。
层次 Softmax(Hierarchical Softmax)
层次 Softmax 利用二叉树结构(通常是霍夫曼树)将复杂度从 $O(V)$ 降到 $O(\log V)$。每个词对应树的一个叶子节点,预测变为沿着路径的概率乘积。
代码实现
import torch
import torch.nn as nn
import torch.optim as optim
class CBOW(nn.Module):
def __init__(self, vocab_size, embedding_dim):
super(CBOW, self).__init__()
self.embeddings = nn.Embedding(vocab_size, embedding_dim)
self.linear = nn.Linear(embedding_dim, vocab_size)
def forward(self, inputs):
embeds = torch.mean(self.embeddings(inputs), dim=1)
out = self.linear(embeds)
return out
# 训练循环示例
model = CBOW(vocab_size=10000, embedding_dim=300)
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.1)
for epoch in range(100):
for batch in dataloader:
context, target = batch
optimizer.zero_grad()
output = model(context)
loss = criterion(output, target)
loss.backward()
optimizer.step()
性能对比
| 方法 | 训练速度 | 内存占用 | 词向量质量 |
|---|---|---|---|
| 标准 Softmax | 慢 | 高 | 最好 |
| 负采样 | 快 | 低 | 较好 |
| 层次 Softmax | 中等 | 中等 | 好 |
避坑指南
- 学习率设置 :负采样通常需要更大的学习率(0.1 左右),而层次 Softmax 需要更小的学习率(0.01 左右)。
- 负采样数量 :5-20 个负样本通常足够,太多会降低训练速度,太少会影响词向量质量。
- 高频词处理 :对高频词进行下采样(如 $P(w_i)=1-\sqrt{t/f(w_i)}$)可以提升罕见词的质量。
总结与思考
选择损失函数时需要权衡计算效率和词向量质量。对于大型词汇表,负采样通常是最佳选择;当需要最高质量的词向量且资源充足时,可以考虑标准 Softmax;层次 Softmax 则在两者之间提供了良好的平衡。
在实际应用中,建议先使用负采样进行快速原型开发,再根据需要尝试其他方法。同时,不同的任务(如词类比 vs. 词相似度)可能对损失函数的选择有不同的要求,这需要通过实验来确定最佳方案。
