《Attention Is All You Need》

本文是对Google2017年发表于NIPS上的论文"Attention is all you need"的阅读笔记.

对于深度学习中NLP问题,通常是将句子分词后,转化词向量序列,转为seq2seq问题.

  • RNN方案

    采用RNN模型,通常是递归地进行 y t = f ( y t 1 , x t ) y_t=f(y_{t-1},x_t) ,优点在于结构简单,十分适合序列建模;缺点在于需要前一个输出作为后一个的输入参与运算,因此无法并行计算,速度很慢,且单向RNN只能获取前向序列关系,需要采用双向RNN才可以获取完整的全局信息.

  • CNN方案

    采用CNN模型,则是通过一个窗口(卷积核)来对整个序列进行遍历, y t = f ( x t 1 , x t , x t + 1 ) y_t = f(x_{t-1},x_t,x_{t+1}) 只能获取到局部信息,需要层叠来增大感受野.

本文提出了一种Transformer注意力机制,完全替代了RNN、CNN.

y t = f ( x t , A , B ) y_t = f(x_t,A,B)

将A、B都取为X时,则称为Self-Attention,即通过 x t x_t 和整个 X X 进行关系运算最后得到 y t y_t .

Attention层

Google给出了如下的Attention结构

Attention层.jpg

A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V) = softmax(\frac{QK^T}{\sqrt{d_k}})V

其中, d k d_k k e y key 的维数, d v d_v v a l u e value 的维数, Q R n × d k , K R m × d k V R m × d v Q\in R^{n\times d_k}, K\in R^{m\times d_k}, V\in R^{m\times d_v}

d k d_k 较小时,采用点积和加法注意力机制的效果时相同的,当 d k d_k 较大时,点积的效果会下降很多,这是由于 d k d_k 较大时,点积产生的值会很大导致 s o f t m a x softmax 陷入了饱和区,因此这里除以了 d k \sqrt{d_k} .

Y s e l f = A t t e n t i o n ( V , V , V ) Y_{self} = Attention(V,V,V)
通过self-attention,可以无视词之间距离直接计算远距离的两个词的依赖关系,从而能学习到整个句子的内部结构,并且相当于进行了句法分析.

Multi-Head Attention

多头注意力机制就是重复进行 h h 次(参数不共享),即采用不同的参数进行 h h 次,捕获不同子空间上的相关信息,将最后的结果拼接起来,会产生更好的效果.
M u l t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , , h e a d h ) W O w h e r e    h e a d i = A t t e n t i o n ( Q W i Q , K W i K , V W i V ) MultiHead(Q,K,V) = Concat(head_1,\dots,head_h)W^O\\ where\ \ head_i = Attention(QW_i^Q,KW_i^K,VW_i^V)

其中, W i Q R d m o d e l × d k , W i K R d m o d e l × d k , W i V R d m o d e l × d v , W O R h d v × d m o d e l W_i^Q\in R^{d_{model}\times d_k}, W_i^K\in R^{d_{model}\times d_k}, W_i^V\in R^{d_{model}\times d_v}, W^O \in R^{hd_v\times d_{model}}

Feed-Forward Networks

在encoder和decoder中,除了注意力子层之外还包含一个全连接的前馈网络,含有两个线性变换,并且在两者之间有一个 R e L U ReLU 激活函数.

F F N ( x ) = max ( 0 , x W 1 + b 1 ) W 2 + b 2 FFN(x) = \max(0, xW_1+b_1)W_2 + b_2

相当于两个卷积核大小为1的卷积层.

Positional Encoding

很容易发现,对于两个顺序不同词相同的句子,通过自注意力层最后得到的输出相同的,即这里的自注意力机制并不能捕捉到词之间的顺序关系,仅仅相当于一个词袋模型.

因此Google提出了Position Encoding,为每个词添加位置编码,与词序列作为共同输入.

PositionalEncoding.jpg

这里采用的运算关系如下:
P E ( p o s , 2 i ) = sin ( p o s 1000 0 2 i / d m o d e l ) P E ( p o s , 2 i + 1 ) = cos ( c o s 1000 0 2 i / d m o d e l ) PE_{(pos,2i)} = \sin(\frac{pos}{10000^{2i/d_{model}}})\\ PE_{(pos,2i+1)} = \cos(\frac{cos}{10000^{2i/d_{model}}})

p o s pos 是位置, i i 是维度,采用sin函数,对于任意的偏移 k k P E p o s + k PE_{pos+k} 都可以描述为 P E p o s PE_{pos} 的线性函数.

自注意力的优势

  • 计算复杂度/layer
  • 并行计算数量
  • 计算远距离依赖关系的路径长度

正则化

  • 对于每一子层都采取dropout操作
  • 对词序列和位置编码的和进行dropout

其他

  • 根据实验结果推测,可能存在一个更复杂的函数要比点积的效果更优.
  • 实验验证,学习过的位置嵌入与sin曲线效果相同.

Beam search

在test集上,通过beam search 集束搜索来寻找解. 集束搜索是一种贪心算法,相当于一个约束优化的广度优先搜索,并不能保证一定可以找到最优解.

大致思路如下:

每一次都只寻找代价最低即可能性最大的前 m m (称为beams size)个解,直到遇到终止符位置.

参考文献

苏剑林-Attention is all you need 浅读

猜你喜欢

转载自blog.csdn.net/JN_rainbow/article/details/84712660