深度学习入门小菜鸟,希望像做笔记记录自己学的东西,也希望能帮助到同样入门的人,更希望大佬们帮忙纠错啦~侵权立删。
✨word2vector系列展示✨
一、CBOW
1、朴素CBOW模型
word2vector之CBoW模型详解_tt丫的博客-CSDN博客
2、基于分层softmax的CBOW模型
基于分层softmax的CBoW模型详解_tt丫的博客-CSDN博客
3、基于高频词抽样+负采样的CBOW模型
基于高频词抽样+负采样的CBOW模型_tt丫的博客-CSDN博客
二、Skip_Gram
本篇
(关于Skip_Gram的分层softmax和负采样,与CBOW类似)
目录
一、前景知识
二、Skip-gram模型思想
三、Skip-gram模型结构分析
1、网络图
2、网络层次级分析
3、注意点
四、代码实现朴素skip-gram
这些可以根据需要跳着看
NLP之文本预处理详解_tt丫的博客-CSDN博客
NLP之文本特征提取详解_tt丫的博客-CSDN博客
CBoW模型word2vector之CBoW模型详解_tt丫的博客-CSDN博客
Skip-gram模型跟CBoW模型是反过来的。
CBoW模型通过上下文来预测当前值,而Skip-gram模型是通过当前值预测上下文。
(1)Input
输入的是1 * V的one-hot向量x(其中V为词典大小)
(2)Hidden
构建一个大小为V * N的嵌入矩阵W(其中N为词向量的维度),所以用这个W和x相乘,得到最终Hidden的输出,大小为1 * N
(3)Output
构建一个大小为N * V的矩阵W’,用W’和Hidden的输出相乘得到最终的输出,大小为1 * V。
skip-gram的训练过程不是一次性用中心词预测窗口数个词,而是中心词和一个周围词组成一个训练样本。
比如当我们指定窗口为2,那么当前词左右的周围词共有4个。有4个周围词的话就有4个样本,即[中心词,周围词1]、[中心词,周围词2]...…
这也决定了上述朴素skip_gram模型的输出是大小为1 * V。(就是这4个1 * V组成了1个当前词预测出上下文4个词)
导入所需的库
import torch
import numpy as np
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
import torch.utils.data as Data
从文件中读取数据,并且进行一定的处理,跟CBoW模型一样的操作
# 文本预处理
path = "1.txt"
f = open(path, 'r', encoding= 'utf-8', errors= 'ignore')
text = []
piece = ''
for line in f:
for uchar in line:
if uchar == '\n':
continue
if uchar == '.' or uchar == '?' or uchar == '!':
text.append(piece)
piece = ''
else:
piece = piece + uchar
#print(text)
word_list = " ".join(text).split()
print(word_list)
#将分词后的结果去重
vab = list(set(word_list))
print(vab)
#对单词建立索引
word_dict = {w:i for i, w in enumerate(vab)} #单词-索引
相关参数的设置
# 相关参数
dtype = torch.FloatTensor
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
batch_size = 8
EMBEDDING_DIM = 4 # 词向量的维度是4
CONTEXT_SIZE = 2 # window size
voc_size = len(vab)
对输入的数据进行处理(针对上下文的输入)以及送进DataLoader
# 数据预处理
data = []
for idx in range(CONTEXT_SIZE, len(word_list) - CONTEXT_SIZE):
center = word_dict[word_list[idx]] # 中心词
# 中心词和每个周围词组成一个训练样本
for j in range(idx - CONTEXT_SIZE,idx + CONTEXT_SIZE + 1):
if j == idx:
continue
data.append([center,word_dict[word_list[j]]])
input_data = []
output_data = []
for i in range(len(data)):
# input_data转换为one-hot形式,output_data合成一个list
input_data.append(np.eye(voc_size)[data[i][0]])
output_data.append(data[i][1])
input_data, output_data = torch.Tensor(input_data), torch.LongTensor(output_data)
dataset = Data.TensorDataset(input_data, output_data)
loader = Data.DataLoader(dataset, batch_size, True)
构建模型
# 构建Skip_gram模型
class Skip_gram(nn.Module):
def __init__(self):
super(Skip_gram, self).__init__()
self.W = nn.Parameter(torch.randn(voc_size, EMBEDDING_DIM).type((dtype)))
self.V = nn.Parameter(torch.randn(EMBEDDING_DIM, voc_size).type((dtype)))
def forward(self, input):
hidden = torch.matmul(input, self.W)
output = torch.matmul(hidden, self.V)
return output
网络配置
model = Skip_gram().to(device)
criterion = nn.CrossEntropyLoss().to(device)
optimizer = optim.Adam(model.parameters(), lr=1e-3)
训练
for epoch in range(1000):
for i , (x, y) in enumerate(loader):
x = x.to(device)
y = y.to(device)
pred = model(x)
loss = criterion(pred, y)
if (epoch + 1) % 50 == 0:
print(epoch + 1, i, loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
欢迎大家在评论区批评指正,谢谢啦~