基于PyTorch的CBOW模型实现与词向量生成

文章目录

  • 一. CBOW模型详解
    • 1.1 Word2Vec与分布式表示
    • 1.2 CBOW模型原理
      • 数学表达
    • 1.3 网络架构详解
      • 代码中的网络层说明:
    • 1.4 训练目标与优化
    • 1.5 CBOW 与 Skip-gram 比较
    • 1.6 词向量的应用与提取
  • 二. 数据准备与预处理
    • 2.1 语料库与基本参数设置
    • 2.2 构建词汇表
    • 2.3 构建训练数据集
    • 2.4 上下文向量化函数
  • 三. CBOW模型构建
    • 3.1 模型类定义
  • 四. 模型训练
    • 4.1 设备配置与模型初始化
    • 4.2 训练循环
  • 五. 模型测试与词向量提取
    • 5.1 模型测试
    • 5.2 词向量提取与保存

一. CBOW模型详解

1.1 Word2Vec与分布式表示

Word2Vec是Google在2013年提出的一种高效学习词向量的模型,它包含两种主要架构:连续词袋模型(CBOW)和跳字模型(Skip-gram)。这两种模型都基于一个核心思想:“一个词的含义可以通过它周围出现的词来定义”,这被称为分布式假设。

在代码实现中,我们通过构建(context, target)训练对来体现这一思想:

foriinrange(CONTEXT_SIZE,len(raw_text)-CONTEXT_SIZE):context=([raw_text[i-(2-j)]forjinrange(CONTEXT_SIZE)]+[raw_text[i+j+1]forjinrange(CONTEXT_SIZE)])# 获取上下文词target=raw_text[i]# 获取目标词data.append((context,target))# 构建训练样本

与传统one-hot编码相比,Word2Vec生成的词向量具有以下优势:

  • 低维稠密:代码中设置embedding_dim=10,将49维的稀疏one-hot压缩为10维稠密向量
  • 语义信息:相似的词在向量空间中距离较近
  • 数学运算:支持向量运算,如"国王 - 男人 + 女人 ≈ 女王"

1.2 CBOW模型原理

CBOW模型的核心思想是通过上下文词汇预测中心词。具体来说:

输入:上下文窗口中所有词的one-hot表示(或索引)
输出:中心词的概率分布
目标:最大化正确中心词的对数似然

数学表达

给定上下文词序列C = { w t − 2 , w t − 1 , w t + 1 , w t + 2 } C = \{w_{t-2}, w_{t-1}, w_{t+1}, w_{t+2}\}C={wt2,wt1,wt+1,wt+2},CBOW模型试图预测中心词w t w_twt

P ( w t ∣ C ) = exp ⁡ ( v w t T ⋅ v ˉ C ) ∑ w ∈ V exp ⁡ ( v w T ⋅ v ˉ C ) P(w_t | C) = \frac{\exp(v_{w_t}^T \cdot \bar{v}_C)}{\sum_{w \in V} \exp(v_w^T \cdot \bar{v}_C)}P(wtC)=wVexp(vwTvˉC)exp(vwtTvˉC)

其中:

  • v ˉ C \bar{v}_CvˉC是上下文词向量的平均(或求和)
  • v w v_{w}vw是词w ww的输出向量
  • V VV是词汇表

在代码中,这一原理体现在CBOW模型的forward方法:

defforward(self,inputs):embeds=sum(self.embeddings(inputs)).view(1,-1)# 对上下文词向量求和out=F.relu(self.proj(embeds))out=self.output(out)nl_l_prob=F.log_softmax(out,dim=-1)# 计算对数概率returnnl_l_prob

1.3 网络架构详解

CBOW模型通常包含以下三层:

  1. 输入层:上下文词的索引表示,代码中使用make_context_vector函数转换
  2. 投影层(隐藏层):共享的嵌入矩阵,将索引映射为稠密词向量
  3. 输出层:线性层将隐藏层表示映射回词汇表空间

代码中的网络层说明:

classCBOW(nn.Module):def__init__(self,vocab_size,embedding_dim):super(CBOW,self).__init__()self.embeddings=nn.Embedding(vocab_size,embedding_dim)# 投影层self.proj=nn.Linear(embedding_dim,128)# 中间层self.output=nn.Linear(128,vocab_size)# 输出层

1.4 训练目标与优化

CBOW的训练目标是最大化给定上下文时正确中心词的条件概率:

L = ∑ t = 1 T log ⁡ P ( w t ∣ w t − m , . . . , w t − 1 , w t + 1 , . . . , w t + m ) \mathcal{L} = \sum_{t=1}^{T} \log P(w_t | w_{t-m}, ..., w_{t-1}, w_{t+1}, ..., w_{t+m})L=t=1TlogP(wtwtm,...,wt1,wt+1,...,wt+m)

在代码中,我们使用负对数似然损失(NLLLoss):

loss_function=nn.NLLLoss()# 负对数似然损失# 在训练循环中train_predict=model(context_vector)loss=loss_function(train_predict,target)# 计算损失

训练过程采用反向传播和Adam优化器:

optimizer=optim.Adam(model.parameters(),lr=0.001)# Adam优化器# 反向传播optimizer.zero_grad()# 梯度清零loss.backward()# 反向传播optimizer.step()# 参数更新

1.5 CBOW 与 Skip-gram 比较

特性CBOWSkip-gram代码体现
训练速度更快较慢forward中求和操作计算效率高
输入输出多对一一对多多个上下文词预测一个中心词
上下文利用求和/平均独立处理使用sum()聚合上下文信息

1.6 词向量的应用与提取

训练完成后,可以提取词向量用于各种NLP任务。代码中通过以下方式提取和保存词向量:

# 获取Embedding层的权重矩阵W=model.embeddings.weight.cpu().detach().numpy()# 构建词向量字典word_2vec={}forwordinword_to_idx.keys():word_2vec[word]=W[word_to_idx[word],:]# 保存词向量np.savez(r'word2vec实现.npz',file_1=W)

这些词向量可以应用于:

  1. 语义相似度计算:通过余弦相似度比较词向量
  2. 文本分类:作为特征输入分类器
  3. 命名实体识别:提供上下文语义信息

二. 数据准备与预处理

2.1 语料库与基本参数设置

首先,需要定义上下文窗口的大小并准备训练语料:

importtorchimporttorch.nnasnn# 神经网络importtorch.nn.functionalasFimporttorch.optimasoptim#fromtqdmimporttqdm,trange# 显示进度条importnumpyasnp# 设置词左边和右边选择的个数(即上下文词汇个数)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()# 中文的语句,你可以选择分词,也可以选择分字

代码分析

  • CONTEXT_SIZE = 2:定义上下文窗口大小为2,即每个中心词考虑左右各2个上下文词
  • raw_text:示例英文语料库,使用.split()方法按空格分词
  • 注释提示对于中文语料,可以选择分词或分字处理

2.2 构建词汇表

vocab=set(raw_text)# 集合、词库,里面内容去重vocab_size=len(vocab)word_to_idx={word:ifori,wordinenumerate(vocab)}# for循环的复合写法,第1次循环,i得到的索引号,word 第1个单词idx_to_word={i:wordfori,wordinenumerate(vocab)}

代码分析

  • vocab = set(raw_text):创建词汇集合,自动去除重复单词
  • vocab_size = len(vocab):获取词汇表大小
  • word_to_idx:创建单词到索引的映射字典
  • idx_to_word:创建索引到单词的映射字典,用于后续的反向查找

2.3 构建训练数据集

data=[]# 获取上下文词,将上下文词作为输入,目标词作为输出。构建训练数据集。foriinrange(CONTEXT_SIZE,len(raw_text)-CONTEXT_SIZE):# (2, 60)context=([raw_text[i-(2-j)]forjinrange(CONTEXT_SIZE)]+[raw_text[i+j+1]forjinrange(CONTEXT_SIZE)])# 获取上下文词 (['we', 'are', 'to', 'study'])target=raw_text[i]# 获取目标词'about'data.append((context,target))# 将上下文词和目标词保存到data中[((['we', 'are', 'to', 'study']), 'about']

代码分析

  • 循环从第3个词开始到倒数第3个词结束(索引从0开始),确保每个中心词都有完整的上下文
  • context列表推导式:前部分获取左侧上下文词,后部分获取右侧上下文词
  • target:当前中心词
  • 最终data列表包含多个(context, target)元组

2.4 上下文向量化函数

defmake_context_vector(context,word_to_ix):# 将上下文词转换为one-hotidxs=[word_to_ix[w]forwincontext]returntorch.tensor(idxs,dtype=torch.long)# 强制类型的转换,将列表print(make_context_vector(data[0][0],word_to_idx))# 示例

代码分析

  • make_context_vector函数:将单词列表转换为对应的索引列表
  • 返回PyTorch张量,数据类型为torch.long,适合作为Embedding层的输入
  • 打印示例:展示如何将上下文词转换为索引张量

三. CBOW模型构建

3.1 模型类定义

classCBOW(nn.Module):# 神经网络def__init__(self,vocab_size,embedding_dim):super(CBOW,self).__init__()# 父类的初始化self.embeddings=nn.Embedding(vocab_size,embedding_dim)# vocab_size:词嵌入的one-hot大小,embedding_dim:压缩后的词嵌入大小self.proj=nn.Linear(embedding_dim,128)#self.output=nn.Linear(128,vocab_size)defforward(self,inputs):embeds=sum(self.embeddings(inputs)).view(1,-1)# cnnout=F.relu(self.proj(embeds))# nn.relu()激活层out=self.output(out)nl_l_prob=F.log_softmax(out,dim=-1)# softmax交叉熵。returnnl_l_prob

代码分析

初始化方法__init__参数

  • vocab_size:词汇表大小,即one-hot向量的维度
  • embedding_dim:词嵌入的维度,将高维one-hot向量压缩到此维度

网络层说明

  • self.embeddings:Embedding层,将单词索引映射为稠密向量
  • self.proj:线性投影层,将词向量维度从embedding_dim映射到128维
  • self.output:输出层,将128维特征映射回词汇表大小维度

前向传播forward方法

  • inputs:上下文词的索引张量
  • sum(self.embeddings(inputs)):对上下文词的词向量求和,体现CBOW的核心思想
  • .view(1, -1):调整张量形状为[1, embedding_dim]
  • F.relu:ReLU激活函数,引入非线性
  • F.log_softmax:log_softmax函数,计算对数概率,与NLLLoss配合使用

四. 模型训练

4.1 设备配置与模型初始化

# 模型在cuda训练device="cuda"iftorch.cuda.is_available()else"mps"iftorch.backends.mps.is_available()else"cpu"print(device)model=CBOW(vocab_size,embedding_dim=10).to(device)# 语料库中一共有49个单词,[000000...1]49->[ ... ]300optimizer=optim.Adam(model.parameters(),lr=0.001)# 优化器

代码分析

  • device:自动检测可用设备(CUDA、MPS或CPU)
  • model:创建CBOW模型实例,词嵌入维度设为10
  • optimizer:使用Adam优化器,学习率为0.001

4.2 训练循环

losses=[]# 存储损失的集合loss_function=nn.NLLLoss()# NLLLoss损失函数(当分类列表非常多的情况),将多个类别分别分成0、1两个类别。这里和log_softmax合在一起就是一个model.train()# 不代表开始训练,模型具备训练的能力,设置一个可写的权限??forepochintqdm(range(200)):# 开始训练total_loss=0forcontext,targetindata:context_vector=make_context_vector(context,word_to_idx).to(device)target=torch.tensor([word_to_idx[target]]).to(device)# 开始前向传播train_predict=model(context_vector)# 可以不写forward,torch的内置功能,loss=loss_function(train_predict,target)# 计算真实值和预测值之间的差距# 反向传播optimizer.zero_grad()# 梯度值清零loss.backward()# 反向传播计算得到每个参数的梯度值optimizer.step()# 根据梯度更新网络参数total_loss+=loss.item()losses.append(total_loss)print(losses)

代码分析

  • losses:记录每个epoch的总损失
  • loss_function:负对数似然损失,与log_softmax配合使用
  • model.train():设置模型为训练模式,启用dropout和batch normalization
  • tqdm(range(200)):使用tqdm包装循环,显示训练进度条
  • 内部循环:遍历所有训练样本
  • make_context_vector:将上下文转换为索引张量
  • torch.tensor([word_to_idx[target]]):将目标词转换为索引张量
  • model(context_vector):前向传播获取预测值
  • loss.backward():反向传播计算梯度
  • optimizer.step():更新模型参数

五. 模型测试与词向量提取

5.1 模型测试

# 测试# context = ['People', 'create', 'to', 'direct'] # People create programs to directcontext=["spirits","of","the","computer"]# spirits of the computercontext_vector=make_context_vector(context,word_to_idx).to(device)# 预测的值model.eval()# 进入到测试模式predict=model(context_vector)max_idx=predict.argmax(1)# dim=1表示每一行中的最大值对应的索引号,dim=0表示每一列中的最大值对应的索引号

代码分析

  • model.eval():设置模型为评估模式,禁用dropout和batch normalization
  • predict.argmax(1):获取预测概率最大值的索引,即预测的中心词

5.2 词向量提取与保存

# 获取词向量,这个Embedding就是我们需要的问题。他只是一个模型的一个中间过程print("CBOW embedding weight=",model.embeddings.weight)# GPUW=model.embeddings.weight.cpu().detach().numpy()# .detach(); 这个方法会创建一个新的Tensor,它和原来的Tensor共享数据,但是不会追踪梯度。# 这意味着这个新的Tensor不会参与梯度的反向传播,这对于防止在计算梯度时意外修改某些参数很有用。print(W)# 生成词嵌入字典,即{单词1:词向量1,单词2:词向量2...}的格式word_2vec={}forwordinword_to_idx.keys():# 词向量矩阵中某个词的索引所对应的那一列即为所该词的词向量word_2vec[word]=W[word_to_idx[word],:]print("end")# 保存训练后的词向量为npz文件'''numpy W 处理矩阵的速度非常快,方便后期其他人项目,要继续使用np.savez(r'word2vec实现.npz',file_1=W)data=np.load(r'word2vec实现.npz')print(data.files)

代码分析

  • model.embeddings.weight:获取Embedding层的权重矩阵,即所有词的词向量
  • .cpu().detach().numpy():将张量转移到CPU,脱离计算图,转换为numpy数组
  • word_2vec字典:构建{单词: 词向量}的映射关系
  • np.savez:将词向量矩阵保存为npz格式,便于后续加载和使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1131285.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于大数据的颈椎病预防交流与数据可视化分析平台设计与实现

摘 要 现代快节奏生活中,长时间低头用电子设备、不良坐姿及运动不足等现象普遍,致颈椎病发病率激增,严重影响生活工作。公众健康意识提升,对颈椎病防治关注度高,却受限于传统方法,亟需科学个性化方案。大数…

【力扣hot100题】合并区间(9)

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。示例 1:输入:intervals [[1,3],[…

DeepBI 帮亚马逊卖家突破销售瓶颈,暴增近20倍销量!

做亚马逊的你,是不是也有这种无力感?店铺销售规模卡在瓶颈难突破,广告烧得凶,利润却薄如纸;熬夜调关键词、算数据,销量还是原地踏步,甚至越优化越亏?深圳的家具类卖家陈总也曾深陷这…

交互式教学:将阿里通义Z-Image-Turbo集成到Jupyter Notebook的秘诀

交互式教学:将阿里通义Z-Image-Turbo集成到Jupyter Notebook的秘诀 作为一名数据科学讲师,我经常需要在课堂上演示AI图像生成技术。传统的命令行工具或独立应用往往让学生感到陌生,而Jupyter Notebook作为数据科学教学的标准环境,…

连锁店管理力不从心?让智能体接管30%重复工作

在连锁商业规模持续扩张的当下,一个核心矛盾日益凸显:消费者对个性化、即时性体验的需求不断升级,而传统依赖店长经验与人工巡检的运营模式,在成本、效率和一致性上渐趋乏力。门店越开越多,管理半径越来越广&#xff0…

模型压缩魔法:让Z-Image-Turbo在消费级GPU上流畅运行

模型压缩魔法:让Z-Image-Turbo在消费级GPU上流畅运行 你是否想在配备中等性能显卡的PC上运行Z-Image-Turbo,却被原始模型的显存要求劝退?本文将介绍如何通过模型压缩技术,让这个强大的图像生成模型在消费级GPU上流畅运行。目前CSD…

AI+教育创新:Z-Image-Turbo在教学场景中的快速部署

AI教育创新:Z-Image-Turbo在教学场景中的快速部署 作为一名教育科技创业者,你是否想过将AI图像生成技术融入在线课程?无论是自动生成教学插图、创建个性化学习素材,还是让学生通过文字描述快速可视化知识点,Z-Image-Tu…

一份精美的Excel,究竟需要多久?

作为一名财务分析师,我每天超过60%的工作时间都在与Excel打交道。从最初简单的数据录入,到如今复杂的财务模型构建,这看似普通的软件已经陪伴了我八年职业生涯。但直到最近,我才真正理解“精美的Excel”意味着什么,以及…

ACPI!PciConfigSpaceHandlerWorker函数中的hal!HalGetBusDataByOffset----重要

ACPI!PciConfigSpaceHandlerWorker函数中的hal!HalGetBusDataByOffset 1: kd> g Breakpoint 14 hit eax00000000 ebx89d376f8 ecx00000100 edx89ddf118 esi00000000 edi00000000 eip804f25ee espf791abdc ebpf791ac48 iopl0 nv up ei pl zr na pe nc cs0008 ss0010…

AI生成内容版权探索:Z-Image-Turbo云端环境下的水印集成

AI生成内容版权探索:Z-Image-Turbo云端环境下的水印集成 随着AI生成图像的普及,如何有效标识版权成为内容平台亟需解决的问题。Z-Image-Turbo作为新一代开源图像生成模型,凭借亚秒级生成速度和出色的中文理解能力,正被广泛应用于…

Z-Image-Turbo多租户方案:云端环境下的资源共享与隔离

Z-Image-Turbo多租户方案:云端环境下的资源共享与隔离实战指南 在AI图像生成领域,Z-Image-Turbo凭借其亚秒级的生成速度和出色的图像质量,正成为越来越多SaaS服务商的首选技术方案。但当企业试图将其部署为多租户服务时,资源竞争和…

揭秘Z-Image-Turbo:如何用阿里云镜像1小时搭建高性能AI画室

揭秘Z-Image-Turbo:如何用阿里云镜像1小时搭建高性能AI画室 作为一名数字媒体课程的讲师,我最近一直在寻找一种简单高效的方式,让学生们能够亲身体验AI图像生成的魅力。学校的计算资源有限,本地部署复杂的AI模型对新手来说门槛太高…

图书管理系统的设计与实现

图书管理系统的设计与实现 【摘 要】随着信息技术的发展,信息系统在社会管理活动中发挥着重要的作用。图书管理系统的是当今校园信息化的重要组成部分,为丰富学生的课余文化生活,给广大的同学带来图书借阅的便利,闽南科技学院图书…

头部企业如何借AI HR破局2026人才战略新棋局

在刚刚过去的2025年,AI在人力资源领域热度只增不减。从智能招聘到数字员工,从预测分析到技能图谱,前沿案例令人目不暇接。仿佛一夜间,人力资源部门就要从职能支持,跃升为企业的战略大脑。但当目光从行业峰会的PPT拉回企…

从DALL·E到Z-Image-Turbo:低成本替代方案的快速迁移

从DALLE到Z-Image-Turbo:低成本替代方案的快速迁移 如果你正在使用商业AI绘画API(如DALLE),但希望寻找一个开源替代方案来降低成本,Z-Image-Turbo可能是一个值得尝试的选择。本文将帮助你快速验证Z-Image-Turbo是否能满…

基于STM32单片机智能交流电流检测监测互感器设计DIY20-572

本设计由STM32F103C8T6单片机核心板电路LCD1602液晶显示电路TA1005M交流电流检测电路组成。1、LCD1602液晶实时显示交流电流值。

假期休闲不重样,靠谱短剧天天有新剧

看短剧是真香:解锁高效休闲新方式在快节奏的现代生活中,寻找一种高效、便捷的休闲放松方式,成为许多人的共同需求。而刷短剧,正以其“短平快”的叙事节奏和强情节的吸引力,迅速俘获了广大用户的心,成为填充…

文化遗产数字化:AI辅助的古迹复原图像生成

文化遗产数字化:AI辅助的古迹复原图像生成实践指南 作为一名文物保护工作者,你是否曾面对残垣断壁的古迹,想象它们当年的辉煌模样?如今通过文化遗产数字化:AI辅助的古迹复原图像生成技术,我们可以借助Stabl…

全网最全10个AI论文软件,专科生毕业论文必备!

全网最全10个AI论文软件,专科生毕业论文必备! AI 工具如何助力论文写作,专科生也能轻松应对 在当今学术写作日益数字化的背景下,AI 工具正逐步成为学生和研究者不可或缺的助手。尤其是对于专科生而言,面对毕业论文的压…