BERT 并不是一种新提出的算法,而是集前人之所能,解决了当时NLP model上存在的部分问题:
- 并行计算问题(LSTM 中element值是逐个进行的,所以速度不快,transformer是并行计算的)
- 梯度消失/爆炸
- 前/后方向耦合
1和2 transform 解决,model不是时序序列结构,但是保留时序结构的优点
-
transformer如何捕获序列中距离较远的元素之间的关系的呢?
答:self-attention。在LSTM中每个单词的相关性计算是不公平的,相聚越远的词之间的相关性越低。
-
self-attention(双向)、encoder-decoder attention以及decoder attention(单向)之间的区别是什么?
答: -
transformer怎么捕获数据中的先后的顺序的?
答:positional encoding。人为定义位置向量,标志先后顺序。
BERT = Stacks of Transformer Encoder
一. transformer编码器(理论部分):
$transformer$模型的直觉, 建立直观认识;
$positional \ encoding$, 即位置嵌入(或位置编码);
$self \ attention \ mechanism$, 即自注意力机制与注意力矩阵可视化;
$Layer \ Normalization$和残差连接.
$transformer \ encoder$整体结构.
二. transformer代码解读, 语料数据预处理, BERT的预训练和情感分析的应用:
三. sequence 2 sequence(序列到序列)模型或Name Entity Recognition(命名实体识别)(待定):
此部分根据前面的反馈待定.
0.
t
r
a
n
s
f
o
r
m
e
r
transformer
transformer模型的直觉, 建立直观认识;
首先来说一下transformer和LSTM的最大区别, 就是LSTM的训练是迭代的, 是一个接一个字的来, 当前这个字过完LSTM单元, 才可以进下一个字, 而transformer的训练是并行了, 就是所有字是全部同时训练的, 这样就大大加快了计算效率, transformer使用了位置嵌入
(
p
o
s
i
t
i
o
n
a
l
e
n
c
o
d
i
n
g
)
(positional \ encoding)
(positional encoding)来理解语言的顺序, 使用自注意力机制和全连接层来进行计算, 这些后面都会详细讲解.
transformer模型主要分为两大部分, 分别是编码器和解码器, 编码器负责把自然语言序列映射成为隐藏层(下图中第2步用九宫格比喻的部分), 含有自然语言序列的数学表达. 然后解码器把隐藏层再映射为自然语言序列, 从而使我们可以解决各种问题, 如情感分类, 命名实体识别, 语义关系抽取, 摘要生成, 机器翻译等等, 下面我们简单说一下下图的每一步都做了什么:
输入自然语言序列到编码器: Why do we work?(为什么要工作);
编码器输出的隐藏层, 再输入到解码器;
输入$<start>$(起始)符号到解码器;
得到第一个字"为";
将得到的第一个字"为"落下来再输入到解码器;
得到第二个字"什";
将得到的第二字再落下来, 直到解码器输出$<end>$(终止符), 即序列生成完成.
我们这节课的内容限于编码器部分, 即把自然语言序列映射为隐藏层的数学表达的过程, 因为理解了编码器中的结构, 理解解码器就非常简单了,最重要的是BERT预训练模型只用到了编码器的部分, 也就是先用编码器训练一个语言模型, 然后再把它适配给其他五花八门的任务.
如果你不知道语言模型是什么, 没关系, 这丝毫不影响本节课内容的理解, 下次我们讲BERT的时候会讲.
而且我们用编码器就能够完成一些自然语言处理中比较主流的任务, 如情感分类, 语义关系分析, 命名实体识别等, 解码器的内容和序列到序列模型有机会我们会涉及到.
Transformer Block结构图, 注意: 为方便查看, 下面的内容分别对应着上图第1, 2, 3, 4个方框的序号:
- p o s i t i o n a l e n c o d i n g positional \ encoding positional encoding, 即位置嵌入(或位置编码);
由于transformer模型没有循环神经网络的迭代操作, 所以我们必须提供每个字的位置信息给transformer, 才能识别出语言中的顺序关系.
现在定义一个位置嵌入的概念, 也就是
p
o
s
i
t
i
o
n
a
l
e
n
c
o
d
i
n
g
positional \ encoding
positional encoding, 位置嵌入的维度为
[
m
a
x
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
]
[max \ sequence \ length, \ embedding \ dimension]
[max sequence length, embedding dimension], 嵌入的维度同词向量的维度,
m
a
x
s
e
q
u
e
n
c
e
l
e
n
g
t
h
max \ sequence \ length
max sequence length属于超参数, 指的是限定的最大单个句长.
注意, 我们一般以字为单位训练transformer模型, 也就是说我们不用分词了, 首先我们要初始化字向量为
[
v
o
c
a
b
s
i
z
e
,
e
m
b
e
d
d
i
n
g
d
i
m
e
n
s
i
o
n
]
[vocab \ size, \ embedding \ dimension]
[vocab size, embedding dimension],
v
o
c
a
b
s
i
z
e
vocab \ size
vocab size为总共的字库数量,
e
m
b
e
d
d
i
n
g
d
i
m
e
n
s
i
o
n
embedding \ dimension
embedding dimension为字向量的维度, 也是每个字的数学表达.
在这里论文中使用了
s
i
n
e
sine
sine和
c
o
s
i
n
e
cosine
cosine函数的线性变换来提供给模型位置信息:
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
+
1
)
=
c
o
s
(
p
o
s
/
1000
0
2
i
/
d
model
)
(eq.1)
PE_{(pos,2i)} = sin(pos / 10000^{2i/d_{\text{model}}}) \quad PE_{(pos,2i+1)} = cos(pos / 10000^{2i/d_{\text{model}}})\tag{eq.1}
PE(pos,2i)=sin(pos/100002i/dmodel)PE(pos,2i+1)=cos(pos/100002i/dmodel)(eq.1) 上式中
p
o
s
pos
pos指的是句中字的位置, 取值范围是
[
0
,
m
a
x
s
e
q
u
e
n
c
e
l
e
n
g
t
h
)
[0, \ max \ sequence \ length)
[0, max sequence length),
i
i
i指的是词向量的维度, 取值范围是
[
0
,
e
m
b
e
d
d
i
n
g
d
i
m
e
n
s
i
o
n
)
[0, \ embedding \ dimension)
[0, embedding dimension), 上面有
s
i
n
sin
sin和
c
o
s
cos
cos一组公式, 也就是对应着
e
m
b
e
d
d
i
n
g
d
i
m
e
n
s
i
o
n
embedding \ dimension
embedding dimension维度的一组奇数和偶数的序号的维度, 例如
0
,
1
0, 1
0,1一组,
2
,
3
2, 3
2,3一组, 分别用上面的
s
i
n
sin
sin和
c
o
s
cos
cos函数做处理, 从而产生不同的周期性变化, 而位置嵌入在
e
m
b
e
d
d
i
n
g
d
i
m
e
n
s
i
o
n
embedding \ dimension
embedding dimension维度上随着维度序号增大, 周期变化会越来越慢, 而产生一种包含位置信息的纹理, 就像论文原文中第六页讲的, 位置嵌入函数的周期从
2
π
2 \pi
2π到
10000
∗
2
π
10000 * 2 \pi
10000∗2π变化, 而每一个位置在
e
m
b
e
d
d
i
n
g
d
i
m
e
n
s
i
o
n
embedding \ dimension
embedding dimension维度上都会得到不同周期的
s
i
n
sin
sin和
c
o
s
cos
cos函数的取值组合, 从而产生独一的纹理位置信息, 模型从而学到位置之间的依赖关系和自然语言的时序特性.
- s e l f a t t e n t i o n m e c h a n i s m self \ attention \ mechanism self attention mechanism, 自注意力机制;
Attention Mask
注意, 在上面
s
e
l
f
a
t
t
e
n
t
i
o
n
self \ attention
self attention的计算过程中, 我们通常使用
m
i
n
i
b
a
t
c
h
mini \ batch
mini batch来计算, 也就是一次计算多句话, 也就是
X
X
X的维度是
[
b
a
t
c
h
s
i
z
e
,
s
e
q
u
e
n
c
e
l
e
n
g
t
h
]
[batch \ size, \ sequence \ length]
[batch size, sequence length],
s
e
q
u
e
n
c
e
l
e
n
g
t
h
sequence \ length
sequence length是句长, 而一个
m
i
n
i
b
a
t
c
h
mini \ batch
mini batch是由多个不等长的句子组成的, 我们就需要按照这个
m
i
n
i
b
a
t
c
h
mini \ batch
mini batch中最大的句长对剩余的句子进行补齐长度, 我们一般用
0
0
0来进行填充, 这个过程叫做
p
a
d
d
i
n
g
padding
padding.
但这时在进行
s
o
f
t
m
a
x
softmax
softmax的时候就会产生问题, 回顾
s
o
f
t
m
a
x
softmax
softmax函数
σ
(
z
)
i
=
e
z
i
∑
j
=
1
K
e
z
j
\sigma (\mathbf {z} )_{i}={\frac {e^{z_{i}}}{\sum _{j=1}^{K}e^{z_{j}}}}
σ(z)i=∑j=1Kezjezi,
e
0
e^0
e0是1, 是有值的, 这样的话
s
o
f
t
m
a
x
softmax
softmax中被
p
a
d
d
i
n
g
padding
padding的部分就参与了运算, 就等于是让无效的部分参与了运算, 会产生很大隐患, 这时就需要做一个
m
a
s
k
mask
mask让这些无效区域不参与运算, 我们一般给无效区域加一个很大的负数的偏置, 也就是:
z
i
l
l
e
g
a
l
=
z
i
l
l
e
g
a
l
+
b
i
a
s
i
l
l
e
g
a
l
z_{illegal} = z_{illegal} + bias_{illegal}
zillegal=zillegal+biasillegal
b
i
a
s
i
l
l
e
g
a
l
→
−
∞
bias_{illegal} \to -\infty
biasillegal→−∞
e
z
i
l
l
e
g
a
l
→
0
e^{z_{illegal}} \to 0
ezillegal→0 经过上式的
m
a
s
k
i
n
g
masking
masking我们使无效区域经过
s
o
f
t
m
a
x
softmax
softmax计算之后还几乎为
0
0
0, 这样就避免了无效区域参与计算.
3.
L
a
y
e
r
N
o
r
m
a
l
i
z
a
t
i
o
n
Layer \ Normalization
Layer Normalization和残差连接.
1). 残差连接:
我们在上一步得到了经过注意力矩阵加权之后的
V
V
V, 也就是
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
Attention(Q, \ K, \ V)
Attention(Q, K, V), 我们对它进行一下转置, 使其和
X
e
m
b
e
d
d
i
n
g
X_{embedding}
Xembedding的维度一致, 也就是
[
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]
[batch size, sequence length, embedding dimension], 然后把他们加起来做残差连接, 直接进行元素相加, 因为他们的维度一致:
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)
Xembedding+Attention(Q, K, V) 在之后的运算里, 每经过一个模块的运算, 都要把运算之前的值和运算之后的值相加, 从而得到残差连接, 训练的时候可以使梯度直接走捷径反传到最初始层:
X
+
S
u
b
L
a
y
e
r
(
X
)
(eq. 5)
X + SubLayer(X) \tag{eq. 5}
X+SubLayer(X)(eq. 5) 2).
L
a
y
e
r
N
o
r
m
LayerNorm
LayerNorm:
L
a
y
e
r
N
o
r
m
a
l
i
z
a
t
i
o
n
Layer Normalization
LayerNormalization的作用是把神经网络中隐藏层归一为标准正态分布, 也就是
i
.
i
.
d
i.i.d
i.i.d独立同分布, 以起到加快训练速度, 加速收敛的作用:
μ
i
=
1
m
∑
i
=
1
m
x
i
j
\mu_{i}=\frac{1}{m} \sum^{m}_{i=1}x_{ij}
μi=m1i=1∑mxij 上式中以矩阵的行
(
r
o
w
)
(row)
(row)为单位求均值;
σ
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}
σj2=m1i=1∑m(xij−μj)2 上式中以矩阵的行
(
r
o
w
)
(row)
(row)为单位求方差;
L
a
y
e
r
N
o
r
m
(
x
)
=
α
⊙
x
i
j
−
μ
i
σ
i
2
+
ϵ
+
β
(eq.6)
LayerNorm(x)=\alpha \odot \frac{x_{ij}-\mu_{i}} {\sqrt{\sigma^{2}_{i}+\epsilon}} + \beta \tag{eq.6}
LayerNorm(x)=α⊙σi2+ϵxij−μi+β(eq.6) 然后用每一行的每一个元素减去这行的均值, 再除以这行的标准差, 从而得到归一化后的数值,
ϵ
\epsilon
ϵ是为了防止除
0
0
0;
之后引入两个可训练参数
α
,
β
\alpha, \ \beta
α, β来弥补归一化的过程中损失掉的信息, 注意
⊙
\odot
⊙表示元素相乘而不是点积, 我们一般初始化
α
\alpha
α为全
1
1
1, 而
β
\beta
β为全
0
0
0.
4.
t
r
a
n
s
f
o
r
m
e
r
e
n
c
o
d
e
r
transformer \ encoder
transformer encoder整体结构.
经过上面3个步骤, 我们已经基本了解到来
t
r
a
n
s
f
o
r
m
e
r
transformer
transformer编码器的主要构成部分, 我们下面用公式把一个
t
r
a
n
s
f
o
r
m
e
r
b
l
o
c
k
transformer \ block
transformer block的计算过程整理一下:
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
(eq.2)
X = EmbeddingLookup(X) + PositionalEncoding \tag{eq.2}
X=EmbeddingLookup(X)+PositionalEncoding(eq.2)
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∈Rbatch size ∗ seq. len. ∗ embed. dim. 2). 自注意力机制:
Q
=
L
i
n
e
a
r
(
X
)
=
X
W
Q
Q = Linear(X) = XW_{Q}
Q=Linear(X)=XWQ
K
=
L
i
n
e
a
r
(
X
)
=
X
W
K
(eq.3)
K = Linear(X) = XW_{K} \tag{eq.3}
K=Linear(X)=XWK(eq.3)
V
=
L
i
n
e
a
r
(
X
)
=
X
W
V
V = Linear(X) = XW_{V}
V=Linear(X)=XWV
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
)
(eq.4)
X_{attention} = SelfAttention(Q, \ K, \ V) \tag{eq.4}
Xattention=SelfAttention(Q, K, V)(eq.4) 3). 残差连接与
L
a
y
e
r
N
o
r
m
a
l
i
z
a
t
i
o
n
Layer \ Normalization
Layer Normalization
X
a
t
t
e
n
t
i
o
n
=
X
+
X
a
t
t
e
n
t
i
o
n
(eq. 5)
X_{attention} = X + X_{attention} \tag{eq. 5}
Xattention=X+Xattention(eq. 5)
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
)
(eq. 6)
X_{attention} = LayerNorm(X_{attention}) \tag{eq. 6}
Xattention=LayerNorm(Xattention)(eq. 6) 4). 下面进行
t
r
a
n
s
f
o
r
m
e
r
b
l
o
c
k
transformer \ block
transformer block结构图中的第4部分, 也就是
F
e
e
d
F
o
r
w
a
r
d
FeedForward
FeedForward, 其实就是两层线性映射并用激活函数激活, 比如说
R
e
L
U
ReLU
ReLU:
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
)
)
)
(eq. 7)
X_{hidden} = Activate(Linear(Linear(X_{attention}))) \tag{eq. 7}
Xhidden=Activate(Linear(Linear(Xattention)))(eq. 7) 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_{hidden} = X_{attention} + X_{hidden}
Xhidden=Xattention+Xhidden
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})
Xhidden=LayerNorm(Xhidden)
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.}
Xhidden∈Rbatch size ∗ seq. len. ∗ embed. dim.
小结:
我们到现在位置已经讲完了transformer的编码器的部分, 了解到了transformer是怎样获得自然语言的位置信息的, 注意力机制是怎样的, 其实举个语言情感分类的例子, 我们已经知道, 经过自注意力机制, 一句话中的每个字都含有这句话中其他所有字的信息, 那么我们可不可以添加一个空白字符到句子最前面, 然后让句子中的所有信息向这个空白字符汇总, 然后再映射成想要分的类别呢? 这就是BERT, 我们下次会讲到.
在BERT的预训练中, 我们给每句话的句头加一个特殊字符, 然后句末再加一个特殊字符, 之后模型预训练完毕之后, 我们就可以用句头的特殊字符的
h
i
d
d
e
n
s
t
a
t
e
hidden \ state
hidden state完成一些分类任务了.