深入理解 Bert核心:Self-Attention与transformer
文章目录Attention机制基本思想Attention机制的权值transformer中的self-Attentionself-Attention多头机制self-Attention位置信息的表达Transformer本文主要讲解Bert模型的核心:transformer。transformer利用self-attention机制实现快速并行。并且Transformer可以增加到非常深的深度,充
文章目录
本文主要讲解Bert模型的核心:transformer。transformer利用self-attention机制实现快速并行。并且Transformer可以增加到非常深的深度,充分发掘DNN模型的特性,提升模型准确率。通过先讲解Attention机制,再讲解Transformer模型,理解它的工作原理。
Attention机制基本思想
Attention机制源自于人类视觉注意力机制:将有限的注意力集中在重点信息上,「从关注全部到关注重点」,从而节省资源,快速获得最有效的信息。Attention就是一种权重参数的分配机制,目标是帮助模型捕捉重要信息,本质是一种带权求和。
下图是文本处理领域里常用的Encoder-Decoder框架最抽象的一种表示。
Encoder是对输入句子Source
x
1
,
x
2
,
x
3
,
x
4
x_1,x_2,x_3,x_4
x1,x2,x3,x4进行编码,将输入句子通过非线性变换转化为中间语义表示C:
C
=
F
(
x
1
,
x
2
,
x
3
,
…
x
n
)
C = \mathcal F(x_1,x_2,x_3,\ldots x_n)
C=F(x1,x2,x3,…xn)
对于解码器Decoder来说,其任务是根据句子Source的中间语义表示C和之前已经生成的历史信息来生成i时刻要生成的单词,即:
y
i
=
G
(
C
,
y
1
,
2
,
…
y
i
−
1
)
y_i = \mathcal G(C,y_1,_2,\ldots y_{i-1})
yi=G(C,y1,2,…yi−1)
注:
G
、
F
\mathcal G、\mathcal F
G、F均是非线性变换函数
如果Source是中文句子,Target是英文句子,那么这就是解决机器翻译问题的Encoder-Decoder框架,在这个翻译的过程中,每个target的生成过程如下:
y
1
=
G
(
C
)
y
2
=
G
(
C
,
y
1
)
y
3
=
G
(
C
,
y
1
,
y
2
)
y_1 = \mathcal G(C) \\ y_2 = \mathcal G(C,y_1) \\ y_3 = \mathcal G(C,y_1,y_2)
y1=G(C)y2=G(C,y1)y3=G(C,y1,y2)
可以看出,在生成目标句子的单词时,不论生成哪个单词,它们使用的输入句子Source的语义编码C都是一样的,没有任何区别。说明这个模型没有体现出注意力。这类似于人类看到眼前的画面,但是眼中却没有注意焦点一样。
下面来看一个具体的例子:
比如输入的是英文句子:Tom chase Jerry,Encoder-Decoder框架逐步生成中文单词:“汤姆”,“追逐”,“杰瑞”。在翻译“杰瑞”这个中文单词的时候,分心模型里面的每个英文单词对于翻译目标单词“杰瑞”贡献是相同的,很明显这里不太合理,显然“Jerry”对于翻译成“杰瑞”更重要,但是分心模型是无法体现这一点的,这就是为何说它没有引入注意力的原因。
如果引入Attention模型的话,应该在翻译“杰瑞”的时候,体现出英文单词对于翻译当前中文单词不同的影响程度,比如给出类似下面一个概率分布值:
(
T
o
m
,
0.3
)
(
C
h
a
s
e
,
0.2
)
(
J
e
r
r
y
,
0.5
)
(Tom,0.3)(Chase,0.2) (Jerry,0.5)
(Tom,0.3)(Chase,0.2)(Jerry,0.5)
每个英文单词的概率代表了翻译当前单词“杰瑞”时,注意力分配模型分配给不同英文单词的注意力大小,这是Attention的关键
同理,目标句子中的每个单词都应该学会其对应的源语句子中单词的注意力分配概率信息。这意味着在生成每个单词yi的时候,原先都是相同的中间语义表示C会被替换成根据当前生成单词而不断变化的Ci,增加了注意力模型的Encoder-Decoder框架如下图所示:
在这个翻译的过程中,每个target的生成过程更新如下:
y
1
=
G
(
C
1
)
y
2
=
G
(
C
2
,
y
1
)
y
3
=
G
(
C
3
,
y
1
,
y
2
)
y_1 = \mathcal G(C_1) \\ y_2 = \mathcal G(C_2,y_1) \\ y_3 = \mathcal G(C_3,y_1,y_2)
y1=G(C1)y2=G(C2,y1)y3=G(C3,y1,y2)
而每个Ci可能对应着不同的源语句子单词的注意力分配概率分布:
C
汤
姆
=
g
(
0.6
∗
f
(
"
T
o
m
"
)
,
0.2
∗
f
(
C
h
a
s
e
)
,
0.2
∗
f
(
"
J
e
r
r
y
"
)
C
追
逐
=
g
(
0.2
∗
f
(
"
T
o
m
"
)
,
0.7
∗
f
(
C
h
a
s
e
)
,
0.1
∗
f
(
"
J
e
r
r
y
"
)
C
杰
瑞
=
g
(
0.3
∗
f
(
"
T
o
m
"
)
,
0.2
∗
f
(
C
h
a
s
e
)
,
0.5
∗
f
(
"
J
e
r
r
y
"
)
C_{汤姆}= g(0.6* f("Tom"),0.2 * f(Chase),0.2 * f("Jerry") \\ C_{追逐}= g(0.2 * f("Tom"),0.7 * f(Chase),0.1 * f("Jerry") \\ C_{杰瑞}= g(0.3 * f("Tom"),0.2 * f(Chase),0.5* f("Jerry")
C汤姆=g(0.6∗f("Tom"),0.2∗f(Chase),0.2∗f("Jerry")C追逐=g(0.2∗f("Tom"),0.7∗f(Chase),0.1∗f("Jerry")C杰瑞=g(0.3∗f("Tom"),0.2∗f(Chase),0.5∗f("Jerry")
这里就是Attention机制,还有一个问题,翻译过程中,“汤姆”对应的输入句子Source中各个单词的概率分布:
(
T
o
m
,
0.6
)
(
C
h
a
s
e
,
0.2
)
(
J
e
r
r
y
,
0.2
)
(Tom,0.6)(Chase,0.2)(Jerry,0.2)
(Tom,0.6)(Chase,0.2)(Jerry,0.2)是如何得到的呢?
Attention机制的权值
注意力机制使神经网络能够更多地关注输入中的相关部分,当给定一个 query(例如,输出句子中的目标词),计算其输出时,会依据 query 对某些 key 元素(例如,输入句子中的源词)进行优先级排序(赋予不同的权重)。在给定 query,确定分配给某个 key 的注意力权重时,存在四个可能的注意力因子:(E1)query 内容特征和 key 内容特征;(E2)query 内容特征和 query-key 相对位置;(E3)仅 key 内容内容特征;(E4)仅 query-key 相对位置。
如果把单词看作是整个单词空间中的向量。每个词向量的方向都有意义。可以使用余弦相似度来衡量向量之间的相似性。
c
o
s
<
v
1
,
v
2
>
=
v
1
⋅
v
2
∣
v
1
∣
∣
v
2
∣
cos<\mathbf v_1,\mathbf v_2> = \frac{\mathbf v_1 \cdot \mathbf v_2}{|\mathbf v_1|| \mathbf v_2|}
cos<v1,v2>=∣v1∣∣v2∣v1⋅v2
也可以使用其他的相似度衡量方法。向量之间的相似性和差异性对应于单词本身的相似性和差异性。
Attention机制如下图所示:
阶段1:度量环境向量(memory)与当前输入向量(query)的相似性,根据给定的Query(例子中的Tom,是一个词向量)与所有的输入(Tom,chase ,Jerry。均为词向量),分别计算余弦相似度。 F ( Q , K ) F(Q,K) F(Q,K)表示相似度计算函数。
阶段2:计算 attention weight,将计算结果进行softmax归一化。
阶段3:根据 attention weight,对所有value进行加权平均得到输出向量,也就是例子中的 C C C
transformer中的self-Attention
self-Attention
在Self-Attention,每个词以自己的embedding为query,查询由所有词汇的embedding构成的memory空间,得到查询结果作为本词的表示。
上面提到的Attention机制里面,是直接用词向量X去与其他词向量X计算相似度进而得到attention 权重,得到最终向量。而在transform中的self-attention则有所不同,对每一个词向量先进行一定的变换,然后再进行Attention机制。
为了对每一个词向量先进行一定的变换,我们引入三个矩阵Queries,Keys,Values三个权重矩阵。将输入矩阵X(X的每一行代表一个词向量,例子中的第一、二行分别表示Thinking、Machines的词向量)分别与权重矩阵相乘得到新的矩阵Q 、K、V。
Q:query表示要去查询的矩阵,Q等效于Attention机制图中阶段1的query
K:key,表示等着被查的矩阵,K中的每一行等效于Attention机制图中阶段1的{key_1,key_2……}
V:value,表示实际的特征值。V等效于Attention机制图中阶段3的{value_1,value_2……}
通过得到的Q、K来计算相似度,如下图所示:
用Thinking 的 Embedding:x_1进行变换后的q_1分别与其他的k_i计算相似度(用内积代替相似度)。将相似度进行归一化和softmax就可以得到权重。将权重与V进行加权平均得到输出向量,如下图所示:
可以结合下图理解上述过程:
图中的Query Key Value Attention均是向量。
Query先和Key1 Key2 Key3 Key4去计算出相似度,然后归一化&softmax,再将得到的权重 a 1 , a 2 , a 3 , a 4 a_1, a_2, a_3,a_4 a1,a2,a3,a4与Value1 Value2 Value3 Value4进行加强输出。
下面是完整的计算流程图:
多头机制
多头机制的思想类似于卷积神经网络中的filter,为了从不同的角度提取图像的特征,往往使用多个filter,在这里多头机制中则使用多个不同的 W Q , Q K , W V W^Q,Q^K,W^V WQ,QK,WV 从而得到不同的 Q , K , V Q,K,V Q,K,V ,从而得到多个特征表达,如下图所示:
然后对每一组 Q , K , V Q,K,V Q,K,V都执行self-attention的计算过程。如下图所示:
将得到的多个特征表达拼接在一起,然后通过一个全连接层来降维,从而得到最终的结果。
这个过程是一个并行的过程:
下图是两个不同的head得到的不同的注意力结果,得到的特征向量表达也不同。说明可以提取到不同的特征。
self-Attention位置信息的表达
在self-attention中每个词都会考虑整个序列的加权,所以其出现位置并不会对结果产生什么影响,相当于放哪都无所谓,但是这跟实际就
有些不符合了,我们希望模型能对位置有额外的认识。所以我们在做self-Attention之前,引入位置信息的编码,说白了就是将每个词位置信息的编码与词向量进行相加后得到包含位置信息的词向量,然后进行self-Attention计算。如下图所示:
Transformer
基本结构
理解了self-Attention后,我们再看看看transform。先看下面的transformer局部图:
这是一个编码器。
图中的Self-Attention就是上述的多头注意力机制。
图中的黑色虚线表示残差连接。
图中的LayerNorm是指按层归一化,如下图所示:
这个编码器图是transformer的核心部分。transformer中的编码和解码部分往往是由多个self-Attention组成的多层多头self-Attention。
transformer的完整结构图如下:
(1)Encoding层 ,输入是引入位置信编码的句子词向量(完整句子),然后做N个多头Self-Attention,层层堆叠,最终输出新的词向量。
(2)Decoding层,对于模型已经生成的部分词向量(在机器翻译过程中,按顺序依次生成“汤姆”,“汤姆抓”,“唐汤姆抓杰瑞”),Decoding层的输入是已经生成的词组成的词向量(部分句子的词向量),在transform中称为Mask机制。获得输入后,也是做N个多头Self-Attention,层层堆叠,最终输出新的词向量。
(3)Encoding-Decoding Self-Attention层 ,在这里,输入包括两个部分。其一Encoding层通过生成的Q新的词向量,计算出新的K,V矩阵。其二Decoding层通过生成的新的词向量,计算出新的Q矩阵。接着做N个多头Self-Attention,层层堆叠,最终输出新的词向量。
(4)线性变换和Softmax层
线性变换层是一个简单的全连接神经网络,它可以把解码组件产生的向量投射到一个比它大得多的、被称作对数几率(logits)的向量里。不妨假设我们的模型从训练集中学习一万个不同的英语单词(我们模型的“输出词表”)。因此对数几率向量为一万个单元格长度的向量——每个单元格对应某一个单词的分数。接下来的Softmax 层便会把那些分数变成概率(都为正数、上限1.0)。概率最高的单元格被选中,并且它对应的单词被作为这个时间步的输出。如下图所示:
从底部以解码器组件产生的输出向量开始。之后它会转化出一个输出单词。可以用它的输出去与真实的输出做比较。
transform与RNN的对比
RNN的基本结构图如下:
计算过程:
h
i
=
f
(
[
W
⋅
x
i
,
U
⋅
h
i
−
1
]
+
b
)
h_i = f([\mathbf W \cdot x_i,\mathbf U \cdot h_{i-1}]+b)
hi=f([W⋅xi,U⋅hi−1]+b)
(1)第一个优势
当计算隐向量时,需要用到上一次的隐向量
h
i
−
1
h_{i-1}
hi−1和当前的输入
x
i
x_i
xi,随着距离拉远,包含前面输入的信息越来越少。但是Transformer这个结构就不存在这个问题,不管当前词和其他词的空间距离有多远,包含其他词的信息不取决于距离,而是取决于两者的相关性,这是Transformer的第一个优势。
(2)第二个优势
对于Transformer来说,在对当前词进行计算的时候,不仅可以用到前面的词,也可以用到后面的词。而RNN只能用到前面的词,这并不是个严重的问题,因为这可以通过双向RNN来解决。
(3)第三个优势
RNN是一个顺序的结构,必须要一步一步地计算,只有计算出h1,才能计算h2,再计算h3,隐向量无法同时并行计算,导致RNN的计算效率不高,这是RNN的固有结构所造成的,之前有一些工作就是在研究如何对RNN的计算并行化。通过前文的介绍,可以看到Transformer不存在这个问题。transform的多头机制是一个并行计算的过程。
更多推荐
所有评论(0)