al+大数据每日学习笔记39

2026年9月15日

基于PyTorch实现CBOW词向量模型

一、前言

在自然语言处理(NLP)任务中,文字无法直接被计算机识别与运算,词向量(Word Embedding)是连接自然语言与深度学习模型的核心桥梁。Word2Vec是经典的轻量级词向量训练算法,主要包含两种模型:**CBOW(连续词袋模型)**和Skip-Gram模型。

其中CBOW模型的核心思想十分简单:通过某个单词的上下文词汇,预测当前中心单词,在训练过程中不断迭代更新权重,最终学习到每一个单词的高维语义向量。

二、CBOW模型核心原理

2.1 核心逻辑

给定固定大小的上下文窗口(本文设置左右各2个单词,共4个上下文词),将上下文单词作为模型输入,中心单词作为预测标签。模型通过学习上下文与中心词的关联关系,将语义相近的单词映射到高维空间中距离相近的向量。

2.2 模型结构

  • 嵌入层(Embedding):将离散的单词索引转换为连续稠密的词向量,是模型的核心权重层,最终训练结果即为该层参数。

  • 隐藏层:通过全连接层对词向量进行特征变换,搭配ReLU激活函数提升模型非线性拟合能力。

  • 输出层:将隐藏层特征映射为词表维度的概率分布,通过log_softmax归一化处理,配合负对数似然损失函数完成训练。

三、环境依赖准备

本次实战所需依赖库均为深度学习常用工具,提前安装即可正常运行代码:

复制代码
pip install numpy tqdm torch

核心依赖说明:

  • torch:搭建、训练深度学习模型核心框架;

  • numpy:数据处理与矩阵运算;

  • tqdm:训练过程进度条可视化。

四、完整代码实现与详细解析

4.1 导入依赖库

复制代码
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from tqdm import tqdm
import numpy as np

4.2 数据集构建

本次使用英文短文作为原始语料,通过固定窗口划分上下文与中心词,构建CBOW训练数据集。同时构建单词与索引的双向映射字典,实现文字与模型可识别数字的转换。

复制代码
# 定义上下文窗口大小:左右各2个单词
CONTEXT_SIZE = 2
# 原始训练语料
raw_text = """We are about to study the idea of a computational process.
Computational processes are abstract beings that inhabit computers.
As they evolve, processes manipulate other abstract things called data.
The evolution of a process is directed by a pattern of rules
called a program. People create programs to direct processes. In effect,
we conjure the spirits of the computer with our spells.""".split()

# 构建词表(去重)
vocab = set(raw_text)
vocab_size = len(vocab)

# 单词-索引双向映射字典
word_to_idx = {word: i for i, word in enumerate(vocab)}
idx_to_word = {i: word for i, word in enumerate(vocab)}

# 构建训练数据集:(上下文词列表, 中心目标词)
data = []
for i in range(CONTEXT_SIZE, len(raw_text) - CONTEXT_SIZE):
    # 拼接左右上下文单词
    context = (
        [raw_text[i - (2-j)] for j in range(2)]
        + [raw_text[i + j + 1] for j in range(CONTEXT_SIZE)]
    )
    target = raw_text[i]
    data.append((context, target))

# 上下文单词转索引张量工具函数
def make_context_vector(context, word_to_idx):
    idxs = [word_to_idx[w] for w in context]
    return torch.tensor(idxs, dtype=torch.long)

4.3 设备自适应配置

自动识别设备硬件,优先使用GPU加速训练,无GPU时自动适配CPU,提升代码通用性。

复制代码
device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
print(f"当前训练设备: {device}")

4.4 搭建CBOW模型

继承PyTorch核心模型基类,定义嵌入层、全连接隐藏层、输出层,实现前向传播逻辑。通过上下文词向量求和聚合语义特征,完成中心词预测。

复制代码
class CBOW(nn.Module):
    def __init__(self, vocab_size, embedding_dim):
        super(CBOW, self).__init__()
        # 词嵌入层:词表大小+词向量维度
        self.embeddings = nn.Embedding(vocab_size, embedding_dim)
        # 隐藏层:词向量映射至128维特征
        self.proj = nn.Linear(embedding_dim, 128)
        # 输出层:特征映射为词表概率分布
        self.output = nn.Linear(128, vocab_size)

    def forward(self, inputs):
        # 上下文词向量求和聚合,适配全连接层输入维度
        embeds = sum(self.embeddings(inputs)).view(1, -1)
        # 非线性特征提取
        out = F.relu(self.proj(embeds))
        # 输出预测分数并归一化对数概率
        out = self.output(out)
        nll_prob = F.log_softmax(out, dim=-1)
        return nll_prob

4.5 模型训练配置与训练循环

配置模型参数、优化器、损失函数,通过多轮迭代完成模型训练,实时记录每轮训练的总损失,监控模型收敛效果。

复制代码
# 初始化模型:词向量维度设置为10
model = CBOW(vocab_size, 10).to(device)
# Adam优化器,学习率0.001
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 损失函数:负对数似然损失,适配log_softmax输出
loss_function = nn.NLLLoss()
# 存储每轮损失值
losses = []

# 模型训练模式
model.train()
# 迭代200轮训练
for epoch in tqdm(range(200), desc="训练进度"):
    total_loss = 0
    # 遍历所有训练样本
    for context, target in data:
        # 数据迁移至对应设备
        context_vector = make_context_vector(context, word_to_idx).to(device)
        target = torch.tensor([word_to_idx[target]]).to(device)

        # 前向传播预测
        predict = model(context_vector)
        # 计算损失
        loss = loss_function(predict, target)

        # 反向传播与参数更新
        optimizer.zero_grad()  # 梯度清零,避免累积
        loss.backward()         # 反向传播求梯度
        optimizer.step()        # 更新模型权重

        total_loss += loss.item()
    losses.append(total_loss)

# 输出训练损失变化
print("每轮训练总损失:", losses)

4.6 模型测试与词向量提取

训练完成后切换模型为评估模式,通过自定义上下文预测中心单词,验证模型效果,同时提取训练完成的词向量矩阵。

复制代码
# 模型评估测试
if __name__ == "__main__":
    # 自定义测试上下文:原句 People create programs to direct
    test_context = ['People', 'create', 'to', 'direct']
    test_vec = make_context_vector(test_context, word_to_idx).to(device)

    # 切换评估模式,关闭训练专属参数
    model.eval()
    # 模型预测
    predict_result = model(test_vec)
    # 取概率最大值对应的单词索引
    max_idx = predict_result.argmax(1).item()
    # 索引还原为单词
    pred_word = idx_to_word[max_idx]

    print(f"上下文词汇:{test_context}")
    print(f"模型预测中心词:{pred_word}")

    # 提取训练完成的词向量矩阵(核心成果)
    word_embedding = model.embeddings.weight.cpu().detach().numpy()
    print(f"\n词向量矩阵维度:{word_embedding.shape}")
    print("词向量矩阵数据:")
    print(word_embedding)

五、核心代码关键点解析

5.1 损失函数搭配逻辑

代码中使用 F.log_softmax + nn.NLLLoss() 组合,效果等价于交叉熵损失函数。先对模型输出做对数概率归一化,再通过负对数似然计算预测值与真实值的误差,是多分类任务的经典搭配。

5.2 训练与评估模式区别

  • model.train():开启训练模式,启用梯度计算、参数更新,适用于模型迭代训练阶段;

  • model.eval():开启评估模式,关闭梯度计算、dropout等训练专属机制,保证预测结果稳定。

5.3 词向量提取逻辑

模型的**embeddings.weight** 即为最终训练的词向量矩阵,维度为[词表数量, 词向量维度]。通过**cpu()、detach()、numpy()**三步处理,将GPU张量转为可直接使用的numpy数组,方便后续保存、可视化和二次运算。

六、实验结果分析

  1. 损失收敛:随着训练轮次增加,每轮总损失持续下降并逐渐趋于平稳,说明模型有效学习到上下文与中心词的语义关联,拟合效果良好。

  2. 预测效果 :输入上下文['People', 'create', 'to', 'direct'],模型可准确预测出中心词programs,符合原始语料语义。

  3. 词向量特征:最终得到的词向量将语义相近的单词映射为相似向量,可用于文本分类、语义匹配、聚类等下游NLP任务。

七、总结与拓展方向

本文实现了极简版CBOW词向量训练模型,完整复现了Word2Vec的核心逻辑,帮助理解词嵌入的训练原理。相较于传统one-hot编码,CBOW得到的稠密词向量解决了维度爆炸、语义缺失的问题,是NLP入门的核心知识点。

相关推荐
Είναι η κοπέλα8 小时前
llama.cpp 与 GGUF 格式:本地大模型的“裸引擎“
开发语言·人工智能·pytorch·python·conda
头发够用的程序员11 小时前
TensorRT 自定义算子插件实战(三):手搓 2×2 最大池化 customMaxpool
人工智能·pytorch·python·深度学习·神经网络·边缘计算·jetson
for_ever_love__1 天前
PyTorch 张量与 autograd——自动求导怎么工作
pytorch·python·深度学习·自动求导
Είναι η κοπέλα2 天前
显存计算与模型选择:你的显卡能跑多大的模型
人工智能·pytorch·python·开源·conda
海天一色y3 天前
模型部署的「通用语」:ONNX 转换
pytorch·onnx
Thomas.Sir3 天前
第26课:工业零部件外观缺陷检测系统:从学术Demo到产线工程的重构实战
pytorch·ai
Zguigo4 天前
【CUDA6】CUDA Stream 是什么,为什么 CUDA 是异步执行,如何正确测量 GPU 时间以及多个任务如何重叠执行
人工智能·pytorch·深度学习
论文复现现场4 天前
RTX 3090 24GB 适合科研吗?单卡论文复现、PyTorch 显存检查与 OOM 排错
人工智能·pytorch·python·深度学习·cuda·rtx3090
论文复现现场5 天前
AutoDL、算家云与公有云 GPU 怎么选?环境复现、计费与断点恢复对比
pytorch·深度学习·云计算·gpu
盘古开天16665 天前
PPO算法代码实战(三):PyTorch从零实现PPO求解CartPole
人工智能·pytorch·算法