Transformer 修炼之道(二)、Encoder

2020-06-19  本文已影响0人  CW不要无聊的风格

Date: 2020/06/19

Author: CW

前言:

本篇文将对 Transformer 的 Encoder 作解析,内容应该是这个系列最丰富的一篇,因为后面的 Decoder 结构与 Encoder 几乎一致,只有些细节差异。

Encoder 的内容主要包括 多头自注意力层(Multi-Head Self-Attention)前向反馈网络层(Feed Forward Network),前者用于捕捉特征之间的关系,后者是进一步编码学习,实质上等同于MLP(Multi-Layer Perceptron)。

Encoder 是由多个(通常6个)层组成的,在每个层内部都有残差连接和归一化操作,同时也包含了上述提及的多头自注意力层和前向反馈网络层。


Outline

I. Multi-Head Self-Attention

II. Feed Forward Network(FFN)

III. Add & Norm

IV. Summary

Encoder

Multi-Head Self-Attention

在 Encoder 的第1层里,多头自注意力层的输入是特征向量矩阵(比如多个词向量组成的矩阵 ),而在后面的其它层,输入则是前一层的输出。多头自注意力层由多个自注意力层组成,其输出由其中的每个自注意力层的输出拼接而成,我们可以先来看看单个自注意力层的操作。

当自注意力层获得输入后,会对其做不同的线性变换分别生成 Q(Query)、K(Key)、V(Value) 三个矩阵。

Q、K、V 的生成

然后按如下公式计算输出:

Self-Attention 计算公式

形象点用图表示如下:

Self-Attention 计算图示

这里除以\sqrt{d_{k} } 原因是防止Q和K的点积值过大(\sqrt{d_{k} } 即Q的列数,也是K的行数),避免在经过softmax后梯度太小。

作者的原话是:

We suspect that for large values of dk, the dot products grow large in magnitude, pushing the softmax function into regions where it has extremely small gradients.

这个计算过程的操作也称为 Scaled Dot-Product Attention 。

OK,至此,我们已经得到单个自注意力的输出,记为Z吧。而多头自注意力就是“多个头的自注意力”,通常“头数”(通俗理解为个数)设为8,这样就有8个自注意力的输出,最后将它们拼接起来再经过一个线性变换即可。

Multi-Head Attention Multi-Head Attention 输出示意图

下面来看看代码实现:

多头自注意力代码实现 (i)

clones是一个方法,代表将结构相同的层实例化n次(上图中n=4)。

clones

接下来看看其前向过程:

多头自注意层代码实现(ii)

注意,通过代码我们可了解到,“多头”的实现是将最后一个维度分割成多个,然后将其中每个独立作为“一个头”,所有头都处理完毕后,将分割出来的维度拼接在一起实现复原。

另外,上图中可以看到有个mask,这里先不谈,在下篇解析 Decoder 时会说明它的作用。

最后来了解下自注意力的计算是如何实现的,即上图中的compute_attn这个方法:

自注意力的实现

注:以上mask_fill()方法应为mask_fill_(),这样scores才会原地改变


Feed Forward Network(FFN)

这部分就相对简单些,实质上就是两个全连接层,并且其中一个带ReLU激活,两层中间有Dropout。

FFN 计算公式

男子汉话不多说,直接上代码:

FFN代码实现

Add & Norm

在 Encoder 内部的每一层都有归一化操作和残差连接,先来看看归一化:

NormLayer

在实现过程中,需要注意下上图红框部分所说的,如果直接令self.gamma=torch.ones(features)的话gamma这个参数是不会注入到模型parameters中的,这样就不能被学习到了。

残差连接是在每一层内部,将多头自注意力或前向反馈层的输入与输出(经过dropout)连接,注意,这里的实现是在输入多头自注意力或前向反馈层前先进行归一化,实际可根据情况作更改,比如在多头自注意力或前向反馈层后再进行归一化。

残差连接

Summary

最后一部分来看看 Encoder 的整体实现:

Encoder

Encoder 就是由多个以下 EncoderLayer 组成:

EncoderLayer

最后

可以看出,Transformer 的结构还是相对简单而有规律的,但就是这么不复杂的一个东西,却意外地好使,就目前的趋势来看,编码+解码+注意力 这套玩法貌似能拓展到许多领域使用。

上一篇下一篇

猜你喜欢

热点阅读