Seq2Seq
讲解Attention之前,必须先了解Seq2Seq模型。
sequence to sequence模型广泛应用于机器翻译、机器问答、文章摘要、图片描述等等领域,是深度学习领域最常见的模型之一。它的基本结构如下:
- 模型包含一个编码器encoder和一个解码器decoder。编码器encoder将输入序列source转化成一种中间表示形式C:
s
o
u
r
c
e
=
(
x
1
,
x
2
,
.
.
.
,
x
m
)
source = (x_1, x_2, ..., x_m)
source=(x1,x2,...,xm)
C
=
F
(
x
1
,
x
2
,
.
.
.
,
x
m
)
C = F(x_1, x_2, ..., x_m)
C=F(x1,x2,...,xm)
- 解码器decoder依赖中间表示C和已经生成的序列,生成当前序列:
y
i
=
G
(
C
,
y
1
,
y
2
,
.
.
.
,
y
i
−
1
)
y_i = G(C, y_1, y_2, ..., y_{i-1})
yi=G(C,y1,y2,...,yi−1)
t
a
r
g
e
t
=
(
y
1
,
y
2
,
.
.
.
,
y
n
)
target = (y_1, y_2, ..., y_n)
target=(y1,y2,...,yn)
- source和target序列可以为文本、语音、图像,分别用于不同类型的任务。比如source和target为同语言的文本,则可用于文本摘要任务,或则问答任务;不同语言文本,则用于语言翻译任务;source为语音序列,target为文本序列,则用于语音识别任务,等等。
Google 2014年的论文《Sequence to Sequence Learning with Neural Networks》介绍了一种基于RNN的seq2seq模型。基本结构如下:
这种结构的模型至少存在两方面的问题:
- source序列的中间表示C形式固定,当source序列较长时,信息量的压缩比较大,模型的性能急剧下降
- target序列的每个元素,所依赖的中间表示C是固定不变的,也就是 y 2 = G ( C , y 1 ) , y 3 = G ( C , y 2 , y 1 ) , y n = G ( C , y n − 1 , . . . , y 1 ) y_2=G(C, y_1),y_3=G(C,y_2,y_1),y_n=G(C,y_{n-1},...,y_1) y2=G(C,y1),y3=G(C,y2,y1),yn=G(C,yn−1,...,y1)。这种设计也是不合理的。因为target序列的每个元素所依赖的source序列元素往往不同。例如对于机器翻译任务来说,target序列的当前元素应该依赖于source序列的某个位置开始的一个或若干个元素,而不是整个source序列。这就是所谓的翻译问题重点对齐问题。
由此我们引入注意力机制。
Attention
普通seq2seq模型中target序列的生成方法为:
y
1
=
G
(
C
)
y_1=G(C)
y1=G(C)
y
2
=
G
(
C
,
y
1
)
y_2=G(C, y_1)
y2=G(C,y1)
y
3
=
G
(
C
,
y
2
,
y
1
)
y_3=G(C,y_2,y_1)
y3=G(C,y2,y1)
y
n
=
G
(
C
,
y
n
−
1
,
.
.
.
,
y
1
)
y_n=G(C,y_{n-1},...,y_1)
yn=G(C,yn−1,...,y1)
回忆上节的两个问题,其实可以归纳为一个问题,就是source序列的中间表示C的问题,沿着这个思路进行改进如下:
y
1
=
G
(
C
1
)
y_1=G(C_1)
y1=G(C1)
y
2
=
G
(
C
2
,
y
1
)
y_2=G(C_2, y_1)
y2=G(C2,y1)
y
3
=
G
(
C
3
,
y
2
,
y
1
)
y_3=G(C_3,y_2,y_1)
y3=G(C3,y2,y1)
y
n
=
G
(
C
n
,
y
n
−
1
,
.
.
.
,
y
1
)
y_n=G(C_n,y_{n-1},...,y_1)
yn=G(Cn,yn−1,...,y1)
我们为target序列的每个元素
h
j
h_j
hj,生成一个定制的中间表示
C
j
C_j
Cj :
一般来说, C j C_j Cj的计算方式为encoder中间状态 h i h_i hi的加权求和:
h
i
=
f
(
x
i
,
.
.
.
,
x
1
)
h_i = f(x_i,...,x_1)
hi=f(xi,...,x1)
C
j
=
∑
i
=
1
m
h
i
a
i
j
C_j = \sum_{i=1}^mh_ia_{ij}
Cj=i=1∑mhiaij
a
i
j
=
e
x
p
(
e
i
j
)
∑
k
=
1
m
e
x
p
(
e
k
j
)
a_{ij}=\frac{exp(e_{ij})}{\sum_{k=1}^mexp(e_{kj})}
aij=∑k=1mexp(ekj)exp(eij)
其中 e i j e_{ij} eij表示source序列第i个元素对targer序列第j个元素的的影响程度。一般来说是一个关于关于encoder和decoder隐状态的函数:
e i j = A ( s j − 1 , h i ) e_{ij}=A(s_{j-1}, h_i) eij=A(sj−1,hi)
函数 A ( ) A() A()可以有不同的具体函数,代表着不同的注意力模型,比如:
A
(
s
,
h
)
=
s
⋅
h
A(s, h) = s \cdot h
A(s,h)=s⋅h
A
(
s
,
h
)
=
s
⋅
W
⋅
h
A(s, h) = s \cdot W \cdot h
A(s,h)=s⋅W⋅h
A
(
s
,
h
)
=
v
⋅
t
a
n
h
(
W
⋅
[
s
;
h
]
)
A(s, h) = v \cdot tanh(W \cdot [s\space;h])
A(s,h)=v⋅tanh(W⋅[s ;h])
总结
上文中我们由seq2seq模型开始,一步步分析引入了Attention机制。但其实Attention本身是一种通用的思想,经过进一步抽象之后,也可以用在其他的模型中。下面我们将Attention机制从seq2seq模型中剥离出来,看看Attention机制的本质思想是什么。
- 首先,Attention值本质是对一组 { V i ∣ i ∈ [ 1 , n ] } \{V_i| i \in[1,n]\} {Vi∣i∈[1,n]}的加权求和。
A t t e n t i o n = ∑ i = 1 n w i V i Attention=\sum_{i=1}^nw_iV_i Attention=i=1∑nwiVi
-
第一步需要决定权重 w i w_i wi如何计算。这一步一般来说又分为两步:计算相关性和权重归一化。
-
相关性计算
r i = R ( Q , V i ) r_i = R(Q, V_i) ri=R(Q,Vi) -
相关性归一化
w i = e x p ( r i ) ∑ k = 1 n e x p ( r k ) w_i = \frac{exp(r_i)}{\sum_{k=1}^nexp(r_k)} wi=∑k=1nexp(rk)exp(ri) -
最后
A t t e n t i o n ( Q , V ) = ∑ i = 1 n e x p ( R ( Q , V i ) ) ∑ k = 1 n e x p ( R ( Q , V k ) ) V i Attention(Q, \mathcal{V})=\sum_{i=1}^n\frac{exp(R(Q, V_i))}{\sum_{k=1}^nexp(R(Q, V_k))}V_i Attention(Q,V)=i=1∑n∑k=1nexp(R(Q,Vk))exp(R(Q,Vi))Vi
其中计算相关性的函数 R R R可以有多重形式,比如最简单的:
r i = R ( Q , V i ) = Q ⋅ V i r_i = R(Q, V_i)=Q\cdot V_i ri=R(Q,Vi)=Q⋅Vi