赞
踩
目录
嵌入(Embedding)是一种通用的概念,用于将高维度的离散数据映射到低维度的连续向量空间。这种映射允许我们更好地表示数据的特征,并在深度学习中广泛应用于各种领域,不仅仅是NLP。嵌入的目标是通过学习数据的分布式表示来捕捉数据之间的关系。
在NLP中,嵌入通常是指将单词或字符映射为连续向量,这就是Word2Vec的一个例子。嵌入可以通过深度学习模型自动学习,也可以使用预训练的模型(如Word2Vec、GloVe、FastText)来获得。因此,Word2Vec是嵌入的一种具体形式,专门用于将单词嵌入为连续向量。可以把Word2Vec看作是嵌入的一个子集,特别适用于NLP领域。嵌入是一个更广泛的概念,适用于多种数据类型和领域。
详情可以查看我的另一篇博客; 词向量Embedding的原理
- import torch # PyTorch深度学习框架
- import torch.nn as nn # 用于定义神经网络结构的模块
- import torch.nn.functional as F # 包含神经网络操作的函数
- import torch.optim as optim # 包含各种优化器
- from tqdm import tqdm, trange # 用于在命令行中显示进度条
- import numpy as np # 用于科学计算和数据处理的核心库
-
-
- # 设置词左边和右边选择的个数(即上下文词汇个数)
- 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(CONTEXT_SIZE)] # 上下文窗口左侧的单词
- + [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_ix):
- idxs = [word_to_ix[w] for w in context]
- return torch.tensor(idxs, dtype=torch.long)
-
- # 创建一个上下文向量示例
- make_context_vector(data[0][0], word_to_idx)
-
- # 定义一个CBOW模型类
- 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)
-
- # 通过线性投影层并应用ReLU激活函数
- out = F.relu(self.proj(embeds))
-
- # 通过输出层并应用log_softmax得到概率分布
- out = self.output(out)
- nll_prob = F.log_softmax(out, dim=-1)
- return nll_prob
-
- # 检查是否有GPU可用,如果没有则使用CPU
- device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
- # 创建一个具有词汇大小 'vocab_size' 和嵌入维度为 10 的CBOW模型,并将其移动到指定的 'device'
- model = CBOW(vocab_size, 10).to(device)
-
- # 使用Adam优化器,学习率为0.001,用于更新模型参数
- optimizer = optim.Adam(model.parameters(), lr=0.001)
-
- # 存储训练期间的损失的列表
- losses = []
-
- # 定义负对数似然损失函数,适用于多类分类任务
- loss_function = nn.NLLLoss()
-
- # 开始进行 200 个周期的训练
- for epoch in trange(200):
- total_loss = 0
-
- # 遍历训练数据
- for context, target in tqdm(data):
- # 将训练数据移到GPU
- context_vector = make_context_vector(context, word_to_idx).to(device)
- target = torch.tensor([word_to_idx[target]]).to(device)
-
- # 将梯度清零,以防止梯度累积
- model.zero_grad()
-
- # 正向传播以获得预测
- train_predict = model(context_vector)
-
- # 计算预测和目标之间的负对数似然损失
- loss = loss_function(train_predict, target)
-
- # 将优化器的梯度清零
- optimizer.zero_grad()
-
- # 反向传播以计算梯度
- loss.backward()
-
- # 使用优化器更新模型参数
- optimizer.step()
-
- # 累积每个周期的总损失
- total_loss += loss.item()
-
- # 将每个周期的总损失添加到 'losses' 列表中
- losses.append(total_loss)
-
- # 使用特定上下文测试训练过的模型
- context = ['People', 'create', 'to', 'direct']
- context_vector = make_context_vector(context, word_to_idx).to(device)
-
- # 将模型设置为评估模式
- model.eval()
-
- # 对给定上下文进行预测
- predict = model(context_vector)
-
- # 找到预测中最大值的索引
- max_idx = predict.argmax(1)
-
- # 获取嵌入层的权重矩阵
- W = model.embeddings.weight.cpu().detach().numpy()
-
- # 创建一个将单词映射到其对应单词向量的字典
- word_2_vec = {}
- for word in word_to_idx.keys():
- word_2_vec[word] = W[word_to_idx[word], :]
-
- # 打印生成的单词向量字典
- print(word_2_vec)

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。