引言
研究深度学习也有两年了,之前看transformer的论文,感觉完全看不懂,因此对transformer的理解都来自于网上的资源,印象比较深的是李宏毅-Transformer和Transformer 详解这两个资源,前者构建了我对自注意力的初始直觉,后者构建了我对整个模型架构的初步理解。然而,这些资源,学完之后总会有种隔靴搔痒的感觉,理解总是有些朦胧。这段时间佛系科研,又遇到了这些模型,准备重新从原文出发,构建出对transformer较为深入的直觉
Transformer
来自文章:2017-NIPS-Attention Is All You Need
1. 适用任务
虽然之后,transformer的变种被应用到各种各样的任务上,但最初,是为了序列转录模型提出的。序列转录模型,用于序列到序列的生成,比如语言建模任务和机器翻译任务,这类模型通常包括一个编码器encoder和一个解码器decoder
2. 动机
并行化:之前的序列转录模型,大多都是使用RNN-based结构。由于RNN中固有的时序性,所以限制了训练的并行化:1)RNN中第 t t t个step依赖于前 t − 1 t-1 t−1个step的结果,也就是说,第 t t t个step的结果必须要等前 t − 1 t-1 t−1得到结果后才能生成;2)当序列较长时,后面的step可能没办法记忆之前的历史信息,或者由于内存的限制而无法记住前面的历史信息(内存限制了hidden state的大小)
而注意力机制,天然得带有“天涯若比邻”的属性,因为你可以令当前step与之前的任意一个遥远的step进行注意力的计算
效率:这一点是用结果来说明的。Transformer模型能够在8块P100的情况下,只有12小时的时间达到彼时的SotA
3. 模型结构
简单来说,是6个encoder和6个decoder来完成的,我们分别以1个encoder和1个decoder为例,来进行维度推演,首先是encoder的(其中 d m o d e l = h e a d ∗ d k / d v d_{model}=head*d_k/d_v dmodel=head∗dk/dv):
层 | 子层 | 作用 | 输入维度 | 输出维度 |
---|---|---|---|---|
embedding layer | 将单词转化为词嵌入 | b s z , m a x _ l e n bsz,max\_len bsz,max_len | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
positional encoding | 为词嵌入添加位置信息 | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
Multi-head Attention | linear | 将词嵌入转化为多个维度(head)的Q、K、V | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d k / d v bsz,max\_len,d_{k}/d_v bsz,max_len,dk/dv |
scaled dot-product attention | 利用Q、K、V从多个维度(head)衡量不同step输入的相关性 | h e a d ∗ ( b s z , m a x _ l e n , d k / d v ) head*(bsz,max\_len,d_{k}/d_v) head∗(bsz,max_len,dk/dv) | h e a d ∗ ( b s z , m a x _ l e n , d v ) head*(bsz,max\_len,d_v) head∗(bsz,max_len,dv) | |
concat | 将多个维度(head)的结果级联起来 | h e a d ∗ ( b s z , m a x _ l e n , d v ) head*(bsz,max\_len,d_v) head∗(bsz,max_len,dv) | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
linear | 线性映射 | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
Add & Norm | 进行残差连接和层归一化 | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
Feed forward | x W 1 + b 1 xW_1+b_1 xW1+b1 | 升维(类似SVM中的升维效果) | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d f f bsz,max\_len,d_{ff} bsz,max_len,dff |
R e L U ( x W 1 + b 1 ) W 2 + b 2 ReLU(xW_1+b_1)W_2+b_2 ReLU(xW1+b1)W2+b2 | 降维 | b s z , m a x _ l e n , d f f bsz,max\_len,d_{ff} bsz,max_len,dff | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
Add & Norm | 进行残差连接和层归一化 | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel |
然后是decoder:
层 | 子层 | 作用 | 输入维度 | 输出维度 |
---|---|---|---|---|
embedding layer | 将ground truth转化为词嵌入 | b s z , m a x _ l e n bsz,max\_len bsz,max_len | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
positional encoding | 为词嵌入添加位置信息 | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
Masked Multi-head Attention | linear | 将词嵌入转化为多个维度(head)的Q、K、V | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d k / d v bsz,max\_len,d_{k}/d_v bsz,max_len,dk/dv |
masked dot-product | Q、K得到权重经过mask再与V进行sum | h e a d ∗ ( b s z , m a x _ l e n , d k / d v ) head*(bsz,max\_len,d_{k}/d_v) head∗(bsz,max_len,dk/dv) | h e a d ∗ ( b s z , m a x _ l e n , d v ) head*(bsz,max\_len,d_v) head∗(bsz,max_len,dv) | |
concat | 将多个维度(head)的结果级联起来 | h e a d ∗ ( b s z , m a x _ l e n , d v ) head*(bsz,max\_len,d_v) head∗(bsz,max_len,dv) | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
linear | 线性映射 | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
Add & Norm | 进行残差连接和层归一化 | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
Multi-head Attention | linear | 将词嵌入转化为多个维度(head)的Q、K、V | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d k / d v bsz,max\_len,d_{k}/d_v bsz,max_len,dk/dv |
scaled dot-product attention | encoder的结果作为Q、K,decoder结果作为V进行多头注意力 | h e a d ∗ ( b s z , m a x _ l e n , d k / d v ) head*(bsz,max\_len,d_{k}/d_v) head∗(bsz,max_len,dk/dv) | h e a d ∗ ( b s z , m a x _ l e n , d v ) head*(bsz,max\_len,d_v) head∗(bsz,max_len,dv) | |
concat | 将多个维度(head)的结果级联起来 | h e a d ∗ ( b s z , m a x _ l e n , d v ) head*(bsz,max\_len,d_v) head∗(bsz,max_len,dv) | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
linear | 线性映射 | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
Add & Norm | 进行残差连接和层归一化 | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
Feed forward | x W 1 + b 1 xW_1+b_1 xW1+b1 | 升维(类似SVM中的升维效果) | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d f f bsz,max\_len,d_{ff} bsz,max_len,dff |
R e L U ( x W 1 + b 1 ) W 2 + b 2 ReLU(xW_1+b_1)W_2+b_2 ReLU(xW1+b1)W2+b2 | 降维 | b s z , m a x _ l e n , d f f bsz,max\_len,d_{ff} bsz,max_len,dff | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | |
Add & Norm | 进行残差连接和层归一化 | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel | b s z , m a x _ l e n , d m o d e l bsz,max\_len,d_{model} bsz,max_len,dmodel |
4. 两大创新
Scaled Dot-Product Attention
Dot-Product Attention(点积注意力),是相对于Additive attention(加性注意力)而言的,顾名思义,Dot-Product Attention是说通过点积来计算两者之间的注意力分数,即相关性,在检索/匹配任务中很常见
注意力函数通常可以描述为,将一个查询query和键值key-value对集合映射为一个输出,这个输出是value的加权和,其权重通过计算query和key之间的相关度得出。而Scaled Dot-Product Attention就是用来计算query和key之间相关度的方式,描述为:
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
Attention(Q,K,V)=softmax(dkQKT)V
一般来说,为了在不同主体之间构建更公平的度量,会使用归一化的点积,即余弦相似度,两者之间的关系是: c o s ( θ ) = A ⋅ B ∣ ∣ A ∣ ∣ ∣ ∣ B ∣ ∣ cos(\theta)=\frac{A·B}{||A||||B||} cos(θ)=∣∣A∣∣∣∣B∣∣A⋅B. 而在transformer中,并没有像余弦相似度这样使用两个向量的长度来进行归一化,而是使用了softmax函数
而其中的 d k \sqrt{d_k} dk就是scaled的表现,这是由于直接使用softmax函数,会因为得到的 Q K T QK^T QKT值过大而引起梯度消失问题,于是可以加入scaled factor来避免梯度消失问题,因此称为Scaled Dot-Product Attention
Multi-Head Attention
严格来说,多头自注意力机制,还不具有完善的可解释性;其含义是,一组
Q
、
K
、
V
Q、K、V
Q、K、V可以从一个维度上构建相关性,而多组
Q
、
K
、
V
Q、K、V
Q、K、V可以从多个维度上构建相关性,而多个
Q
、
K
、
V
Q、K、V
Q、K、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
,
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,...,head_h)W^O, where\ head_i=Attention(QW_i^Q,KW_i^k,VW_i^V)
MultiHead(Q,K,V)=Concat(head1,...,headh)WO,where headi=Attention(QWiQ,KWik,VWiV)
也就是说,原本单头注意力只需要在
Q
、
K
、
V
Q、K、V
Q、K、V中进行Scaled Dot-Product Attention就可以了,现在多头注意力则需要先将
Q
、
K
、
V
Q、K、V
Q、K、V(
b
s
z
,
l
e
n
,
d
m
o
d
e
l
bsz,len, d_{model}
bsz,len,dmodel)分别进行
h
e
a
d
head
head次线性映射(
b
s
z
,
l
e
n
,
d
k
/
d
v
bsz,len, d_{k}/d_{v}
bsz,len,dk/dv),然后再映射得到的向量之间执行Scaled Dot-Product Attention得到输出(
b
s
z
,
l
e
n
,
d
k
/
d
v
bsz,len, d_{k}/d_{v}
bsz,len,dk/dv),最后将不同
h
e
a
d
head
head得到的输出concat起来
b
s
z
,
l
e
n
,
h
∗
d
k
/
d
v
bsz,len,h*d_{k}/d_{v}
bsz,len,h∗dk/dv,再变换维度到
b
s
z
,
l
e
n
,
d
m
o
d
e
l
bsz,len,d_{model}
bsz,len,dmodel. 上述过程如下图:
其实因为有最后一个线性层的存在,我们无需规定
d
k
,
d
v
,
d
m
o
d
e
l
,
h
e
a
d
d_k,d_v,d_{model},head
dk,dv,dmodel,head之间的关系,但作者在具体实施中规定:
d
k
=
d
v
=
d
m
o
d
e
l
/
h
e
a
d
=
64
,
h
e
a
d
=
8
d_k=d_v=d_{model}/head=64,head=8
dk=dv=dmodel/head=64,head=8
ViT
来自论文2021-ICLR-An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale
1. 动机
很简单的动机,作者认为CNN在视觉任务中不是必须的(其实就是看到transformer在nlp领域的成功,于是想要用到视觉领域,希望也能获得性能上的提升)
2. 结论
那扩展到视觉任务中有没有成功呢?结论是:
1)在缺乏强正则约束的情况下,当训练在中等大小的数据集,如ImageNet上时,ViT达到的性能比同等大小的ResNet达到的性能低几个点
作者认为这是由于transformer本身缺乏像CNN内在的归纳偏差,如平移不变性和局部性;而这个推断很值得深思,我们首先应该抱着怀疑的态度提出几个问题:CNN的归纳偏差什么含义?为什么CNN的归纳偏差可以帮助提点?transformer中就完全没有归纳偏差吗?
第一个问题)我曾经做过简单的调研,发布在【直觉建设】归纳偏差与选择性偏差
第二个问题)归纳偏差