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入门的核心知识点。

相关推荐
ysu_03146 小时前
PINNs的参数反演——从“正问题”到“逆问题”的工程改造
人工智能·pytorch·深度学习·mcmc·参数反演·逆问题·darcy流
玫幽倩9 小时前
2026第二届湾区杯网络安全大赛决赛(AI专项赛道静态题wp)
pytorch·python·ai·agent·ctf·rag·湾区杯
论文复现现场11 小时前
课程作业要跑 PyTorch 训练,学校机房不够用去哪租?云 GPU 选型、环境迁移与防丢数据指南
人工智能·pytorch·深度学习·云计算·gpu·cuda
崖边看雾11 小时前
深度学习——PyTorch 实现 CBOW 词向量模型:从数据预处理到训练与保存
pytorch·深度学习
ysu_03141 天前
边界条件的硬约束与软约束——从试函数构造到谱分析诊断
人工智能·pytorch·深度学习·物理信息神经网络·pinns·边界条件·ntk
会飞锦鲤1 天前
基于 Mask R-CNN 的药片缺陷检测系统
人工智能·pytorch·python·神经网络·resnet-50
马剑威(威哥爱编程)1 天前
【共创稿事节】HarmonyOS 7 Agent A2A 实战:让日程智能体和打车智能体自己谈成一单
pytorch·深度学习·harmonyos
内蒙深海大鲨鱼1 天前
8-13课程归纳
pytorch
派大_星1 天前
基于 PyTorch 实现 CBOW 词向量模型
pytorch