共计 2297 个字符,预计需要花费 6 分钟才能阅读完成。
在自然语言处理(NLP)领域,词嵌入技术是许多任务的基础。CBOW(Continuous Bag of Words)模型作为 Word2Vec 的一种实现方式,能够将词语转换为低维稠密向量,捕捉词语之间的语义和语法关系。对于初学者来说,理解并实现 CBOW 模型不仅有助于掌握词嵌入的核心概念,还能为后续的 NLP 任务打下坚实基础。

然而,在实际实现过程中,新手往往会遇到一系列挑战。比如,稀疏矩阵的内存消耗问题、低频词的处理、窗口大小的选择等。这些问题如果不妥善解决,可能会导致模型性能下降甚至无法正常运行。下面,我将分步骤详细讲解如何从零开始实现 CBOW 模型,并分享一些优化技巧和避坑指南。
数据预处理
数据预处理是构建 CBOW 模型的第一步。我们需要将原始文本转换为模型可以处理的数值形式。以下是具体的实现步骤:
- Tokenization:将文本分割成单词或子词单元。
- 构建词汇表 :统计词频,建立词到索引的映射。
以下是 Python 代码示例:
from collections import Counter
import numpy as np
# 示例文本
text = "natural language processing is fun and challenging"
# Tokenization
tokens = text.lower().split()
# 构建词汇表
vocab = Counter(tokens)
vocab = sorted(vocab, key=vocab.get, reverse=True)
word2idx = {word: idx for idx, word in enumerate(vocab)}
idx2word = {idx: word for idx, word in enumerate(vocab)}
print("词汇表:", word2idx)
网络结构搭建
CBOW 模型的核心是一个简单的神经网络,包含一个嵌入层和一个全连接层。以下是使用 PyTorch 实现的代码:
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 = self.embeddings(inputs).mean(dim=1)
out = self.linear(embeds)
return out
# 示例参数
vocab_size = len(vocab)
embedding_dim = 10
model = CBOW(vocab_size, embedding_dim)
训练技巧
训练 CBOW 模型时,学习率调整和负采样是两个重要的优化技巧。以下是实现代码片段:
from tqdm import tqdm
# 负采样实现
def negative_sampling(target, vocab_size, num_neg_samples=5):
neg_samples = []
while len(neg_samples) < num_neg_samples:
sample = np.random.randint(0, vocab_size)
if sample != target:
neg_samples.append(sample)
return neg_samples
# 训练循环
optimizer = optim.SGD(model.parameters(), lr=0.01)
loss_function = nn.CrossEntropyLoss()
for epoch in tqdm(range(100)):
total_loss = 0
for context, target in training_data:
optimizer.zero_grad()
output = model(context)
loss = loss_function(output, target)
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Epoch {epoch}, Loss: {total_loss}")
避坑指南
在实现 CBOW 模型时,有几个常见的陷阱需要注意:
- 选择 embedding_dim:一般来说,较小的维度(如 50-100)适用于小型语料,而较大的维度(如 200-300)适用于大型语料。
- 处理 OOV 词 :可以使用特殊标记(如
<UNK>)来表示词汇表中未出现的词。 - 使用 gensim 验证结果 :gensim 库提供了 Word2Vec 的预实现,可以用来验证自定义实现的正确性。
from gensim.models import Word2Vec
# 使用 gensim 训练 CBOW 模型
gensim_model = Word2Vec(sentences, vector_size=100, window=5, min_count=1, sg=0)
print(gensim_model.wv.most_similar("language"))
开放性问题
最后,留给大家两个开放性问题:
- CBOW 与 Skip-gram 在不同语料规模下的性能对比如何?
- 如何将生成的词嵌入应用到下游任务(如文本分类或机器翻译)中?
希望这篇文章能帮助你理解并实现 CBOW 模型。如果有任何问题或建议,欢迎在评论区交流!
正文完
