当前位置: 首页 > news >正文

word2vec模型案例

代码实现:

import torch.optim as optim
from tqdm import tqdm, trange
import numpy as np
import torch
from torch import nn
import torch.nn.functional as FCONTEXT_SIZE = 2raw_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):  # (2, 60)context = ([raw_text[i - (2-j)] for j in range(CONTEXT_SIZE)]          # [we,are]+ [raw_text[i + j + 1] for j in range(CONTEXT_SIZE)]       # [to,study])target = raw_text[i]  # 目标词data.append((context, target))def make_context_vector(context,word_to_idx):idxs = [word_to_idx[x] for x in context]return torch.tensor(idxs,dtype=torch.long)
print(make_context_vector(data[0][0],word_to_idx))device = 'cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_available() else 'cpu'
print(device)class CBOW(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)def forward(self,inputs):embeds = sum(self.embeddings(inputs)).view(1,-1)out = F.relu(self.proj(embeds))out = self.output(out)null_plob = F.log_softmax(out,dim=-1)return null_plobmodel = CBOW(vocab_size,10).to(device)
optimizer = optim.Adam(model.parameters(),lr=0.001)
losses = []
loss_function = nn.NLLLoss()
model.train()
for epoch in tqdm(range(200)):total_loss = 0size = 0for context,target in data: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)loss = loss_function(train_predict,target)optimizer.zero_grad()loss.backward()optimizer.step()total_loss += loss.item()size += 1avg_loss = total_loss / sizeprint(avg_loss)context = ['People', 'create', 'to', 'direct']  # People create programs to direct
context_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表示每一列中的最大值对应的索引号# 获取词向量,这个Embedding就是我们需要的词向量,他只是一个模型的一个中间过程
print("CBOW embedding weight=", model.embeddings.weight)  # GPU
W = model.embeddings.weight.cpu().detach().numpy()  # .detach(): 这个方法会创建一个新的Tensor,它和原来的Tensor共享# 这意味着这个新的Tensor不会参与梯度的反向传播,这对于防止在计算梯度时意外修改某些参数很有用。
print(W)# 生成词嵌入字典,即{单词1:词向量1,单词2:词向量2...}的格式
word_2_vec = {}
for word in word_to_idx.keys():# 词向量矩阵中某个词的索引所对应的那一列即为该词的词向量word_2_vec[word] = W[word_to_idx[word], :]
print('jiesu')# 保存训练后的词向量为npz文件,numpy处理矩阵的速度非常快,方便后期其他操作
np.savez('word2vec实现.npz', file_1=W)
data = np.load('word2vec实现.npz')
print(data.files)

这段代码是一个基于 PyTorch 实现的CBOW(连续词袋模型) 示例,用于训练词向量(类似 Word2Vec 的核心功能)。下面逐步分析代码:

一、核心功能概述

代码通过一段示例文本训练 CBOW 模型,最终得到每个单词的低维向量表示(词嵌入)。CBOW 的核心思想是:用一个单词的上下文(周围单词)预测该单词本身,通过这个过程让模型学习到单词的语义向量。

二、代码分步解析

1. 导入依赖库
import torch.optim as optim  # PyTorch优化器
from tqdm import tqdm, trange  # 进度条工具
import numpy as np  # 数值计算
import torch
from torch import nn  # 神经网络模块
import torch.nn.functional as F  # 神经网络函数(如激活函数、softmax等)

这些是 PyTorch 深度学习和数据处理的基础库,tqdm用于显示训练进度,提高可视化体验。

2. 数据预处理
(1)定义超参数和原始文本
CONTEXT_SIZE = 2  # 上下文窗口大小:每个目标词的前后各取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 个词作为上下文(共 4 个词)。

(2)构建词汇表
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)}

计算机无法直接处理文本,需将单词转为数字索引。这里通过两个字典实现单词和索引的双向映射。

(3)构建训练数据(上下文→目标词)
data = []
# 遍历文本,为每个位置的词构建上下文和目标
for i in range(CONTEXT_SIZE, len(raw_text) - CONTEXT_SIZE):# 上下文 = 目标词前面2个词 + 后面2个词context = ([raw_text[i - (2-j)] for j in range(CONTEXT_SIZE)]  # 前面2个词(如i=2时,取i-2, i-1)+ [raw_text[i + j + 1] for j in range(CONTEXT_SIZE)]  # 后面2个词(如i=2时,取i+1, i+2))target = raw_text[i]  # 目标词(当前位置的词)data.append((context, target))

例如,对于句子片段We are about to study

  • 当目标词是about(索引 = 2)时,上下文是前面的We, are和后面的to, study,即(["We", "are", "to", "study"], "about")

data最终是一个列表,每个元素是(上下文单词列表, 目标词)的元组,用于模型训练。

(4)上下文转向量函数
def make_context_vector(context, word_to_idx):# 将上下文单词转为对应的索引,再封装成PyTorch张量idxs = [word_to_idx[x] for x in context]return torch.tensor(idxs, dtype=torch.long)

将上下文的单词列表(如["We", "are", "to", "study"])转为索引张量(如[10, 5, 3, 8]),作为模型的输入。

3. 设备配置
device = 'cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_available() else 'cpu'
print(device)

自动选择训练设备:优先用 NVIDIA GPU(cuda),其次 Apple GPU(mps),最后用 CPU,以加速训练。

4. CBOW 模型定义
class CBOW(nn.Module):def __init__(self, vocab_size, embedding_dim):super(CBOW, self).__init__()# 嵌入层:将单词索引转为低维向量(vocab_size→embedding_dim)self.embeddings = nn.Embedding(vocab_size, embedding_dim)# 投影层:将嵌入向量映射到128维self.proj = nn.Linear(embedding_dim, 128)# 输出层:将128维向量映射到词汇表大小(预测目标词)self.output = nn.Linear(128, vocab_size)def forward(self, inputs):# 1. 上下文嵌入:获取输入的每个单词的嵌入向量,求和(上下文向量的平均/求和代表上下文语义)embeds = sum(self.embeddings(inputs)).view(1, -1)  # 形状:(1, embedding_dim)# 2. 投影层+激活函数out = F.relu(self.proj(embeds))  # 形状:(1, 128)# 3. 输出层+log_softmax(将输出转为概率分布的对数)out = self.output(out)  # 形状:(1, vocab_size)log_probs = F.log_softmax(out, dim=-1)  # 沿最后一维计算softmax并取对数return log_probs

模型核心逻辑:

嵌入层(embeddings):是训练的核心,其权重就是最终的词向量(每个单词对应一行向量)。

前向传播:将上下文单词的嵌入向量求和(代表上下文的整体语义),通过两层线性网络,最终输出对目标词的概率分布(对数形式)。

5. 模型训练
# 初始化模型(词汇表大小,嵌入维度10),并移动到指定设备
model = CBOW(vocab_size, 10).to(device)
# 优化器:Adam(常用的自适应学习率优化器)
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 损失函数:NLLLoss(负对数似然损失,配合log_softmax使用,等价于交叉熵损失)
loss_function = nn.NLLLoss()losses = []  # 记录损失
model.train()  # 切换到训练模式# 训练200个epoch
for epoch in tqdm(range(200)):total_loss = 0  # 总损失size = 0  # 样本数for context, target in data:# 1. 准备数据:上下文向量和目标词索引(均移动到设备)context_vector = make_context_vector(context, word_to_idx).to(device)target = torch.tensor([word_to_idx[target]]).to(device)  # 目标词的索引# 2. 模型预测predict = model(context_vector)# 3. 计算损失loss = loss_function(predict, target)# 4. 反向传播+参数更新optimizer.zero_grad()  # 清空梯度loss.backward()  # 计算梯度optimizer.step()  # 更新参数total_loss += loss.item()  # 累加损失(转为Python数值)size += 1# 计算并打印每个epoch的平均损失avg_loss = total_loss / sizeprint(f"Epoch {epoch+1}, Average Loss: {avg_loss}")losses.append(avg_loss)

训练过程流程:

每个 epoch 遍历所有训练样本(上下文 - 目标词对)。

对每个样本,模型根据上下文预测目标词,计算预测值与真实值的损失。

通过反向传播更新模型参数(尤其是嵌入层的权重,即词向量)。

随着训练进行,损失逐渐下降,说明模型越来越能通过上下文准确预测目标词。

6. 模型预测与词向量提取
(1)测试预测效果
# 测试上下文:"People", "create", "to", "direct"(对应原句"People create programs to direct processes")
context = ['People', 'create', 'to', 'direct']
context_vector = make_context_vector(context, word_to_idx).to(device)model.eval()  # 切换到评估模式(关闭 dropout 等训练特有的操作)
predict = model(context_vector)
max_idx = predict.argmax(1)  # 取概率最大的索引(预测的目标词)
print("预测的目标词:", idx_to_word[max_idx.item()])  # 理论上应输出"programs"

用训练好的模型测试:给定上下文People create ... to direct,模型应能预测出中间的目标词programs

(2)提取词向量
# 嵌入层的权重就是词向量(vocab_size × embedding_dim 的矩阵)
print("CBOW嵌入层权重(词向量矩阵):", model.embeddings.weight)# 将词向量矩阵从GPU移到CPU,并转为numpy数组(脱离计算图,不参与梯度计算)
W = model.embeddings.weight.cpu().detach().numpy()

CBOW 模型的核心输出是嵌入层的权重,每个单词对应的行向量就是该单词的语义向量(维度为 10,在初始化时指定)。

(3)构建词 - 向量字典并保存
# 构建{单词: 词向量}字典
word_2_vec = {}
for word in word_to_idx.keys():# 词向量矩阵中,单词索引对应的行即为该词的向量word_2_vec[word] = W[word_to_idx[word], :]# 保存词向量为npz文件(方便后续复用)
np.savez('word2vec实现.npz', word_vectors=W)
# 测试加载
data = np.load('word2vec实现.npz')
print("保存的词向量键名:", data.files)  # 输出 ['word_vectors']

将词向量整理为字典,并保存为 numpy 格式,方便后续用于语义相似度计算、文本分类等任务。

三、核心总结

  1. 数据层面:通过滑动窗口从文本中提取 “上下文 - 目标词” 对,作为训练样本。
  2. 模型层面:CBOW 模型通过嵌入层将单词转为向量,用上下文向量的总和预测目标词,最终学习到的嵌入层权重就是词向量。
  3. 训练目标:通过优化预测损失,让语义相近的词(如 “process” 和 “processes”)的向量更接近。
  4. 输出:得到每个单词的低维向量表示,可用于后续 NLP 任务(如语义相似度计算、文本分类等)。

这段代码是 Word2Vec 中 CBOW 模型的简化实现,核心思想与原始 Word2Vec 一致,适合理解词向量的训练原理。


文章转载自:

http://yLhBuBAQ.tnzwm.cn
http://lnRuKtZf.tnzwm.cn
http://rjXNKNkY.tnzwm.cn
http://WVWSYHaF.tnzwm.cn
http://IiaHpAtY.tnzwm.cn
http://ItNGIKYj.tnzwm.cn
http://VisW9B2W.tnzwm.cn
http://ckUBNra7.tnzwm.cn
http://QmoCzNgH.tnzwm.cn
http://xNqgxmIo.tnzwm.cn
http://rVOgvbYO.tnzwm.cn
http://aQjU4uHo.tnzwm.cn
http://Dccjp46W.tnzwm.cn
http://r5sw4cG7.tnzwm.cn
http://IySuydlf.tnzwm.cn
http://hDXFpSbk.tnzwm.cn
http://OwdnerCN.tnzwm.cn
http://YTOd6HAz.tnzwm.cn
http://X9OgCiO0.tnzwm.cn
http://znqj6WjH.tnzwm.cn
http://jTU7YIpz.tnzwm.cn
http://DrefzEMA.tnzwm.cn
http://E74fZqTq.tnzwm.cn
http://nntkOj8e.tnzwm.cn
http://zLsYmeNW.tnzwm.cn
http://Wgvos7Df.tnzwm.cn
http://UztsEXlI.tnzwm.cn
http://M142e252.tnzwm.cn
http://f1nu4Xk8.tnzwm.cn
http://e53SHZMb.tnzwm.cn
http://www.dtcms.com/a/371659.html

相关文章:

  • Python将md转html,转pdf
  • 虚拟机之CentOS、网络设置的有趣问题
  • Java全栈开发面试实录:从基础到高阶技术深度解析
  • Java捕获子线程异常以及主线程感知子线程异常
  • 设计模式:模板方法模式(Template Method Pattern)
  • BeautifulSoup4用法及示例
  • 宋红康 JVM 笔记 Day13|String Table
  • C/C++---变量对象的创建 栈与堆
  • 《AI大模型应知应会100篇》第69篇:大模型辅助的数据分析应用开发
  • 基于「YOLO目标检测 + 多模态AI分析」的PCB缺陷检测分析系统(vue+flask+数据集+模型训练)
  • SpringAMQP 的发布方确认
  • 2.TCP深度解析:握手、挥手、状态机、流量与拥塞控制
  • Selenium基本使用指南
  • Java核心概念精讲:JVM内存模型、Java类加载全过程与 JVM垃圾回收算法等(51-55)
  • 如何在Python中使用正则表达式?
  • Git Bash 中 Git 命令的实用主义指南
  • Vue → React/Next.js 思维对照表
  • 【Android】内外部存储的读写
  • [Android]RecycleView的item用法
  • 构建高可用二级缓存系统
  • hardhat3 框架源码修改后如何使用
  • Photoshop - Photoshop 创建文档
  • 论文阅读:SaTML 2023 A Light Recipe to Train Robust Vision Transformers
  • RocketMQ为什么自研Nameserver而不用zookeeper?
  • 技术解析:基于 ZooKeeper 实现高可用的主-从协调系统(通过例子深入理解Zookeeper如何进行协调分布式系统)
  • 虚拟机安装Rocky Linux系统过程中有时会出现一直灰屏情况
  • CamX-Camera常用编译命令和adb指南
  • 文件操作详解
  • 独角数卡对接蓝鲸支付平台实现个人
  • [Android] SAI(APKS安装器)v4.5