Transformer编码器结构及运算过程的符号表示
这篇文章主要是展示Transformer编码器的结构,同时尽量使用数学符号表达编码器的运算过程。
Transformer编码器的核心结构是多头注意力机制,本文从(单头)注意力机制开始描述,然后扩展到对编码器运算过程的描述。暂不涉及解码器的描述。
注意:此处介绍的注意力机制均为自注意力机制。
一、(单头)自注意力机制
输入
X = [ x 1 , x 2 , . . . , x m ] X=[x_1, x_2, ..., x_m] X=[x1,x2,...,xm], m m m表示输入的token的数量(句子的长度)(在Transformer中是一个超参数,一般设置成128、256)。
x i ∈ R d × 1 x_i \in \mathbb{R}^{d\times 1} xi∈Rd×1, d d d表示embedding向量的维度(在Transformer中是一个超参数,一般设置成64、128、256), i = 1 , . . . , m i=1,...,m i=1,...,m。
X ∈ R d × m X \in \mathbb{R}^{d \times m} X∈Rd×m。
查询(query)、键(key)、价值(value)
q i = W Q x i q_i = \textcolor{red}{W_Q} x_i qi=WQxi, W Q ∈ R d × d \textcolor{red}{W_Q} \in \mathbb{R}^{d \times d} WQ∈Rd×d, q i ∈ R d × 1 q_i \in \mathbb{R}^{d \times 1} qi∈Rd×1。
Q = [ q 1 , q 2 , . . . , q m ] Q = [q_1, q_2, ..., q_m] Q=[q1,q2,...,qm], Q ∈ R d × m Q \in \mathbb{R}^{d \times m} Q∈Rd×m。
k i = W K x i k_i = \textcolor{red}{W_K} x_i ki=WKxi, W K ∈ R d × d \textcolor{red}{W_K} \in \mathbb{R}^{d \times d} WK∈Rd×d, k i ∈ R d × 1 k_i \in \mathbb{R}^{d \times 1} ki∈Rd×1。
K = [ k 1 , k 2 , . . . , k m ] K = [k_1, k_2, ..., k_m] K=[k1,k2,...,km], K ∈ R d × m K \in \mathbb{R}^{d \times m} K∈Rd×m。
v i = W V x i v_i = \textcolor{red}{W_V} x_i vi=WVxi, W V ∈ R d × d \textcolor{red}{W_V} \in \mathbb{R}^{d \times d} WV∈Rd×d, v i ∈ R d × 1 v_i \in \mathbb{R}^{d \times 1} vi∈Rd×1。
V = [ v 1 , v 2 , . . . , v m ] V = [v_1, v_2, ..., v_m] V=[v1,v2,...,vm], V ∈ R d × m V \in \mathbb{R}^{d \times m} V∈Rd×m。
注意力(attention)
a
i
=
σ
(
K
T
q
i
α
)
a_i = \sigma \left(\frac{K^{\mathrm{T}}q_i}{\alpha} \right)
ai=σ(αKTqi),
α
\alpha
α是标量,表示放缩因子。
a
i
∈
R
m
×
1
a_i \in \mathbb{R}^{m \times 1}
ai∈Rm×1。
σ
(
⋅
)
\sigma(\cdot)
σ(⋅)表示softmax函数。
A
=
[
a
1
,
a
2
,
.
.
.
,
a
m
]
A = [a_1, a_2, ..., a_m]
A=[a1,a2,...,am],
A
∈
R
m
×
m
A \in \mathbb{R}^{m \times m}
A∈Rm×m。
上下文/输出
c
i
=
V
a
i
=
a
1
i
v
1
+
a
2
i
v
2
+
.
.
.
+
a
m
i
v
m
=
V
⋅
σ
(
K
T
q
i
α
)
c_i = \textcolor{blue}{V} a_i = a_{1i}v_1 + a_{2i}v_2 + ... + a_{mi}v_m = \textcolor{blue}{V} \cdot \sigma \left( \frac{K^{\mathrm{T}}q_i}{\alpha} \right)
ci=Vai=a1iv1+a2iv2+...+amivm=V⋅σ(αKTqi),
c
i
∈
R
d
×
1
c_i \in \mathbb{R}^{d \times 1}
ci∈Rd×1。
C = [ c 1 , c 2 , . . . , c m ] C = [c_1, c_2, ..., c_m] C=[c1,c2,...,cm], C ∈ R d × m C \in \mathbb{R}^{d \times m} C∈Rd×m。
总结
C = Attn ( X , X ) C = \text{Attn}(X,X) C=Attn(X,X)。 Attn ( ⋅ ) \text{Attn}(\cdot) Attn(⋅)表示自注意力模块,包含了前述计算query、key、value、注意力、上下文的过程。
自注意力模块只包含三个参数矩阵:
W
Q
W_Q
WQ、
W
K
W_K
WK、
W
V
W_V
WV。
二、多头自注意力机制
与单头自注意力机制相比,多头(multi-head)自注意力机制会按照“头(head)”的数量对输入进行划分。假设有 h h h个head,那么 x i = [ x i [ 1 ] , x i [ 2 ] , . . . , x i [ h ] ] x_i = \left[ x_i^{[1]}, x_i^{[2]}, ..., x_i^{[h]} \right] xi=[xi[1],xi[2],...,xi[h]], x i [ j ] ∈ R d h × 1 x_i^{[j]} \in \mathbb{R}^{\frac{d}{h} \times 1} xi[j]∈Rhd×1, j = 1 , . . . , h j=1,...,h j=1,...,h。
每个head的自注意力处理一个 x i [ j ] x_i^{[j]} xi[j],处理流程与单头自注意力机制相同,得到的输出是 c i [ j ] ∈ R d h × 1 c_i^{[j]} \in \mathbb{R}^{\frac{d}{h} \times 1} ci[j]∈Rhd×1。将每个head的输出进行拼接,才得到与输入 x i x_i xi对应的 c i c_i ci。
多头自注意力模块包含
3
h
3h
3h个参数矩阵。
三、Transformer编码器结构
如下图所示,Transformer编码器主要由一层多头自注意力和一层前馈网络组成。
多头自注意力
多头自注意力的过程如前文所述。此处有 3 h 3h 3h个参数矩阵: W Q [ 1 ] , . . . , W Q [ h ] , W K [ 1 ] , . . . , W K [ h ] , W V [ 1 ] , . . . , W V [ h ] W_Q^{[1]},...,W_Q^{[h]}, W_K^{[1]},...,W_K^{[h]}, W_V^{[1]},...,W_V^{[h]} WQ[1],...,WQ[h],WK[1],...,WK[h],WV[1],...,WV[h]。
前馈网络
前馈网络一般使用一层线性层实现,不改变输入的维度: X ′ = W u X X^{\prime} = \textcolor{red}{W_u} X X′=WuX, X ← C + X X \leftarrow C + X X←C+X, X ′ ∈ R d × m X^{\prime} \in \mathbb{R}^{d \times m} X′∈Rd×m。
此处有1个参数矩阵 W u ∈ R d × d W_u \in \mathbb{R}^{d \times d} Wu∈Rd×d。
四、token编码(词表映射)与位置编码
输入 X X X在进入Transformer编码块之前还要经过token编码和位置编码。在经过token编码和位置编码之前,输入还只是一个个token(每个token都是一个整数,表示在词表中的索引)。
token编码
token编码就是将token转换成embedding,也即让输入经过一个embedding映射层 E E E。这个embedding映射层既可以是现成的,也可以是跟随模型一起训练得到的。
embedding映射层并不是一个线性层,更像是一个词表。假设模型能处理 vocab_size \text{vocab\_size} vocab_size个词,每个词的embedding向量长度是 d d d,那么embedding映射层的这个词表大小就是 vocab_size × d \text{vocab\_size} \times d vocab_size×d。
token转换成embedding的过程: x i ← E [ x i , : ] x_i \leftarrow E[x_i, :] xi←E[xi,:]。
位置编码
最初的Transformer模型使用正弦和余弦函数来生成固定的位置编码,这些编码与模型的其他参数是分开的,不是通过学习得到的。
P
E
(
p
o
s
,
2
i
)
=
s
i
n
(
p
o
s
/
1000
0
2
i
/
d
)
P
E
(
p
o
s
,
2
i
+
1
)
=
c
o
s
(
p
o
s
/
1000
0
2
i
/
d
)
PE_{(pos,2i)}=sin(pos/10000^{2i/d})\\PE_{(pos,2i+1)}=cos(pos/10000^{2i/d})
PE(pos,2i)=sin(pos/100002i/d)PE(pos,2i+1)=cos(pos/100002i/d)
其中,
p
o
s
pos
pos表示token的序号,
i
i
i表示embedding的维度。