基于tensorflow实现的论文Attention is All You Need
- docker pull majing/tensorflow-1.10.0-cpu-transformer:v2
- docker run -i -t -p 7000:7000 --rm majing/tensorflow-1.10.0-cpu-transformer:v2
- docker pull majing/tensorflow-1.10.0-gpu-transformer:v2
- docker run -i -t -p 7000:7000 --rm majing/tensorflow-1.10.0-gpu-transformer:v2
- python3.6
- pip install -r requirement.txt
- 在docker环境下:jupyter-notebook --no-browser --ip 0.0.0.0 --port=7000 --allow-root
- 在浏览器中访问ip:7000打开jupyter
- 预处理:python prepro.py
- github中TED_data为已处理好的数据
- 训练:python train.py
- 测试:python test.py
编码由6个相同的层组成,每一层有两个子层。第一个子层使用了多头的注意力机制,第二个子层是一个基于位置的全连接网络。在两个子层之间使用了残差连接和基于层的参数归一化。也就是说,每一个子层可以用来表示。
解码也由6个相同的层组成,每一层包含三个子层,除了编码阶段两个子层外,增加了一个对编码阶段输出的多头注意力的层。在解码阶段也使用了自注意力,为了避免位置信息对解码的影响,增加了一个mask,来保证对位置i的预测只和位置i之前的输出有关系。
注意力可以看成是query在(key, value)对的映射下,产生新的output。output是由value的加权和算出来的,权重则是根据query和key的相关度算出来的。
Scaled Dot-Product Attention是计算attention的基本单元,如下图:
其中的主要作用是为了防止
比较大时,softmax的梯度会非常小,因此进行了一个归一化。这里Q、K的维度都是
,V的维度时
Multi-Head Attention将注意力计算映射到不同的QKV向量,并行地产生多个维度的outputs,最终将输出concat到一起,如下图:
在论文实验中,使用层并行计算attention,对于每一层使用参数
,由于每一个head的参数的维度降低了,整体计算量和之前保持一致。
模型中共有3个地方使用了这种多头注意力机制:
- encoder-decoder attention层:Q是上一层解码器的输出,K、V是encoder输出
- encoder层:自注意力,Q、K、V是上一层encoder的输出,每一层encoder的每一个位置都可以和前面层的所有位置的向量产生交互。
- decoder层:在self-attentino基础上使用了masking。
对于同一层的不同位置,参数是共享的;不同层间参数不共享。
也可以把这个理解成两个的卷积,输入和输出的维度都是
,中间层维度是
输入token、输出token到向量的转换过程使用共享的embedding。
由于整个模型没有使用循环或者卷积操作,在encoder和decoder中加入位置编码。位置编码计算方法如下: