赞
踩
代码中给出的数据是使用的是IWSLT2016德语和英语的数据集,如下图所示,(对于linux的用户可以执行shell脚本获取到数据集),对于windows的用户数据下载地址为(https://wit3.fbk.eu/2016-01)。
该文件主要做的就是分词,其中先将需要的句子从文件中解析出来以句子的形式放入list中,分为三部分,分别为训练集,测试集和验证集。
由于训练集和测试集、验证集的文件形式不一致,所以处理的方式不太相同,但是都是以句子的形式放入list中,(这里提示一下,在文件读写的时候需要加入encoding=“utf-8”,否则会提示编码错误)。
后面就是以句子的形式保存如文件中,形成训练、测试和验证的语料库
获取语料后,进行分词处理,代码中需要安装一个库sentencepiece,这是nlp的语料处理工具,具体使用方式可以自行百度(这里请注意,在 \ 之前应该加上单引号)。
处理完成的结果就是会形成一个字典文件,里面有每个词对应的id,还会形成的文件是分词后的语料文件。
数据加载,这里主要是构建能够用于深度学习使用的数据输入,具体过程如下:
模型主要的组件在modules.py中,其中包括scaled_dot_product_attention、multihead_attention、layer_normalization、full connection layer、word_embedding、position_embedding层。
model.py中主要是建立模型,将上面的components进行组合形成论文中transformer的框架。
首先这是model.py的__init__方法,主要就是获取token2idx和idx2token两个映射字典,以及字典中所有单词的embedding向量,
其中embedding的主要参数就是vocab_size(单词的数量)、d_model(嵌入的维度)、zero_padding(是否进行zero_padding);其中zero_padding将padding(值为0)的向量加入到词向量中。
这里是encoder部分,xs是之前load_data中获取的生成器的所获取的一个batch的数据,里面包含了三部分内容(见数据加载部分的source_data),其中x是idx的list,src_masks是用于后期mask的计算,因为有的句子长度不够需要进行padding,但是padding的信息不是我们需要的(src_masks中进行padding的位置为True),后期需要进行mask处理;后面就是对x进行embedding获取嵌入后的词向量,然后进行标准化。
position_encoding在论文中采用的是sin和cos三角函数的形式,如下图所示,pos代表的是单词在句子中的位置,2i和2i+1分别代表的是词向量的偶数维和奇数维,即对于奇数维采用sin函数,对于偶数维采用cos形式。
position的具体实现方式如下,首先E为词向量的嵌入维度,N为batch_size,T为该batch中最长的句子的长度;position_ind就是将每句话的词的位置进行复制N次,因为经过padding后每个句子的长度相等;position_enc就是将上面公式中的sin和cos括号里面的内容实现,然后再根据不同的位置设置sin和cos,和embedding一样通过lookup的方式进行查找;对于padding的位置,我们通过masking的判断将其设置为0。
这里通过循环的方式实现论文中的block部分,这里的enc是word_embedding和position_embedding进行相加所得到的向量,该循环中最主要的就是multihead-attention部分。
下面是multihead-attention的代码,其实本质上是self-attention的多次计算并经计算结果再进行组合,其中d_model还是嵌入的词向量的维度,encoder部分的query,key,values都是自身,因此在这里三者相等,通过非激活的dense层进行线性映射,将映射的结果在最后一个维度进行分割,然后将分割的结果组合到第一个维度,将组合的结果进行scaled-dot-product-attention,(按照我的理解就是对词向量的不同部分进行多次注意力机制);将attention的结果在第一维度进行分解然后再组合回第三维度,这样久能得到mutlihead-attention的结果;output+queries是残差连接操作,ln是进行layer-normalization操作,论文中都有提及。
scaled-dot-product-attention其实具体操作是十分简单的,按照公式就是(Q*K^T/d_k ** 0.5) * V,这里论文中进行了解释,除以d_k ** 0.5的原因是保持均值和方差不变;在获取到该结果后不能直接进行softmax,因为padding的部分是无用信息,因此我们不希望padding部分参与运算,这里有一步就是进行mask,mask主要就是根据前面提到的src_masks进行位置检测,并将相应位置上的向量全部置为-2 ** 32 + 1,这样进行softmax该位置的权重基本全部为0。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。