介绍词向量word2evc概念,及CBOW和Skip-gram的算法实现( 七 )


forcenter_word,target_word,labelindataset:
#遍历dataset中的每个样本 , 并将这些数据送到不同的tensor里
center_word_batch.append([center_word])
target_word_batch.append([target_word])
label_batch.append(label)
#当样本积攒到一个batch_size后 , 我们把数据都返回回来
#在这里我们使用numpy的array函数把list封装成tensor
#并使用python的迭代器机制 , 将数据yield出来
#使用迭代器的好处是可以节省内存
iflen(center_word_batch)==batch_size:
yieldnp.array(center_word_batch).astype("int64"),
np.array(target_word_batch).astype("int64"),
np.array(label_batch).astype("float32")
center_word_batch=[]
target_word_batch=[]
label_batch=[]
iflen(center_word_batch)>0:
yieldnp.array(center_word_batch).astype("int64"),
np.array(target_word_batch).astype("int64"),
np.array(label_batch).astype("float32")
for_,batchinzip(range(10),build_batch(dataset,128,3)):
print(batch)
3.2网络定义
定义skip-gram的网络结构 , 用于模型训练 。 在飞桨动态图中 , 对于任意网络 , 都需要定义一个继承自fluid.dygraph.Layer的类来搭建网络结构、参数等数据的声明 。 同时需要在forward函数中定义网络的计算逻辑 。 值得注意的是 , 我们仅需要定义网络的前向计算逻辑 , 飞桨会自动完成神经网络的后向计算 , 代码如下:
#定义skip-gram训练网络结构
#这里我们使用的是paddlepaddle的1.8.0版本
#一般来说 , 在使用fluid训练的时候 , 我们需要通过一个类来定义网络结构 , 这个类继承了fluid.dygraph.Layer
classSkipGram(fluid.dygraph.Layer):
def__init__(self,vocab_size,embedding_size,init_scale=0.1):
#vocab_size定义了这个skipgram这个模型的词表大小
#embedding_size定义了词向量的维度是多少
#init_scale定义了词向量初始化的范围 , 一般来说 , 比较小的初始化范围有助于模型训练
super(SkipGram,self).__init__()
self.vocab_size=vocab_size
self.embedding_size=embedding_size
#使用paddle.fluid.dygraph提供的Embedding函数 , 构造一个词向量参数
#这个参数的大小为:[self.vocab_size,self.embedding_size]
#数据类型为:float32
#这个参数的名称为:embedding_para
#这个参数的初始化方式为在[-init_scale,init_scale]区间进行均匀采样
self.embedding=Embedding(
size=[self.vocab_size,self.embedding_size],
dtype='float32',
param_attr=fluid.ParamAttr(
name='embedding_para',
initializer=fluid.initializer.UniformInitializer(
low=-0.5/embedding_size,high=0.5/embedding_size)))
#使用paddle.fluid.dygraph提供的Embedding函数 , 构造另外一个词向量参数
#这个参数的大小为:[self.vocab_size,self.embedding_size]
#数据类型为:float32
#这个参数的名称为:embedding_para_out
#这个参数的初始化方式为在[-init_scale,init_scale]区间进行均匀采样
#跟上面不同的是 , 这个参数的名称跟上面不同 , 因此 ,
#embedding_para_out和embedding_para虽然有相同的shape , 但是权重不共享
self.embedding_out=Embedding(
size=[self.vocab_size,self.embedding_size],
dtype='float32',
param_attr=fluid.ParamAttr(
name='embedding_out_para',
initializer=fluid.initializer.UniformInitializer(
low=-0.5/embedding_size,high=0.5/embedding_size)))
#定义网络的前向计算逻辑
#center_words是一个tensor(mini-batch) , 表示中心词
#target_words是一个tensor(mini-batch) , 表示目标词
#label是一个tensor(mini-batch) , 表示这个词是正样本还是负样本(用0或1表示)
#用于在训练中计算这个tensor中对应词的同义词 , 用于观察模型的训练效果