word2vector之Skip_Gram模型详解

一个深度学习入门的菜鸟,希望通过做笔记的方式记录下自己学到的东西,希望对同样入门的人有所帮助。希望大佬们帮忙指正错误~侵权立即删除。

内容

一、前景知识

二、Skip-gram模型思想

三、Skip-gram模型结构分析

1、网络图

2、网络层次级分析

3、注意点

四、代码实现朴素skip-gram

一、前景知识

这些可以根据需要跳过和观看

NLP之文本预处理详解_tt丫的博客-CSDN博客

NLP之文本特征提取详解_tt丫的博客-CSDN博客

CBoW模型word2vector之CBoW模型详解_tt丫的博客-CSDN博客

二、Skip-gram模型思想

Skip-gram模型跟CBoW模型是反过来的。

CBoW模型通过上下文来预测当前值,而Skip-gram模型是通过当前值预测上下文。

三、Skip-gram模型结构分析

1、网络图

word2vector之Skip_Gram模型详解

2、网络层次级分析

(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。

3、注意点

skip-gram的训练过程不是一次性用中心词预测窗口数个词,而是中心词和一个周围词组成一个训练样本。

比如当我们指定窗口为2,那么当前词左右的周围词共有4个。有4个周围词的话就有4个样本,即[中心词,周围词1]、[中心词,周围词2]……

这也决定了上述朴素skip_gram模型的输出是大小为1 * V。(就是这4个1 * V组成了1个当前词预测出上下文4个词)

四、代码实现朴素skip-gram

🎈 导入需要的库

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()

欢迎大家在评论区批评指正,谢谢~

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2022年3月15日 下午12:37
下一篇 2022年3月15日

相关推荐