要想了解BERT,首先需要掌握他的基本结构Transformer.因为BERT的Encoder就是Transformer
自然语言处理中,有三种特征处理器(就是特征抽取器):卷积神经网络、递归神经网络和后起之秀 Transformer。
这一篇《带你全面认识自然语言处理三大特征抽取器(CNN/RNN/TF)》用诙谐幽默而通俗易懂的语言介绍了上面三种特征处理器。
我们首先对整个BERT的信息流的传递,然后深入encoder的输入输出。
其次我们将分析每一个encoder blocks,并理解Multi-Head Attention.
Information Flow
The data flow through the architecture is as follows:
- 模型将每一个token表示为emb_dim大小的向量,给每一个输入token都嵌入为(embedding)一个向量,我们就得到一个特定的输入序列(input sequence),具体为 (input_length) x (emb_dim) 大小的矩阵。
- 然后添加位置信息进行位置编码,这一步返回大小(input_length) x (emb_dim)的矩阵。
- 数据经过N个encoder blocks后我们得到大小(input_length) x (emb_dim)的矩阵。
步骤1,2,3如下图所示:
注意,下一个encoder block的输入和上一个encoder block的输出是一样的,每个blocks两两之间无权重。
2 From words to vectors
2.1 Tokenization, numericalization and word embeddings
上图红色区域就是Tokenization, numericalization and embeddings发生的地方。
对于一个语料库中的一个句子:
“ Hello, how are you?”
第一步是tokenize it:
“ Hello, how are you?” → [“Hello”, “,” , “how”, “are”, “you”, “?”]
第二步是对其数值化numericalization(将上面的每一个token映射成一个语料库词汇表中互不重复的整数)
[“Hello”, “, “, “how”, “are”, “you”, “?”] → [34, 90, 15, 684, 55, 193]
这样我们就得到了一组经过embedding每一个单词后的序列了。序列中的每一个单词都被映射为emb_dim维度的向量(找一下公式)提供给模型训练学习。
向量中的元素作为模型的参数,在反向传播的过程中得到优化。
所以,对每一个token,我们可以查找到对应的向量:
[“<pad>”, “<pad>”, “<pad>”, “Hello”, “, “, “how”, “are”, “you”, “?”] →[5, 5, 5, 34, 90, 15, 684, 55, 193]
2.2 Positional Encoding
尽管我们能找到一个矩阵 Z Z Z表示输入的序列,但是这并不能表示同一个单词每次出现在不同的位置。
我们的目标是能够根据特定单词的位置信息来得到单词的意义。这只需要对上述表示矩阵模型进行修改即可。
我们可以用预先确定的(不是通过学习得到的)正弦函数将【-1,1】之间的值嵌入token中。由此哪怕是完全一样的单词,我们也可以根据单词所在的位置不同,构建不同位置的单词的略微不同的表示方式。
另外,我们希望编码器能够实现对于同一个序列,部分单词在初始位置,而另外一部分单词在指定的位置——即**希望网络能够理解相对位置,而不仅仅是绝对位置。**正弦函数可以使位置被表示为彼此的线性组合,从而网络可以学习token位置之间的相对关系。
用数学描述,就是在原来的
Z
Z
Z矩阵中加入带有位置编码的矩阵
P
P
P。
Z
+
P
Z+P
Z+P我们用
i
i
i表示token在序列中的位置;用
j
j
j表示嵌入特征(embedding feature)的位置。
- 可以无限地增加input_length,因为可以计算任意位置的函数。
- 需要学习的参数更少,模型训练更快。
通过 X = Z + P X=Z+P X=Z+P,大小为(input_length) x (emb_dim)的矩阵 X X X将送入第一个encoder block。
2.3 Encoder Block
Encoder Blocks共有N个encoder block链接在一起,以生成编码器的输出。特定块负责查找输入表示之间的关系,并将它们编码到输出中。
2.3.1 Multi-Head Attention
引入多头注意力的Transformer,在不同时间使用不同的权重矩阵计算注意力h,然后将结果连接在一起。
这些并行计算注意力的结果被称为头head。我们将用下标 i i i 来表示一个特定的头和相关的权重矩阵。下图描述了并行计算头(computes attention h)及其结果连接在一起(and then concatenates the results together)的过程:
2.3.2 Scaled Dot-Product Attention
每个头将由三个不同的投影(矩阵乘法)由矩阵给出:
为了计算一个头部head,输入X矩阵,并分别投射X给上述三个权值矩阵:
其中, d k = d v = e m b _ d i m / h d_k=d_v=emb\_dim/h dk=dv=emb_dim/h
得到
K
i
、
Q
i
K_i 、Q_i
Ki、Qi和
V
i
V_i
Vi后我们用它们来计算缩放的点积注意力Dot-Product 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(\frac{QK^T}{\sqrt{d_k}})V
Attention(Q,K,V)=softmax(dkQKT)V
用图描述为:
在编码器块中计算注意不使用mask。在解码器使用mask
2.3.3 Going Deep
GOING DEEP是BERT的关键,所以我们需要仔细理解它。让我们从 Q i Q_i Qi和 K i K_i Ki的转置矩阵乘积开始 Q i K i T Q_iK_i^T QiKiT
Q
i
Q_i
Qi和
K
i
K_i
Ki是tokens在
d
k
d_k
dk维空间中的不同投影。因此我们可以把这些投影的点积看作度量tokens投影之间相似性的方法。
对于每一个通过
Q
i
Q_i
Qi投影得到的向量与每一个通过
K
i
K_i
Ki投影得到的向量,可以用点积来度量这些向量之间的相似性。将
v
i
v_i
vi和
u
j
u_j
uj分别称为第
i
i
i个token和第
j
j
j个token通过
Q
i
Q_i
Qi和
K
i
K_i
Ki的投影,则它们的点积为:
因此,这是一个度量 u i u_i ui和 v j v_j vj在方向上有多相似以及它们的长度有多大的方法(方向越接近,长度越大,点积越大)。
也可以认为这个矩阵乘积是作为对输入序列中tokens之间特定关系的encoding(这种关系由矩阵
K
i
K_i
Ki和
Q
i
Q_i
Qi定义)。
在此乘法之后,将矩阵按元素顺序除以
d
k
d_k
dk的平方根,以便进行缩放。
下一步是按行Softmax
s
o
f
t
m
a
x
(
Q
K
T
d
k
)
softmax(\frac{QK^T}{\sqrt{d_k}})
softmax(dkQKT)
结果将是数字在0和1之间的行,它们的和为1。最后,将结果乘以
V
i
V_i
Vi得到head的结果。
s
o
f
t
m
a
x
(
Q
K
T
d
k
)
V
i
softmax(\frac{QK^T}{\sqrt{d_k}})V_i
softmax(dkQKT)Vi