目录
1、one-hot编码
在机器学习和自然语言处理(NLP)中,one-hot 编码是一种常用于将类别数据(如单词)转换为机器学习模型可以处理的数值形式的方法。one-hot 编码会为每个类别分配一个全为零的向量,除了该类别的索引位置为1之外。因为单词通常被视为离散的类别,所以这种方法在处理文本数据时特别有用。
假设我们有一个简单的词汇表 ["cat", "dog", "tree"]
,并且我们想要为这些单词创建one-hot
编码。
- "cat" 可能会编码为
[1, 0, 0]
- "dog" 可能会编码为
[0, 1, 0]
- "tree" 可能会编码为
[0, 0, 1]
2、cbow原理
CBOW模型的核心思想是通过上下文中的词来预测目标词。具体而言,CBOW模型通过将上下文中的词的词向量相加,得到一个上下文向量,然后通过一个隐藏层将上下文向量映射到目标词的概率分布。在训练过程中,CBOW模型通过最大化预测目标词的概率来学习到每个词的词向量表示。
3、cbow模型的训练过程
1.当前词的上下文词语的one-hot编码输入到输入层。
2.这些词分别乘以同一个矩阵W*N后分别得到各自的1*N 向量。
3.将多个这些1*N 向量取平均为一个1*N 向量。
4.将这个1*N 向量乘矩阵 W’v*N,变成一个1*V 向量。
5.将1*V 向量softmax归一化后输出取每个词的概率向量1*V
6.将概率值最大的数对应的词作为预测词。
7.将预测的结果1*V 向量和真实标签1*V 向量(真实标签中的V个值中有一个是1,其他是0)计算误差
8.在每次前向传播之后反向传播误差,不断调整 W*n和 W’v*矩阵的值。
4、代码示例
import torch
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))
#将上下文词转换为one-hot编码
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) # vocab si2
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) # cnn
out = F.relu(self.proj(embeds))
out = self.output(out)
nll_prob =F.log_softmax(out,dim=-1)
return nll_prob
device = "cuda" if torch.cuda.is_available() else "map" if torch.backends.mps.is_available() else "cpu"
print(f"Using {device} device")
# 实例化模型并设置优化器和损失函数
model=CBOW(vocab_size,10).to(device)
optimizer =optim.Adam(model.parameters(),lr=0.001)
losses=[]
loss_function =nn.NLLLoss()
# 训练模型
for epoch in trange(200):
total_loss = 0
for context, target in tqdm(data):
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) # 可以不与forward
loss =loss_function(train_predict,target)
# 反向传播
optimizer.zero_grad()# 梯度值清零
loss.backward() # 反向传播计算得到每个参数的度值
optimizer.step()# 根据梯度更新网络参数
total_loss += loss.item()
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)
print("cBOW embedding'weight=", model.embeddings.weight)
W=model.embeddings.weight.cpu().detach().numpy()#
print(W)
#'保存训练后的词向量为npz文件"
np.savez('word2vec实现.npz',file_1=W)
data = np.load('word2vec实现.npz')
print(data.files)
这段代码实现了一个简单的CBOW模型,用于学习词向量表示。代码首先准备数据,构建词汇表并生成训练数据集。然后定义了CBOW模型类,包括Embedding层、线性映射层和输出层。接着使用Adam优化器和负对数似然损失函数进行模型训练,迭代多个epoch。最后,给定上下文词列表,模型预测目标词的词向量表示,并将训练得到的词向量保存为npz文件。整体而言,这段代码展示了如何使用PyTorch实现CBOW模型进行词向量表示学习。