接上一篇文章 AI大模型 之 词向量(Word to Vector), 模型是由中心词,来预测周围上下文。 而接下来要实现的 模型则是由上下文来预测中心词。
权重向量被存储在 的线性层 中。线性层是神经网络的最基本组件。嵌入层和线性层都是通过对层内参数的调整,来获得权重,学习知识。可以用嵌入层替换One-Hot编码,可节省计算资源。
In
# 定义一个句子列表,后面会用这些句子来训练CBOW和Skip-Gram模型
sentences = ["Kage is Teacher", "Mazong is Boss", "Niuzong is Boss",
"Xiaobing is Student", "Xiaoxue is Student",]
# 将所有句子连接在一起,然后用空格分隔成多个单词
words = ' '.join(sentences).split()
# 构建词汇表,去除重复的词
word_list = list(set(words))
# 创建一个字典,将每个词映射到一个唯一的索引
word_to_idx = {word: idx for idx, word in enumerate(word_list)}
# 创建一个字典,将每个索引映射到对应的词
idx_to_word = {idx: word for idx, word in enumerate(word_list)}
vec_size = len(word_list) # 计算词汇表的大小
print("词汇表:", word_list) # 输出词汇表
print("词汇到索引的字典:", word_to_idx) # 输出词汇到索引的字典
print("索引到词汇的字典:", idx_to_word) # 输出索引到词汇的字典
print("词汇表大小:", vec_size) # 输出词汇表大小
# 生成CBOW训练数据
def create_cbow_dataset(sentences, window_size=2):
data = [] # 初始化数据
for sentence in sentences:
sentence = sentence.split() # 将句子分割成单词列表
for idx, word in enumerate(sentence): # 遍历单词及其索引
# 获取上下文词汇,将当前单词前后各window_size个单词作为周围词
context_words = sentence[max(idx - window_size, 0):idx] \
+ sentence[idx + 1:min(idx + window_size + 1,len(sentence))]
# 将当前单词与上下文词汇作为一组训练数据
data.append((word, context_words))
return data
# 使用函数创建CBOW训练数据
cbow_data = create_cbow_dataset(sentences)
# 打印未编码的CBOW数据样例(前三个)
print("CBOW数据样例(未编码):", cbow_data[:3])
Out
CBOW数据样例(未编码): [('Kage', ['is', 'Teacher']), ('is', ['Kage', 'Teacher']), ('Teacher', ['Kage', 'is'])]
In
# 定义One-Hot编码函数
import torch # 导入torch库
def one_hot_encoding(word, word_to_idx):
tensor = torch.zeros(len(word_to_idx)) #创建一个长度与词汇表相同的全0张量
tensor[word_to_idx[word]] = 1 # 将对应词索引位置上的值设为1
return tensor # 返回生成的One-Hot编码后的向量
# 展示One-Hot编码前后的数据
word_example = "Teacher"
print("One-Hot编码前的单词:", word_example)
print("One-Hot编码后的向量:", one_hot_encoding(word_example, word_to_idx))
One-Hot编码前的单词: Teacher
One-Hot编码后的向量: tensor([0., 0., 0., 0., 0., 0., 0., 1., 0.])
定义CBOW模型
# 定义CBOW模型
import torch.nn as nn # 导入neural network
class CBOW(nn.Module):
def __init__(self, vec_size, embedding_size):
super(CBOW, self).__init__()
# 从词汇表大小到嵌入大小的线性层(权重矩阵)
self.input_to_hidden = nn.Linear(vec_size, embedding_size, bias=False)
# 从嵌入大小到词汇表大小的线性层(权重矩阵)
self.hidden_to_output = nn.Linear(embedding_size, vec_size, bias=False)
def forward(self, X): # X: [num_context_words, vec_size]
# 生成嵌入: [num_context_word, embedding_size]
embedding_size = self.input_to_hidden(X)
# 计算隐藏层,求嵌入的均值:[embedding_size]
hidden_layer = torch.mean(embeddings, dim=0)
# 生成输出层:[1, vec_size]
output_layer = self.hidden_to_output(hidden_layer.unsqueeze(0))
return output_layer
embedding_size = 2 # 设定嵌入层的大小,这里选择2是为了方便展示
cbow_model = CBOW(vec_size, embedding_size) # 实例化CBOW模型
print("CBOW模型:", cbow_model)
Out
CBOW模型: CBOW(
(input_to_hidden): Linear(in_features=9, out_features=2, bias=False)
(hidden_to_output): Linear(in_features=2, out_features=9, bias=False)
)