Transformer
1.自注意力机制 Self-Attention
自注意力机制在文本中的应用,主要是通过计算单词间的互相影响,来解决长距离依赖问题。 自注意力机制的计算过程:
①Multi-head Self-Attention
之前我们都是用Q去找K,来计算相关性。但是两个事物之间相关性本身可能有多种不同的类型。因此设置多个Q(head),不同的Q来负责不同的相关性,所以需要Multi-head Self-Attention。 我们可以发现不管是Self-attention还是Multi-head Self-attention的操作中都没有加入关于输入input的位置信息(positional encoding)。 因此,当我们觉得我们做的任务中位置信息也很重要的话,可以使用positional encoding的方法来为每一个input设置一个唯一的位置。
2.Transformer的结构
Transformer 架构是以encoder/decoder架构为基础在Encoder和Decoder中都使用了Self-attention, Point-wise和全连接层。Encoder和decoder的大致结构分别如下图的左半部分和右半部分所示: Encoder将输入序列(x1,…,xn)映射到一个连续表示序列 z=(z1,…,zn)。对于编码得到的z,Decoder每次解码生成一个符号,直到生成完整的输出序列:(y1,…,ym)。对于每一步解码,模型都是自回归的,即在生成下一个符号时将先前生成的符号作为附加输入。
①Encoder and Decoder
输入文本会先经过一个叫Encoders的模块进行编码,数据再传入一个叫Decoders的模块进行解码,解码后就得到了翻译后的文本。 每个编码器的结构均相同(但它们不共享权重),每层有两个子层:自注意力层(self-attention) 和全连接的前馈网络层(feed-forward)。 从编码器输入的句子首先会经过一个自注意力层,这层帮助编码器在对每个单词编码时关注输入句子的其他单词。自注意力层的输出会传递到前馈神经网络中。每个位置的单词对应的前馈神经网络相同。 自注意力层和前馈层之间还有一个注意力层,用来关注输入句子的相关部分。确保了生成位置i的预测时,仅依赖小于i的位置处的已知输出,相当于把后面不该看到的信息屏蔽掉。
②残差连接 residual connections
整体加到Encoder\Decoder中看就是如下图所示:区别在于它多了一个Encoder-Decoder Attention层,这个层的输入除了来自Self-Attention之外还有Encoder最后一层的所有时刻的输出。Encoder-Decoder Attention层的Query来自下一层,而Key和Value则来自Encoder的输出。
③编码器模块结构
编码器的代码分析: 编码器层的代码分析:
④解码器模块结构
解码器的代码分析: 解码器层的代码实现:
def __init__(self, size, self_attn, src_attn, feed_forward, dropout):
""" 初始化函数的参数有5个
第一个是分别是size,代表词嵌入的维度大小, 同时也代表解码器层的尺寸,
第二个是self_attn,多头自注意力对象,也就是说这个注意力机制需要Q=K=V,
第三个是src_attn,多头注意力对象,这里Q!=K=V,
第四个是前馈全连接层对象,
最后是droupout置0比率。"""
super(DecoderLayer, self).__init__()
self.size = size
self.self_attn = self_attn
self.src_attn = src_attn
self.feed_forward = feed_forward
self.sublayer = clones(SublayerConnection(size, dropout), 3)
def forward(self, x, memory, source_mask, target_mask):
"""forward函数中的参数有4个,
分别是来自上一层的输入x,
来自编码器层的语义存储变量mermory,
以及源数据掩码张量和目标数据掩码张量."""
m = memory
x = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, target_mask))
x = self.sublayer[1](x, lambda x: self.src_attn(x, m, m, source_mask))
return self.sublayer[2](x, self.feed_forward)
|