Notes On “Attention Is All You Need”
The fundamental constraint of sequential computation: The batching across examples limited by memory
NLP序列编码
NLP基本思路,先将句子分词,然后将每个词转化为对应词向量,这样由单词拼接而成的句子就对应了一个矩阵 X = ( x 1 , x 2 , … , x n ) X=(x_1,x_2,\dots,x_n) X=(x1,x2,…,xn),其中 x i x_i xi 就对应第 i i i 个单词的词向量,维度为 d d d ,问题转化为对 X X X 这个大小为 n × d n\times d n×d 的矩阵进行编码。
传统方法的采取RNN的方案:
- sequence model : h t = f ( h t − 1 , x t ) h t h_t=f(h_{t-1},x_t) \quad h_t ht=f(ht−1,xt)ht 这里表示 position t \text{position } t position t 时hidden state
- Pros:结构简单,适合序列建模
- Cons:难以并行,在序列长度较长时训练速度慢;与此同时,当序列长度较长时,学习相距较远的两个向量关系的操作数随他们间距离的增长而增加,因此就很难学习到两个相距远的向量之间的关系
Transformer:直接采用Attention获取词向量之间的关系,简单粗暴的直接事先一步到位获取全局信息以供后续利用。
y
t
=
f
(
x
t
,
A
,
B
)
y_t=f(x_t,A,B)
yt=f(xt,A,B)
文章中主要都是令
A
=
B
=
X
A=B=X
A=B=X ,这样就比较得出
x
t
x_t
xt 与
X
X
X 中每个向量的相似度
Attention层
Attention定义
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\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dkQKT)V
这里的 Q , K , V Q,K,V Q,K,V 分别对应 q u e r y , k e y , v a l u e query,key,value query,key,value , K , V K,V K,V 依次对应,可以理解为 k e y − v a l u e key-value key−value 对;
具体的 Q = ( q 1 , q 2 , … , q n ) , K = ( k 1 , k 2 , … , k n ) Q=(q_1,q_2,\dots,q_n),K=(k_1,k_2,\dots,k_n) Q=(q1,q2,…,qn),K=(k1,k2,…,kn) ,其目的就在于用 q i q_i qi 与 K K K 中每一个向量作比较,得出 q i q_i qi 与 K K K 中每一个向量的相关度,从而以这一个相关度对 V V V 中的向量做一个加权平均。
s o f t m a x softmax softmax 作用:将 Q K T QK^T QKT 得到的向量权值归一化(毕竟我们是在做加权平均)
d k \sqrt{d_k} dk 作用:在维度 d k d_k dk 较大时, q i ⋅ k j q_i \cdot k_j qi⋅kj 这个点乘的积过大,此时 s o f t m a x softmax softmax 得到的梯度过小,不利于学习
为什么是 Q ⋅ K Q\cdot K Q⋅K 这样的点乘形式:事实上,我们的目的只是求 Q Q Q 与 K K K 的相关度,并不一定要使用点积;论文中提到也可以使用一个前馈神经网络来完成这个过程,但是实验表明在经过放缩后的点积即使在 d k d_k dk 较大时也能取得与前馈网络相近的性能,此时使用点积显然就更加方便
Multi-Head Attention
这里其实可以类比CNN中的多重卷积:
- CNN中使用多重卷积从而提取原始数据的不同特征
- 那Attention机制也自然可以通过在不同权值的意义下做多次Attention从不同的表达子空间的不同位置获取注意力信息
具体而言,做
h
h
h 次时:
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
)
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
head_i=Attention(QW_i^Q,KW_i^K,VW_i^V)\\ Multihead(Q,K,V)=Concat(head_1,\dots,head_h)W^O
headi=Attention(QWiQ,KWiK,VWiV)Multihead(Q,K,V)=Concat(head1,…,headh)WO
前面是分别做Attention,后面是将这些分别做出来的结果拼接在一起;而这个过程可以并行而加速
Transformer中所有的Attention都是使用的Multi-Head Attention,后面就不再强调了
Applications of Attention in Transformer
Transformer中在三个不同的地方利用了Attention机制:
- “Encoder-Decoder Attention” 层中, q u e r y query query 来自于Decoder层上一层的输出, k e y , v a l u e key,value key,value 均来自于Encoder层的输出,这让Decoder中每一个位置都能找到他在输入序列中大致的位置;从NLP中文本翻译的角度来理解, 可以认为作用是将已输出的目标语言句子 X X X 与原始语言句子 Y Y Y 进行比较从而完成对齐,从而确认下一个应当翻译的单词应该是哪个单词
- Encoder层中内部的Self-Attention
- Encoder层中内部的Self-Attention(关于Self-Attention的具体解释见下)
Self Attention
文章最具突破性的的一点就是Self Attention在模型中的多次应用,在Encode以及Decode部分都应用了Self Attention的思路
而所谓Self Attention就是在前面的表达式中 Q = V = K Q=V=K Q=V=K 的Attention,也即 A t t e n t i o n ( X , X , X ) Attention(X,X,X) Attention(X,X,X);
前面我们已经提到, X X X 是输入的词向量序列,那么这个 A t t e n t i o n ( X , X , X ) Attention(X,X,X) Attention(X,X,X) 就是通过将 X X X 中的每一个向量 x i x_i xi 与其他的所有向量做比较,从而得出 X X X 中所有元素的相互关系
事实上,我们注意到在Transformer模型中(至少在这篇论文中), K = V K=V K=V 是一直成立的,另外出现的只有形如 A t t e n t i o n ( X , Y , Y ) Attention(X,Y,Y) Attention(X,Y,Y) 这样的注意力模型;
Position Embedding
事实上,如果仅仅是把原本的词向量顺序放在一起形成 X X X ,并不能够有效反映原文本序列中的单词顺序关系
例如:我们考虑将 X X X 中两个向量的位置相互交换,考虑 A t t e n t i o n ( Y , X , X ) Attention(Y,X,X) Attention(Y,X,X) ,显然此时由于 K , V K,V K,V 中对应位置的向量位置都被交换了,那么最终这样与不交换会得到相同的结果;但这显然是不符合事实的:原文中两个单词交换了顺序显然应当显著影响翻译结果!
因此我们应当将单词的位置信息也加入原本的词向量,这样在做Self Attention时才能有效反映单词间的位置关系
而Google给出的方法是先做出一个位置向量,定义如下:
{
P
E
(
p
o
s
,
2
i
)
=
sin
(
p
o
s
/
1000
0
2
i
/
d
model
)
P
E
(
p
o
s
,
2
i
+
1
)
=
cos
(
p
o
s
/
1000
0
2
i
/
d
model
)
\begin{cases} PE_{(pos,2i)}&=\sin(pos/10000^{2i/d_{\text{model}}})\\ PE_{(pos,2i+1)}&=\cos(pos/10000^{2i/d_{\text{model}}}) \end{cases}
{PE(pos,2i)PE(pos,2i+1)=sin(pos/100002i/dmodel)=cos(pos/100002i/dmodel)
其中,
p
o
s
pos
pos 表示原本词向量在词序列中的位置;而
i
i
i 则表示,
p
o
s
pos
pos 这个位置被映射成一个
d
model
d_\text{model}
dmodel 维的向量,它的第
i
i
i 维的值符合这个表达式
而这样选择的原因在于,给定偏移 k k k ,以及初始的位置向量 P E p o s PE_{pos} PEpos , P E p o s + k PE_{pos+k} PEpos+k 就能被 P E p o s PE_{pos} PEpos 线性表出;这一点由公式 sin ( x + y ) = sin x cos y + cos x sin y \sin(x+y)=\sin x\cos y+\cos x\sin y sin(x+y)=sinxcosy+cosxsiny 就容易得到;也因此,除了由 p o s pos pos 直接反映的绝对位置,各位置之间的相对关系也能够被较好的表出,从而能更好的反映不同距离的词之间的相对关系
Why Self Attention
目标: Encode,即:将 ( x 1 , … , x n ) (x_1,\dots,x_n) (x1,…,xn)这样的一列符号表示映射到 ( z 1 , … , z n ) (z_1,\dots,z_n) (z1,…,zn)
优化指标:
- 每一层计算的时间复杂度
- 能被并行的运算的数量:这可以用顺序操作的最小数量来衡量
- 长距离依赖关系在网络中呈现的路径长度。正如之前提到:学习一个长距离依赖关系对于这样顺序转换任务是一个挑战,在网络中,两个向量的之间路径长度越长,他们之间的依赖关系就越难以被学习到;换句话说,两个本来相距较远的向量如果我们能让他们在网络中的路径距离减小,那么我们就能更好的学习到他们之间的关系。因此我们可以采用任意两个输入、输出在网络中路径长度的最大值作为衡量指标。
分析:
Layer Type | Complexity per Layer | Sequential Operations | Maximum Path Length |
---|---|---|---|
Self-Attention | O ( n 2 ⋅ d ) O(n^2\cdot d) O(n2⋅d) | O ( 1 ) O(1) O(1) | O ( 1 ) O(1) O(1) |
Recurrent | O ( n ⋅ d 2 ) O(n\cdot d^2) O(n⋅d2) | O ( n ) O(n) O(n) | O ( n ) O(n) O(n) |
Convolutional | O ( k ⋅ n ⋅ d 2 ) O(k\cdot n \cdot d^2) O(k⋅n⋅d2) | O ( 1 ) O(1) O(1) | O ( log k ( n ) ) O(\log_k(n)) O(logk(n)) |
Self-Attention(restricted) | O ( r ⋅ n ⋅ d ) O(r\cdot n\cdot d) O(r⋅n⋅d) | O ( 1 ) O(1) O(1) | O ( n / r ) O(n/r) O(n/r) |
对于CNN而言:
- 设kernel的宽度为 k k k ,利用空洞卷积和分离卷积可以做到表中的复杂度
- 上述卷积方法我也不是很会,还需要后续学习,暂时作为事实放在这里
对于Self-Attention而言:
-
每一层暴力两两向量比较,每一次比较复杂度 O ( d ) O(d) O(d),因此每一层复杂度 O ( n 2 ⋅ d ) O(n^2\cdot d) O(n2⋅d),由于向量是两两直接比较,相应于在网络中就是直接连接,长度 O ( 1 ) O(1) O(1)
-
考虑到,通常情况下序列长度 n n n 小于维度 d d d ,因此Self Attention比RNN更快
-
对于 n n n 较大的长序列,我们可以限制每一个单词的Attention对象仅为它的 r r r 个邻居,从而降低单层复杂度到 O ( r ⋅ n ⋅ d ) O(r\cdot n\cdot d) O(r⋅n⋅d)
-
由于整个问题可以理解为对原向量进行了分块,因此复杂度为 O ( n / r ) O(n/r) O(n/r)
写在最后:
这里我们主要是分享了Transformer的主要思想:即采取Attention和Self-Attention机制直接获取向量组之间的关系以及向量组内部的关系用以encode和decode,从而避免了传统RNN长序列带来的一系列问题。
至于更细化的代码具体实现,对我这样的初学者而言还有一定的细节需要理清,解释可以参考:
- http://nlp.seas.harvard.edu/2018/04/03/attention.html
- https://zengwenqi.blog.csdn.net/article/details/98188386
对于注意力机制的理解参考了:
- https://kexue.fm/archives/4765
- https://zhuanlan.zhihu.com/p/37601161
至于图片的话,有时间再补吧。。。