一、基本框架
Transformer模型是Google在2017年的论文《Attention is all you need》中提出的一种模型。Transformer之前的Seq2Seq的模型中,Encoder和Decoder中的基本单元结构是RNN系列(如LSTM,GRU等)的单元。但在Transformer中并没有使用这些单元结构。
首先来说一下transformer和LSTM的最大区别, 就是LSTM的训练是迭代的, 是一个接一个字的来, 当前这个字过完LSTM单元, 才可以进下一个字, 而transformer的训练是并行了, 就是所有字是全部同时训练的, 这样就大大加快了计算效率, transformer使用了位置嵌入(𝑝𝑜𝑠𝑖𝑡𝑖𝑜𝑛𝑎𝑙 𝑒𝑛𝑐𝑜𝑑𝑖𝑛𝑔)来理解语言的顺序, 使用自注意力机制和全连接层来进行计算, 这些后面都会详细讲解.
transformer模型主要分为两大部分, 分别是编码器和解码器, 编码器负责把自然语言序列映射成为隐藏层(下图中第2步用九宫格比喻的部分), 含有自然语言序列的数学表达. 然后解码器把隐藏层再映射为自然语言序列, 从而使我们可以解决各种问题, 如情感分类, 命名实体识别, 语义关系抽取, 摘要生成, 机器翻译等等, 下面我们简单说一下下图的每一步都做了什么:
1、输入自然语言序列到编码器: Why do we work?(为什么要工作); 2、编码器输出编码后的隐藏层, 再输入到解码器; 3、输入<𝑠𝑡𝑎𝑟𝑡>(起始)符号到解码器; 4、得到第一个字"为"; 5、将得到的第一个字"为"落下来再输入到解码器; 6、得到第二个字"什"; 7、将得到的第二字再落下来, 直到解码器输出<𝑒𝑛𝑑>(终止符), 即序列生成完成.
二、编码结构
编码过程是一个把自然语言序列映射称为相关数学表达的一个过程,属于上游任务。 上游任务:将自然语言序列编码为数学表达; 下游任务:将编码映射为自然语言序列如情感分类, 命名实体识别, 语义关系抽取, 摘要生成, 机器翻译等等。
Transformer的编码结构如下,可以分为4个部分,分别是: 1、𝑝𝑜𝑠𝑖𝑡𝑖𝑜𝑛𝑎𝑙 𝑒𝑛𝑐𝑜𝑑𝑖𝑛𝑔, 即位置嵌入(或位置编码); 2、𝑠𝑒𝑙𝑓 𝑎𝑡𝑡𝑒𝑛𝑡𝑖𝑜𝑛 , 自注意力机制; 3、Add & Norm 4、Feed Forward.
2.1 、𝑝𝑜𝑠𝑖𝑡𝑖𝑜𝑛𝑎𝑙 𝑒𝑛𝑐𝑜𝑑𝑖𝑛𝑔
transformer模型没有循环神经网络的迭代操作,所以必须提供每个字的位置信息给transformer, 这样才能识别出语言中的顺序关系。
但要怎么编码呢?
一种简单的想法是直接按顺序编码:E=pos=0,1,2,….,T-1 ,但这样会导致数值过大、干扰字嵌入结果和模型 。 那就给上面的编码统一除以长度,变成:E=pos/(T-1),这样就到了[0,1]区间之内,但也不行,因为这样的话长短文本的编码步长就会存在较大的差异。
经过前面2种实验,我们发现位置编码有两个要求: 1、要体现不同位置的编码区别; 2、编码的差异不应该依赖于文本的长度。
在这里论文中使用了
s i n e
s
i
n
e
sine
s i n e 和
c o s i n e
c
o
s
i
n
e
cosine
c o s i n e 函数的线性变换来提供给模型位置信息:
P E ( p o s , 2 i ) = s i n ( p o s / 1000 0 2 i / d model )
P
E
(
p
o
s
,
2
i
)
=
s
i
n
(
p
o
s
/
1000
0
2
i
/
d
model
)
PE_{(pos,2i)} = sin(pos / 10000^{2i/d_{\text{model}}})
P E ( p o s , 2 i ) = s i n ( p o s / 1 0 0 0 0 2 i / d model )
P E ( p o s , 2 i + 1 ) = c o s ( p o s / 1000 0 2 i / d model )
P
E
(
p
o
s
,
2
i
+
1
)
=
c
o
s
(
p
o
s
/
1000
0
2
i
/
d
model
)
PE_{(pos,2i+1)} = cos(pos / 10000^{2i/d_{\text{model}}})
P E ( p o s , 2 i + 1 ) = c o s ( p o s / 1 0 0 0 0 2 i / d model )
上式中
p o s
p
o
s
pos
p o s 指的是句中字的位置, 取值范围是
[ 0 , m a x s e q u e n c e l e n g t h )
[
0
,
m
a
x
s
e
q
u
e
n
c
e
l
e
n
g
t
h
)
[0, \ max \ sequence \ length)
[ 0 , m a x s e q u e n c e l e n g t h ) ,
i
i
i
i 指的是词向量的维度, 取值范围是
[ 0 , e m b e d d i n g d i m e n s i o n )
[
0
,
e
m
b
e
d
d
i
n
g
d
i
m
e
n
s
i
o
n
)
[0, \ embedding \ dimension)
[ 0 , e m b e d d i n g d i m e n s i o n ) 。
上面有
s i n
s
i
n
sin
s i n 和
c o s
c
o
s
cos
c o s 一组公式, 也就是对应着
e m b e d d i n g d i m e n s i o n
e
m
b
e
d
d
i
n
g
d
i
m
e
n
s
i
o
n
embedding \ dimension
e m b e d d i n g d i m e n s i o n 维度的一组奇数和偶数的序号的维度, 例如
0 , 1
0
,
1
0, 1
0 , 1 一组,
2 , 3
2
,
3
2, 3
2 , 3 一组, 分别用上面的
s i n
s
i
n
sin
s i n 和
c o s
c
o
s
cos
c o s 函数做处理, 从而产生不同的周期性变化, 而位置嵌入在
e m b e d d i n g d i m e n s i o n
e
m
b
e
d
d
i
n
g
d
i
m
e
n
s
i
o
n
embedding \ dimension
e m b e d d i n g d i m e n s i o n 维度上随着维度序号增大, 周期变化会越来越慢, 而产生一种包含位置信息的纹理。 上图展示了编码维度和语句长度之间的关系。
2.2 、self attention机制
Self-Attention 的 Query=Key=Value,即 Q,K,V 三个矩阵都来自同一个输入,而 Attention 计算过程如何呢? Attention 机制实质上就是一个寻址过程,通过给定一个任务相关的查询 Query 向量 Q,通过计算与 Key 的注意力分布并附加在 Value 上,从而计算 Attention Value,这个过程实际上是 Attention 缓解神经网络复杂度的体现,不需要将所有的 N 个输入都输入到神经网络进行计算,而是选择一些与任务相关的信息输入神经网络,与 RNN 中的门控机制思想类似。
Attention 机制实质上就是一个寻址过程,通过给定一个任务相关的查询 Query 向量 Q,通过计算与 Key 的注意力分布并附加在 Value 上,从而计算 Attention Value,这个过程实际上是 Attention 缓解神经网络复杂度的体现,不需要将所有的 N 个输入都输入到神经网络进行计算,而是选择一些与任务相关的信息输入神经网络,与 RNN 中的门控机制思想类似。
Attention 机制计算过程大致可以分成三步:
① 信息输入:将 Q,K,V 输入模型 用
X = [ x 1 , x 2 , ⋯ , x n ]
X
=
[
x
1
,
x
2
,
⋯
,
x
n
]
X=[x_1,x_2,\cdots,x_n]
X = [ x 1 , x 2 , ⋯ , x n ] 表示输入权重向量
② 计算注意力分布 α:通过计算 Q 和 K 进行点积计算相关度,并通过 softmax 计算分数 令
Q = K = V = X
Q
=
K
=
V
=
X
Q=K=V=X
Q = K = V = X ,通过 softmax 计算注意力权重,
α i = s o f t m a x ( s ( k i , q ) ) = s o f t m a x ( s ( x i , q ) )
α
i
=
s
o
f
t
m
a
x
(
s
(
k
i
,
q
)
)
=
s
o
f
t
m
a
x
(
s
(
x
i
,
q
)
)
α_i=softmax(s(k_i,q))=softmax(s(x_i, q))
α i = s o f t m a x ( s ( k i , q ) ) = s o f t m a x ( s ( x i , q ) ) 我们将
α i
α
i
α_i
α i 称之为注意力概率分布,
s ( x i , q )
s
(
x
i
,
q
)
s(x_i, q)
s ( x i , q ) 为注意力打分机制,常见的有如下几种: 加性模型:
s ( x i , q ) = v T t a n h ( W x i + U q )
s
(
x
i
,
q
)
=
v
T
t
a
n
h
(
W
x
i
+
U
q
)
s(x_i,q)=v^Ttanh(Wx_i+Uq)
s ( x i , q ) = v T t a n h ( W x i + U q ) 点积模型:
s ( x i , q ) = x T i q
s
(
x
i
,
q
)
=
x
i
T
q
s(x_i,q)=x_i^Tq
s ( x i , q ) = x i T q 缩放点积模型:
s ( x i , q ) = x T i q / d k − − √
s
(
x
i
,
q
)
=
x
i
T
q
/
d
k
s(x_i,q)={x_i^Tq}/\sqrt{d_k}
s ( x i , q ) = x i T q / d k
双线性模型:
s ( x i , q ) = x T i W q
s
(
x
i
,
q
)
=
x
i
T
W
q
s(x_i,q)=x_i^TWq
s ( x i , q ) = x i T W q ③ 信息加权平均:注意力分布
α i
α
i
α_i
α i 来解释在上下文查询
q i
q
i
q_i
q i 时,第
i
i
i
i 个信息受关注程度。
a t t ( q , X ) = ∑ N i = 1 α i X i
a
t
t
(
q
,
X
)
=
∑
i
=
1
N
α
i
X
i
att(q,X)=\sum_{i=1}^N{α_iX_i}
a t t ( q , X ) = ∑ i = 1 N α i X i
上面讲述了 Attention 的通用计算过程,也讲述了注意力分数计算的多种选择,那么在 Transformer 中,采用哪种呢?答案就是:Scaled Dot-Product Attention 运算的过程可以表示成下图形式:
如上图展示的一样,我们在得到位置编码后,会生成[batch_size,seq_len,embed_dim]形式的矩阵,假设embed_dim=9,我们拿出来1个具有6个字符(seq_len=6)的语句,它的编码矩阵如上图第一个矩阵所示。
可以看出我们把它根据3个不同权重的矩阵线性的转化为了3个矩阵:Q、K、V。 设置head=3,然后每个矩阵接着继续划分为3个小矩阵(9/3=3),然后使用Q的一个小矩阵乘以一个K的小矩阵的转置,然后经过softmax归一化之后与V的小矩阵相乘。(图中未展示与V相乘的过程) 用于计算注意力权重的等式为:
A t t e n t i o n ( Q , K , V ) = s o f t m a x k ( Q K T d k − − √ ) V
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
=
s
o
f
t
m
a
x
k
(
Q
K
T
d
k
)
V
\Large{Attention(Q, K, V) = softmax_k(\frac{QK^T}{\sqrt{d_k}}) V}
A t t e n t i o n ( Q , K , V ) = s o f t m a x k ( d k
Q K T ) V
2.3、Add&Norm
1). 残差连接 : 我们在上一步得到了经过注意力矩阵加权之后的
V
V
V
V , 也就是
A t t e n t i o n ( Q , K , V )
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
Attention(Q, \ K, \ V)
A t t e n t i o n ( Q , K , V ) , 我们对它进行一下转置, 使其和
X e m b e d d i n g
X
e
m
b
e
d
d
i
n
g
X_{embedding}
X e m b e d d i n g 的维度一致, 也就是
[ b a t c h s i z e , s e q u e n c e l e n g t h , e m b e d d i n g d i m e n s i o n ]
[
b
a
t
c
h
s
i
z
e
,
s
e
q
u
e
n
c
e
l
e
n
g
t
h
,
e
m
b
e
d
d
i
n
g
d
i
m
e
n
s
i
o
n
]
[batch \ size, \ sequence \ length, \ embedding \ dimension]
[ b a t c h s i z e , s e q u e n c e l e n g t h , e m b e d d i n g d i m e n s i o n ] , 然后把他们加起来做残差连接, 直接进行元素相加, 因为他们的维度一致:
X e m b e d d i n g + A t t e n t i o n ( Q , K , V )
X
e
m
b
e
d
d
i
n
g
+
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
X_{embedding} + Attention(Q, \ K, \ V)
X e m b e d d i n g + A t t e n t i o n ( Q , K , V ) 在之后的运算里, 每经过一个模块的运算, 都要把运算之前的值和运算之后的值相加, 从而得到残差连接, 训练的时候可以使梯度直接走捷径反传到最初始层:
X + S u b L a y e r ( X )
X
+
S
u
b
L
a
y
e
r
(
X
)
X + SubLayer(X)
X + S u b L a y e r ( X )
2).
L a y e r N o r m
L
a
y
e
r
N
o
r
m
LayerNorm
L a y e r N o r m :
L a y e r N o r m a l i z a t i o n
L
a
y
e
r
N
o
r
m
a
l
i
z
a
t
i
o
n
Layer Normalization
L a y e r N o r m a l i z a t i o n 的作用是把神经网络中隐藏层归一为标准正态分布, 也就是
i . i . d
i
.
i
.
d
i.i.d
i . i . d 独立同分布, 以起到加快训练速度, 加速收敛的作用:
μ i = 1 m ∑ m i = 1 x i j
μ
i
=
1
m
∑
i
=
1
m
x
i
j
\mu_{i}=\frac{1}{m} \sum^{m}_{i=1}x_{ij}
μ i = m 1 i = 1 ∑ m x i j 上式中以矩阵的行
( r o w )
(
r
o
w
)
(row)
( r o w ) 为单位求均值;
σ 2 j = 1 m ∑ m i = 1 ( x i j − μ j ) 2
σ
j
2
=
1
m
∑
i
=
1
m
(
x
i
j
−
μ
j
)
2
\sigma^{2}_{j}=\frac{1}{m} \sum^{m}_{i=1}(x_{ij}-\mu_{j})^{2}
σ j 2 = m 1 i = 1 ∑ m ( x i j − μ j ) 2 上式中以矩阵的行
( r o w )
(
r
o
w
)
(row)
( r o w ) 为单位求方差;
L a y e r N o r m ( x ) = α ⊙ x i j − μ i σ 2 i + ϵ √ + β
L
a
y
e
r
N
o
r
m
(
x
)
=
α
⊙
x
i
j
−
μ
i
σ
i
2
+
ϵ
+
β
LayerNorm(x)=\alpha \odot \frac{x_{ij}-\mu_{i}}{\sqrt{\sigma^{2}_{i}+\epsilon}} + \beta
L a y e r N o r m ( x ) = α ⊙ σ i 2 + ϵ
x i j − μ i + β 然后用每一行 的每一个元素 减去这行的均值 , 再除以这行的标准差 , 从而得到归一化后的数值,
ϵ
ϵ
\epsilon
ϵ 是为了防止除
0
0
0
0 ; 之后引入两个可训练参数
α , β
α
,
β
\alpha, \ \beta
α , β 来弥补归一化的过程中损失掉的信息, 注意
⊙
⊙
\odot
⊙ 表示元素相乘而不是点积, 我们一般初始化
α
α
\alpha
α 为全
1
1
1
1 , 而
β
β
\beta
β 为全
0
0
0
0 .
2.4、Feed Forward
前馈网络由两层全联接层组成,两层之间有一个 ReLU 激活函数。
def point_wise_feed_forward_network ( d_model, dff) :
return tf. keras. Sequential( [
tf. keras. layers. Dense( dff,
activation= 'relu' ) ,
tf. keras. layers. Dense( d_model)
] )
例如上面两个Tensorflow中的Dense层。
四、整体结构
我们下面用公式把一个
t r a n s f o r m e r b l o c k
t
r
a
n
s
f
o
r
m
e
r
b
l
o
c
k
transformer \ block
t r a n s f o r m e r b l o c k 的计算过程整理一下: 1). 字向量与位置编码:
X = E m b e d d i n g L o o k u p ( X ) + P o s i t i o n a l E n c o d i n g
X
=
E
m
b
e
d
d
i
n
g
L
o
o
k
u
p
(
X
)
+
P
o
s
i
t
i
o
n
a
l
E
n
c
o
d
i
n
g
X = EmbeddingLookup(X) + PositionalEncoding
X = E m b e d d i n g L o o k u p ( X ) + P o s i t i o n a l E n c o d i n g
X ∈ R b a t c h s i z e ∗ s e q . l e n . ∗ e m b e d . d i m .
X
∈
R
b
a
t
c
h
s
i
z
e
∗
s
e
q
.
l
e
n
.
∗
e
m
b
e
d
.
d
i
m
.
X \in \mathbb{R}^{batch \ size \ * \ seq. \ len. \ * \ embed. \ dim.}
X ∈ R b a t c h s i z e ∗ s e q . l e n . ∗ e m b e d . d i m .
2). 自注意力机制:
Q = L i n e a r ( X ) = X W Q
Q
=
L
i
n
e
a
r
(
X
)
=
X
W
Q
Q = Linear(X) = XW_{Q}
Q = L i n e a r ( X ) = X W Q
K = L i n e a r ( X ) = X W K
K
=
L
i
n
e
a
r
(
X
)
=
X
W
K
K = Linear(X) = XW_{K}
K = L i n e a r ( X ) = X W K
V = L i n e a r ( X ) = X W V
V
=
L
i
n
e
a
r
(
X
)
=
X
W
V
V = Linear(X) = XW_{V}
V = L i n e a r ( X ) = X W V
X a t t e n t i o n = S e l f A t t e n t i o n ( Q , K , V )
X
a
t
t
e
n
t
i
o
n
=
S
e
l
f
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
X_{attention} = SelfAttention(Q, \ K, \ V)
X a t t e n t i o n = S e l f A t t e n t i o n ( Q , K , V )
3). 残差连接与
L a y e r N o r m a l i z a t i o n
L
a
y
e
r
N
o
r
m
a
l
i
z
a
t
i
o
n
Layer \ Normalization
L a y e r N o r m a l i z a t i o n
X a t t e n t i o n = X + X a t t e n t i o n
X
a
t
t
e
n
t
i
o
n
=
X
+
X
a
t
t
e
n
t
i
o
n
X_{attention} = X + X_{attention}
X a t t e n t i o n = X + X a t t e n t i o n
X a t t e n t i o n = L a y e r N o r m ( X a t t e n t i o n )
X
a
t
t
e
n
t
i
o
n
=
L
a
y
e
r
N
o
r
m
(
X
a
t
t
e
n
t
i
o
n
)
X_{attention} = LayerNorm(X_{attention})
X a t t e n t i o n = L a y e r N o r m ( X a t t e n t i o n )
4). 下面进行
t r a n s f o r m e r b l o c k
t
r
a
n
s
f
o
r
m
e
r
b
l
o
c
k
transformer \ block
t r a n s f o r m e r b l o c k 结构图中的第4部分 , 也就是
F e e d F o r w a r d
F
e
e
d
F
o
r
w
a
r
d
FeedForward
F e e d F o r w a r d , 其实就是两层线性映射并用激活函数激活, 比如说
R e L U
R
e
L
U
ReLU
R e L U :
X h i d d e n = A c t i v a t e ( L i n e a r ( L i n e a r ( X a t t e n t i o n ) ) )
X
h
i
d
d
e
n
=
A
c
t
i
v
a
t
e
(
L
i
n
e
a
r
(
L
i
n
e
a
r
(
X
a
t
t
e
n
t
i
o
n
)
)
)
X_{hidden} = Activate(Linear(Linear(X_{attention})))
X h i d d e n = A c t i v a t e ( L i n e a r ( L i n e a r ( X a t t e n t i o n ) ) )
5). 重复3).:
X h i d d e n = X a t t e n t i o n + X h i d d e n
X
h
i
d
d
e
n
=
X
a
t
t
e
n
t
i
o
n
+
X
h
i
d
d
e
n
X_{hidden} = X_{attention} + X_{hidden}
X h i d d e n = X a t t e n t i o n + X h i d d e n
X h i d d e n = L a y e r N o r m ( X h i d d e n )
X
h
i
d
d
e
n
=
L
a
y
e
r
N
o
r
m
(
X
h
i
d
d
e
n
)
X_{hidden} = LayerNorm(X_{hidden})
X h i d d e n = L a y e r N o r m ( X h i d d e n )
X h i d d e n ∈ R b a t c h s i z e ∗ s e q . l e n . ∗ e m b e d . d i m .
X
h
i
d
d
e
n
∈
R
b
a
t
c
h
s
i
z
e
∗
s
e
q
.
l
e
n
.
∗
e
m
b
e
d
.
d
i
m
.
X_{hidden} \in \mathbb{R}^{batch \ size \ * \ seq. \ len. \ * \ embed. \ dim.}
X h i d d e n ∈ R b a t c h s i z e ∗ s e q . l e n . ∗ e m b e d . d i m .
五、实战
完整代码 :https://github.com/LIANGQINGYUAN/NLP-Notebook
参考链接: Transformer介绍与展示:https://jalammar.github.io/illustrated-transformer/ Transformer讲解与实现: https://github.com/aespresso/a_journey_into_math_of_ml Transformer中的注意力机制:https://zhuanlan.zhihu.com/p/109983672
转载:
https://blog.csdn.net/qq_33414271/article/details/104704391