目录
谷歌的Transformer模型最早是用于机器翻译任务,当时达到了SOTA效果。Transformer改进了RNN最被人诟病的训练慢的缺点,利用self-attention机制实现快速并行。并且Transformer可以增加到非常深的深度,充分发掘DNN模型的特性,提升模型准确率;Transformer由论文
《Attention is All You Need》
提出,现在被广泛应用于NLP的各个领域。目前在NLP各业务全面发展的模型如GPT,BERT等,都是基于Transformer模型
Seq2Seq的编码器-解码器架构与Attention机制
首先,关于Seq2Seq的Encoder-Decoder模型与Luong Attention机制原理及实现可回顾 第十二课Seq2Seq与Attention ;
以机器翻译(英文到中文)为例,在原始的Encoder-Decoder模型里,英文句子的信息被压缩在Encoder的输出 hidden state 里,这不可避免的造成大量信息损失,对翻译中文不利,引入注意力后,给原始Decoder的某个输出词向量融合了其对应的重要英文分词信息,能提升翻译出该中文分词的准确性;
注意力机制的本质是更针对性实现特征提取,即加权平均,发展至今,注意力也有了不同的分类;
柔性注意力 Soft Attention
输入信息 X = [ x 1 , x 2 , . . . , x N ] X=[x_{1},x_{2},...,x_{N}] X=[x1,x2,...,xN],注意力计算过程如下:
- 1.在输入信息上计算注意力分布;
- 2.根据注意力分布计算输入信息的加权平均;
注意力分布
给定一个和任务相关的查询向量
q
q
q,用注意力变量
z
∈
[
1
,
N
]
z\in [1,N]
z∈[1,N] 表示被选择信息的索引位置,即
z
=
i
z=i
z=i 表示选择了第
i
i
i 个输入信息,其中查询向量
q
q
q 可以是动态生成的,也可以是可学习的参数;通常在Seq2Seq中,查询向量会使用当前模型的输出信息(比如Encoder-Decoder当前输出词对应的词向量);
在给定输入信息
X
X
X 和查询向量
q
q
q 后,选择第
i
i
i 个输入信息的概率:
a
i
=
P
(
z
=
i
∣
X
,
q
)
=
s
o
f
t
m
a
x
(
s
c
o
r
e
(
x
i
,
q
)
)
=
e
x
p
(
s
c
o
r
e
(
x
i
,
q
)
)
∑
j
=
1
N
e
x
p
(
s
c
o
r
e
(
x
j
,
q
)
)
a_{i}=P(z=i|X,q)=softmax(score(x_{i},q))=\frac{exp(score(x_{i},q))}{\sum_{j=1}^{N}exp(score(x_{j},q))}
ai=P(z=i∣X,q)=softmax(score(xi,q))=∑j=1Nexp(score(xj,q))exp(score(xi,q))
其中,
a
i
a_{i}
ai 称为注意力分布,反映提取信息
x
i
x_{i}
xi 的程度,
s
c
o
r
e
(
x
i
,
q
)
score(x_{i},q)
score(xi,q) 为注意力打分函数;
打分函数有不同的形式:
- 加性模型
s c o r e ( x i , q ) = v T t a n h ( W x i + U q ) score(x_{i},q)=v^{T}tanh(Wx_{i}+Uq) score(xi,q)=vTtanh(Wxi+Uq) - 点积模型(常用)
s c o r e ( x i , q ) = x i T q score(x_{i},q)=x_{i}^{T}q score(xi,q)=xiTq - 缩放点积模型(常用)
s c o r e ( x i , q ) = x i T q d score(x_{i},q)=\frac{x_{i}^{T}q}{\sqrt{d}} score(xi,q)=d xiTq - 双线性模型
s c o r e ( x i , q ) = x i T W q score(x_{i},q)=x_{i}^{T}Wq score(xi,q)=xiTWq
其中, [ W , U , v ] [W,U,v] [W,U,v]为待学习参数, d d d 为输入信息的维度。点积模型的计算效率更高,当输入信息 x i x_{i} xi 的维度维度 d d d 较大,可以通过缩放点积平衡数值。注意力分布可解释为在给定查询向量下,第 i i i 个信息的受关注程度;
加权平均
基于注意力分布和输入信息,得到:
a
t
t
n
(
X
,
q
)
=
∑
i
=
1
N
a
i
x
i
attn(X,q)=\sum_{i=1}^{N}a_{i}x_{i}
attn(X,q)=i=1∑Naixi
即:
在软注意力中,输入信息一方面要用于计算注意力,另一方面是被注意力提取的对象,这对输入信息来说,负担过重。因此,提出了键值对注意力;
键值对注意力 Key-Value Pair Attention
输入信息为:
(
K
,
V
)
=
[
(
k
1
,
v
1
)
,
(
k
2
,
v
2
)
,
.
.
.
,
(
k
N
,
v
N
)
]
(K,V)=[(k_{1},v_{1}),(k_{2},v_{2}),...,(k_{N},v_{N})]
(K,V)=[(k1,v1),(k2,v2),...,(kN,vN)]
其中,键用于计算注意力分布
a
i
a_{i}
ai,值用来计算聚合信息,通常值
V
V
V 即为输入信息
X
X
X;
K
K
K 对应的信息不固定,只要是和
V
V
V 有关系的对象均可以做为
K
K
K;
给定查询向量
q
q
q ,注意力分布为:
a
i
=
e
x
p
(
s
c
o
r
e
(
k
i
,
q
)
)
∑
j
=
1
N
e
x
p
(
s
c
o
r
e
(
k
j
,
q
)
)
a_{i}=\frac{exp(score(k_{i},q))}{\sum_{j=1}^{N}exp(score(k_{j},q))}
ai=∑j=1Nexp(score(kj,q))exp(score(ki,q))
加权平均:
a
t
t
n
(
(
K
,
V
)
,
q
)
=
∑
i
=
1
N
a
i
v
i
attn((K,V),q)=\sum_{i=1}^{N}a_{i}v_{i}
attn((K,V),q)=i=1∑Naivi
当
K
=
V
K=V
K=V 时,键值对注意力就是柔性注意力;
自注意力 Self-Attention
在键值对注意力中,有两个量
(
K
,
q
)
(K,q)
(K,q)比较模糊,没有一个统一的标准,于是提出自注意力机制,输入序列为:
X
=
[
x
1
,
x
2
,
.
.
.
,
x
N
]
∈
R
d
1
×
N
X=[x_{1},x_{2},...,x_{N}]\in R^{d_{1}\times N}
X=[x1,x2,...,xN]∈Rd1×N
输出序列为:
H
=
[
h
1
,
h
2
,
.
.
.
,
h
N
]
∈
R
d
2
×
N
H=[h_{1},h_{2},...,h_{N}]\in R^{d_{2}\times N}
H=[h1,h2,...,hN]∈Rd2×N
通过线性变换得到向量序列:
Q
=
W
Q
X
∈
R
d
3
×
N
Q=W_{Q}X\in R^{d_{3}\times N}
Q=WQX∈Rd3×N
K
=
W
K
X
∈
R
d
3
×
N
K=W_{K}X\in R^{d_{3}\times N}
K=WKX∈Rd3×N
V
=
W
V
X
∈
R
d
2
×
N
V=W_{V}X\in R^{d_{2}\times N}
V=WVX∈Rd2×N
其中,
[
Q
,
K
,
V
]
[Q,K,V]
[Q,K,V] 分别为查询向量,键向量,值向量;
[
W
Q
,
W
K
,
W
V
]
[W_{Q},W_{K},W_{V}]
[WQ,WK,WV]为待学习参数;
预测输出向量:
h
^
i
=
a
t
t
n
(
(
K
,
V
)
,
q
i
)
=
∑
j
=
1
N
a
i
,
j
v
j
=
∑
j
=
1
N
s
o
f
t
m
a
x
(
s
c
o
r
e
(
k
j
,
q
i
)
)
v
j
\widehat{h}_{i}=attn((K,V),q_{i})=\sum_{j=1}^{N}a_{i,j}v_{j}=\sum_{j=1}^{N}softmax(score(k_{j},q_{i}))v_{j}
h
i=attn((K,V),qi)=j=1∑Nai,jvj=j=1∑Nsoftmax(score(kj,qi))vj
当使用缩放点积打分时,输出向量序列为:
H
d
2
×
N
=
W
V
X
s
o
f
t
m
a
x
(
K
T
Q
d
3
,
a
x
i
s
=
−
1
)
H_{d_{2}\times N}=W_{V}Xsoftmax(\frac{K^{T}Q}{\sqrt{d_{3}}},axis=-1)
Hd2×N=WVXsoftmax(d3
KTQ,axis=−1)
pytorch 中softmax函数举例:
import torch
import torch.nn as nn
mat=torch.randn(2,2)
print(mat,mat.size())
softmax=nn.Softmax(dim=1)
output=softmax(mat)
print(output,output.size())
"""
tensor([[ 0.0081, 0.1971],
[-0.2666, -1.0529]]) torch.Size([2, 2])
tensor([[0.4529, 0.5471],
[0.6870, 0.3130]]) torch.Size([2, 2])
"""
axis=-1
即dim=-1
,即在最后一维上操作,在(2,2)
的张量上,体现为沿着列轴计算softmax:
0.4529
=
e
x
p
(
0.0081
)
e
x
p
(
0.0081
)
+
e
x
p
(
0.1971
)
0.4529=\frac{exp(0.0081)}{exp(0.0081)+exp(0.1971)}
0.4529=exp(0.0081)+exp(0.1971)exp(0.0081)
多头注意力 Multi-Head Attention
多头注意力的本质其实就是自注意力:
a
t
t
n
(
(
K
,
V
)
,
Q
)
=
a
t
t
n
(
(
K
,
V
)
,
q
1
)
⊕
a
t
t
n
(
(
K
,
V
)
,
q
2
)
⊕
.
.
.
⊕
a
t
t
n
(
(
K
,
V
)
,
q
N
)
attn((K,V),Q)=attn((K,V),q_{1})\oplus attn((K,V),q_{2})\oplus ...\oplus attn((K,V),q_{N})
attn((K,V),Q)=attn((K,V),q1)⊕attn((K,V),q2)⊕...⊕attn((K,V),qN)
其中的
⊕
\oplus
⊕ 表示张量拼接
Transformer通用特征提取器
Transformer是一种架构,目的是用于实现一种通用的特征提取器。模型架构如下:
模型有两个输入,一个输出,左部被称为编码器,右部被称为解码器。左边的输入为源序列,右边输入为目标预测单词前的前序序列,比如英文到中文问题,目标序列是"我需要它",当前的预测词为"它",则前序序列为"我需要";
图中的 N × N\times N× 表示网络的堆叠,图中的灰色部分表示一层单元(比如左边的Encoder单元和右边的Decoder单元),加深网络可以通过重复堆叠单元实现。
输入,目标,输出序列
输入序列,
i
q
∈
R
N
i_{q}\in R^{N}
iq∈RN反映了该词在词汇表中的序号(one-hot编码)
i
n
p
u
t
s
=
[
i
1
,
i
2
,
.
.
.
,
i
N
]
inputs=[i_{1},i_{2},...,i_{N}]
inputs=[i1,i2,...,iN]
目标序列,
t
q
∈
R
T
a
r
g
e
t
V
o
c
a
b
S
i
z
e
t_{q}\in R^{TargetVocabSize}
tq∈RTargetVocabSize反映了该词在词汇表中的序号(one-hot编码)
t
a
r
g
e
t
s
=
[
t
1
,
t
2
,
.
.
.
,
t
M
]
targets=[t_{1},t_{2},...,t_{M}]
targets=[t1,t2,...,tM]
其中还有
o
u
t
p
u
t
s
p
r
o
b
a
b
i
l
i
t
i
e
s
=
T
r
a
n
s
f
o
r
m
e
r
(
i
n
p
u
t
s
,
t
a
r
g
e
t
s
)
=
(
o
1
,
o
2
,
.
.
.
,
o
M
)
outputs_{probabilities}=Transformer(inputs,targets)=(o_{1},o_{2},...,o_{M})
outputsprobabilities=Transformer(inputs,targets)=(o1,o2,...,oM)
o
u
t
p
u
t
s
p
r
o
b
a
b
i
l
i
t
i
e
s
outputs_{probabilities}
outputsprobabilities为预测结果,
o
q
∈
R
T
a
r
g
e
t
V
o
c
a
b
S
i
z
e
o_{q}\in R^{TargetVocabSize}
oq∈RTargetVocabSize反映了词汇表中词的概率;
词嵌入与位置信息融合
输入序列词嵌入为:
E
m
b
e
d
d
i
n
g
(
i
n
p
u
t
s
)
∈
R
N
,
d
m
o
d
e
l
Embedding(inputs)\in R^{N,d_{model}}
Embedding(inputs)∈RN,dmodel
其中,
N
N
N为输入序列长度,
d
m
o
d
e
l
d_{model}
dmodel为词嵌入维度,输入序列位置编码为:
P
o
s
E
n
c
(
p
o
s
t
i
o
n
i
n
p
u
t
s
)
∈
R
N
,
d
m
o
d
e
l
PosEnc(postion_{inputs})\in R^{N,d_{model}}
PosEnc(postioninputs)∈RN,dmodel
其中,
p
o
s
t
i
o
n
i
n
p
u
t
s
=
(
1
,
2
,
.
.
.
,
p
,
.
.
.
,
N
)
postion_{inputs}=(1,2,...,p,...,N)
postioninputs=(1,2,...,p,...,N) 为各个字符在句子中对应的位置序号;
位置编码计算为:
P
o
s
E
n
c
(
p
o
s
,
2
i
)
=
s
i
n
(
p
o
s
1000
0
2
i
/
d
m
o
d
e
l
)
,
P
o
s
E
n
c
(
p
o
s
,
2
i
+
1
)
=
c
o
s
(
p
o
s
1000
0
2
i
/
d
m
o
d
e
l
)
PosEnc(pos,2i)=sin(\frac{pos}{10000^{2i/d_{model}}}),PosEnc(pos,2i+1)=cos(\frac{pos}{10000^{2i/d_{model}}})
PosEnc(pos,2i)=sin(100002i/dmodelpos),PosEnc(pos,2i+1)=cos(100002i/dmodelpos)
其中,
p
o
s
∈
p
o
s
t
i
o
n
i
n
p
u
t
s
pos\in postion_{inputs}
pos∈postioninputs,
i
∈
(
0
,
1
,
.
.
.
,
d
m
o
d
e
l
/
2
)
i\in (0,1,...,d_{model}/2)
i∈(0,1,...,dmodel/2);
融合位置信息的目的:注意力机制没有考虑单词的位置信息,而是单纯的加权平均,所以在Transformer中添加了位置信息
将词嵌入与位置信息融合:
E
m
b
e
d
d
i
n
g
(
i
n
p
u
t
s
)
+
P
o
s
E
n
c
(
p
o
s
t
i
o
n
i
n
p
u
t
s
)
Embedding(inputs)+PosEnc(postion_{inputs})
Embedding(inputs)+PosEnc(postioninputs)
同样的,目标序列也进行对应的融合:
E
m
b
e
d
d
i
n
g
(
t
a
r
g
e
t
s
)
+
P
o
s
E
n
c
(
p
o
s
t
i
o
n
t
a
r
g
e
t
s
)
Embedding(targets)+PosEnc(postion_{targets})
Embedding(targets)+PosEnc(postiontargets)
编码器
编码器的计算为:
e
0
=
E
m
b
e
d
d
i
n
g
(
i
n
p
u
t
s
)
+
P
o
s
E
n
c
(
p
o
s
t
i
o
n
i
n
p
u
t
s
)
e_{0}=Embedding(inputs)+PosEnc(postion_{inputs})
e0=Embedding(inputs)+PosEnc(postioninputs)
e
l
=
E
n
c
o
d
e
r
L
a
y
e
r
(
e
l
−
1
)
,
l
∈
[
1
,
n
]
e_{l}=EncoderLayer(e_{l-1}),l\in [1,n]
el=EncoderLayer(el−1),l∈[1,n]
其中,
e
0
∈
R
N
,
d
m
o
d
e
l
e_{0}\in R^{N,d_{model}}
e0∈RN,dmodel为编码器输入,
n
n
n为编码器层数,
e
l
e_{l}
el为第
l
l
l层编码器的输出;
编码器
E
n
c
o
d
e
r
L
a
y
e
r
EncoderLayer
EncoderLayer:
e
m
i
d
=
L
a
y
e
r
N
o
r
m
(
e
i
n
+
M
u
l
t
i
H
e
a
d
A
t
t
e
n
t
i
o
n
(
e
i
n
)
)
e_{mid}=LayerNorm(e_{in}+MultiHeadAttention(e_{in}))
emid=LayerNorm(ein+MultiHeadAttention(ein))
e
o
u
t
=
L
a
y
e
r
N
o
r
m
(
e
m
i
d
+
F
F
N
(
e
m
i
d
)
)
e_{out}=LayerNorm(e_{mid}+FFN(e_{mid}))
eout=LayerNorm(emid+FFN(emid))
其中,
e
i
n
∈
R
N
,
d
m
o
d
e
l
e_{in}\in R^{N,d_{model}}
ein∈RN,dmodel为编码器层输入,
e
o
u
t
∈
R
N
,
d
m
o
d
e
l
e_{out}\in R^{N,d_{model}}
eout∈RN,dmodel为编码器层输出,
M
u
l
t
i
H
e
a
d
A
t
t
e
n
t
i
o
n
MultiHeadAttention
MultiHeadAttention为多头注意力机制,
F
F
N
FFN
FFN为前馈神经网络,
L
a
y
e
r
N
o
r
m
LayerNorm
LayerNorm为层归一化;
图中的多头注意力机制输入有三条支路,代表了三个待学习参数 [ W Q , W K , W V ] [W_{Q},W_{K},W_{V}] [WQ,WK,WV]
关于Transformer的缩放点积和多头注意力机制:
注意左图的
[
Q
,
K
,
V
]
[Q,K,V]
[Q,K,V]是右图
[
Q
,
K
,
V
]
[Q,K,V]
[Q,K,V]经过线性变换得到的;
输入向量序列 e i n = [ e i n 1 , e i n 2 , . . . , e i n N ] ∈ R N , d m o d e l e_{in}=[e_{in1},e_{in2},...,e_{inN}]\in R^{N,d_{model}} ein=[ein1,ein2,...,einN]∈RN,dmodel,分别得到查询向量序列 Q = e i n Q=e_{in} Q=ein,键向量序列 K = e i n K=e_{in} K=ein,值向量序列 V = e i n V=e_{in} V=ein;
使用缩放点积打分的多头注意力机制:
M
u
l
t
i
H
e
a
d
A
t
t
e
n
t
i
o
n
(
e
i
n
)
=
C
o
n
c
a
t
(
h
e
a
d
1
,
.
.
.
,
h
e
a
d
h
)
W
O
MultiHeadAttention(e_{in})=Concat(head_{1},...,head_{h})W_{O}
MultiHeadAttention(ein)=Concat(head1,...,headh)WO
其中,多头输出:
h
e
a
d
i
=
A
t
t
e
n
t
i
o
n
(
Q
W
Q
,
i
,
K
W
K
,
i
,
V
W
V
,
i
)
=
s
o
f
t
m
a
x
(
Q
W
Q
,
i
(
K
W
K
,
i
)
T
d
K
)
V
W
V
,
i
head_{i}=Attention(QW_{Q,i},KW_{K,i},VW_{V,i})=softmax(\frac{QW_{Q,i}(KW_{K,i})^{T}}{\sqrt{d_{K}}})VW_{V,i}
headi=Attention(QWQ,i,KWK,i,VWV,i)=softmax(dK
QWQ,i(KWK,i)T)VWV,i
可学习的参数为:
[
W
Q
,
i
∈
R
d
m
o
d
e
l
,
d
K
,
W
K
,
i
∈
R
d
m
o
d
e
l
,
d
K
,
W
V
,
i
∈
R
d
m
o
d
e
l
,
d
V
,
W
O
∈
R
h
⋅
d
V
,
d
m
o
d
e
l
]
[W_{Q,i}\in R^{d_{model},d_{K}},W_{K,i}\in R^{d_{model},d_{K}},W_{V,i}\in R^{d_{model},d_{V}},W_{O}\in R^{h\cdot d_{V},d_{model}}]
[WQ,i∈Rdmodel,dK,WK,i∈Rdmodel,dK,WV,i∈Rdmodel,dV,WO∈Rh⋅dV,dmodel]
Mask操作可以省略,Mask操作是为了保留非填充(pad)的词
前馈神经网络为全连接网络,两层网络如下:
F
F
N
(
e
m
i
d
)
=
R
e
L
U
(
e
m
i
d
W
1
+
b
1
)
W
2
+
b
2
FFN(e_{mid})=ReLU(e_{mid}W_{1}+b_{1})W_{2}+b_{2}
FFN(emid)=ReLU(emidW1+b1)W2+b2
解码器
d
0
=
E
m
b
e
d
d
i
n
g
(
t
a
r
g
e
t
s
)
+
P
o
s
E
n
c
(
p
o
s
t
i
o
n
t
a
r
g
e
t
s
)
d_{0}=Embedding(targets)+PosEnc(postion_{targets})
d0=Embedding(targets)+PosEnc(postiontargets)
d
l
=
D
e
c
o
d
e
r
L
a
y
e
r
(
d
l
−
1
)
,
l
∈
[
1
,
n
]
d_{l}=DecoderLayer(d_{l-1}),l\in [1,n]
dl=DecoderLayer(dl−1),l∈[1,n]
o
u
t
p
u
t
s
p
r
o
b
a
b
i
l
i
t
i
e
s
=
s
o
f
t
m
a
x
(
d
n
W
)
outputs_{probabilities}=softmax(d_{n}W)
outputsprobabilities=softmax(dnW)
其中,
d
0
∈
R
M
,
d
m
o
d
e
l
d_{0}\in R^{M,d_{model}}
d0∈RM,dmodel为解码器的输入,
d
l
∈
R
M
,
d
m
o
d
e
l
d_{l}\in R^{M,d_{model}}
dl∈RM,dmodel为解码器第
l
l
l层的输出,
W
∈
R
d
m
o
d
e
l
,
T
a
r
g
e
t
V
o
c
a
b
S
i
z
e
W\in R^{d_{model},TargetVocabSize}
W∈Rdmodel,TargetVocabSize;
从模型公式看出,不同于第十二课的Encoder-Decoder每次预测一个词,Transformer的结构使模型直接预测一整句话
解码器层
D
e
c
o
d
e
r
L
a
y
e
r
DecoderLayer
DecoderLayer:
d
m
i
d
1
=
L
a
y
e
r
N
o
r
m
(
d
i
n
+
M
a
s
k
e
d
M
u
l
t
i
H
e
a
d
A
t
t
e
n
t
i
o
n
(
d
i
n
)
)
d_{mid1}=LayerNorm(d_{in}+MaskedMultiHeadAttention(d_{in}))
dmid1=LayerNorm(din+MaskedMultiHeadAttention(din))
d
m
i
d
2
=
L
a
y
e
r
N
o
r
m
(
d
m
i
d
1
+
M
u
l
t
i
H
e
a
d
A
t
t
e
n
t
i
o
n
(
d
m
i
d
1
,
e
o
u
t
)
)
d_{mid2}=LayerNorm(d_{mid1}+MultiHeadAttention(d_{mid1},e_{out}))
dmid2=LayerNorm(dmid1+MultiHeadAttention(dmid1,eout))
d
o
u
t
=
L
a
y
e
r
N
o
r
m
(
d
m
i
d
2
+
F
F
N
(
d
m
i
d
2
)
)
d_{out}=LayerNorm(d_{mid2}+FFN(d_{mid2}))
dout=LayerNorm(dmid2+FFN(dmid2))
其中,
d
i
n
∈
R
M
,
d
m
o
d
e
l
d_{in}\in R^{M,d_{model}}
din∈RM,dmodel为解码器输入,
d
o
u
t
∈
R
M
,
d
m
o
d
e
l
d_{out}\in R^{M,d_{model}}
dout∈RM,dmodel为解码器输出;
由于解码器的目标序列是逐渐递增的输入,在预测当前词时,使用 M a s k e d M u l t i H e a d A t t e n t i o n MaskedMultiHeadAttention MaskedMultiHeadAttention遮挡住后序目标序列;由于逐个词向后预测,可以想象到解码器内的 M a s k Mask Mask矩阵是非零元素为1的三角矩阵