本文部分内容参考于张俊林的博客,每一次不输出的学习,归根到底就是一场偷懒式的学习,切记切记。
注意力机制模型
encoder-decoder框架
一般来说该模型适合于使用一个句子来生成另一个句子,适用于机器翻译等自然语言处理模型。
这里的source=
<
x
1
,
x
2
,
x
3
,
x
4
>
<x1,x2,x3,x4>
<x1,x2,x3,x4>,而target=
<
y
1
,
y
2
,
y
3
>
<y1,y2,y3>
<y1,y2,y3>
encoder:对输入的句子进行编码,将句子通过非线性变换转为中间语义C,可以抽象为以下公式:
c
=
f
(
x
1
,
x
1
,
x
3
,
x
4
)
c=f(x1,x1,x3,x4)
c=f(x1,x1,x3,x4)
decoder:解码器是对中间语义C和之前已经生成的历史信息来生成当前时刻需要的单词:例如针对
y
3
y3
y3,那么历史信息就是
y
1
,
y
2
y1,y2
y1,y2
y
3
=
g
(
C
,
y
1
,
y
2
)
y3=g(C,y1,y2)
y3=g(C,y1,y2)
现在将输出
y
y
y抽象为输出的单词数量有i个,那么整个系统可以根据source来生成target,source是中文,那么target就是英文。这是解决机器翻译的框架。
不加注意力机制的问题
通过观察可以看出来:
y
1
=
g
(
C
)
,
y
2
=
g
(
C
,
y
1
)
,
y
3
=
g
(
C
,
y
1
,
y
2
)
y1=g(C) ,y2=g(C,y1),y3=g(C,y1,y2)
y1=g(C),y2=g(C,y1),y3=g(C,y1,y2)
由于C的产生是通过encoder编码产生的,它们是一样的,没有任何区别。这便意味着输入(source)中的单词对于输出yi的作用是一样的,这就像是人的眼睛可以看到一幅画面,但是却没有焦点。
举一个例子:
假如我们的source是[Tom chase Jerry],生成的中文单词是[“汤姆”,“追逐”,“杰瑞”],那么在翻译Tom单词的时候,chase和jerry对于‘汤姆’的影响力应该很小。如下所示,目标中的单词应该需要学会根据source单词的注意力分配概率信息,这意味着生成的每个单词yi的时候,原先句子中的C会替换为当前的Ci
即有:
y
1
=
g
(
c
1
)
,
y
2
=
g
(
c
2
,
y
1
)
,
y
3
=
g
(
c
3
,
y
1
,
y
2
)
y1=g(c1),y2=g(c2,y1),y3=g(c3,y1,y2)
y1=g(c1),y2=g(c2,y1),y3=g(c3,y1,y2)
对应的每一个ci:
C
汤
姆
=
s
(
0.6
∗
f
2
(
"
T
o
m
"
)
,
0.2
∗
f
2
(
"
c
h
a
s
e
"
)
,
0.3
∗
f
3
(
"
j
e
r
r
y
"
)
)
C_{汤姆}=s(0.6*f2("Tom"),0.2*f2("chase"),0.3*f3("jerry"))
C汤姆=s(0.6∗f2("Tom"),0.2∗f2("chase"),0.3∗f3("jerry"))
C
追
逐
=
s
(
0.2
∗
f
2
(
"
T
o
m
"
)
,
0.7
∗
f
2
(
"
c
h
a
s
e
"
)
,
0.1
∗
f
3
(
"
j
e
r
r
y
"
)
)
C_{追逐}=s(0.2*f2("Tom"),0.7*f2("chase"),0.1*f3("jerry"))
C追逐=s(0.2∗f2("Tom"),0.7∗f2("chase"),0.1∗f3("jerry"))
如果给定的encode框架是RNN框架,这里的f2其实就是输入xi结点之后隐层结点的状态值。
C
i
=
∑
j
=
1
L
x
a
i
j
h
j
Ci=\sum_{j=1}^{L_x}a_{ij}h_j
Ci=j=1∑Lxaijhj
其中
h
j
h_{j}
hj代表的是输入单词中第j个单词的语义编码。
L
x
L_{x}
Lx代表的是输入句子source的长度。
a
i
j
a_{ij}
aij代表的是输出为第
i
i
i个单词的时候,对应的source中,针对source中第
j
j
j个单词分配的概率值,例如输出的
i
=
1
i=1
i=1,对应的单词为汤姆,那么
a
11
=
0.6
,
a
12
=
0.2
,
a
13
=
0.3
a_{11}=0.6,a_{12}=0.2,a_{13}=0.3
a11=0.6,a12=0.2,a13=0.3,如果
i
=
2
i=2
i=2,输出的为追逐,那么
a
21
=
0.2
,
a
22
=
0.7
,
a
23
=
0.1
a_{21}=0.2,a_{22}=0.7,a_{23}=0.1
a21=0.2,a22=0.7,a23=0.1。
如何计算注意力概率分布值
如果了解过RNN网络结构的朋友们知道,当前时刻的输出和当前时刻的输入和上一个结点的输出都有关系,这里的
h
i
−
1
h_{i-1}
hi−1就是前一个隐藏结点的输出值。当前时刻yi输出是由前一时刻的
h
i
−
1
h_{i-1}
hi−1和当前时刻的
y
i
−
1
y_{i-1}
yi−1共同决定的。
1.计算source中的每一个
h
j
hj
hj和
h
i
−
1
h_{i-1}
hi−1的关联性即可,常用的方法是求内积,当然在不同论文里可能会采取不同的方法。称这里计算关联性的函数为
F
(
h
j
,
h
i
−
1
)
F(hj,h_{i-1})
F(hj,hi−1).
2.F输出之后经过softmax归一化之后,就可以得到概率分布的数值。
是target中的某个query。
source(key,value)。
计算query和每个key的相似度或者相关性,得到每个key值对应value的权重洗漱,之后对value加权求和,得到最终的attention的数值。
attention机制的本质思想
如上图所示,将attention机制从encoder-decoder编码中剥离,那么它的本质如下所示。
我们将source想象成:包含一系列的<key,value>键值对组成 ,此时给定了target元素中某个元素query,例如汤姆,通过计算key和target的相似度,然后将得到key对于value的权重系数,然后权重系数和value进行加权求和的操作。
注意,Lx代表的是source的长度。机器翻译的例子中:key和value指的是同一个东西,即输入句子中每个单词的语义编码,我们将以上表述的过程再次抽象一下,可以明白注意力机制的大致流程。
阶段1:
计算某一个query和所有Key的相似度,从而可以得到针对不同的Key值的权重系数。
常用的权重系数的计算公式如下:第一个是用的最多的。
阶段2:
由于得到的系数可能处于不同的范围之内,所以需要对其进行归一化的处理,使得它们的取值都落在[0,1]之间,使用的是softmax函数,最终它们的概率值相加之后的结果为1。
为什么使用softmax函数:可以更加突出重要元素的权重,记得之前看过一篇文章,通过softmax归一化处理之后,使得系数大的占比更大,而系数小的占比很小。
公式如下:
a
i
=
s
o
f
t
m
a
x
(
s
i
m
i
)
=
e
s
m
i
∑
j
=
1
L
x
e
s
i
m
j
a_{i}=softmax(sim_{i})=\frac{e^{smi}}{\sum_{j=1}^{L_x}e^{sim_j}}
ai=softmax(simi)=∑j=1Lxesimjesmi
其中
L
x
L_x
Lx是句子的长度.
阶段3:
这里value值对应的权重系数就是
a
i
a_{i}
ai,将每一个权重系数和对应的
v
a
l
u
e
i
value_{i}
valuei相乘再相加,就可以得到最终的注意力数值。
self_attention机制
这里大概的提一下self_attention,它又被称为(intra-attention),大部分的机器翻译模型都采用的该模型。文章中指出,self_attention机制可任意捕获一个句子中单词之间的句法特别或者语义特征,因此它更有助于捕获句子中长距离的相互依赖特征。
使用RNN或者LSTM,需要依照序列的次数进行计算,如果两个单词相距比较远,那么有效捕获的可能性比较小。这就是self_attention被广泛使用的主要原因。
一般的attention:source和target是不一样的,它计算的是target的元素query和source的元素key的关联度的计算。
source attention:它计算的是source元素之间关联度或者是target元素之间的相似度
如下图所示:计算的是source之间的,也可以理解成source=target。
以上是对所学知识的一个总结,下一篇将会记录self_attention(李宏毅教授的笔记)。