Seq2Seq
讲解Attention之前,必须先了解Seq2Seq模型。
sequence to sequence模型广泛应用于机器翻译、机器问答、文章摘要、图片描述等等领域,是深度学习领域最常见的模型之一。它的基本结构如下:
- 模型包含一个编码器encoder和一个解码器decoder。编码器encoder将输入序列source转化成一种中间表示形式C:
source=(x1,x2,...,xm)
C=F(x1,x2,...,xm)
- 解码器decoder依赖中间表示C和已经生成的序列,生成当前序列:
yi=G(C,y1,y2,...,yi−1)
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是固定不变的,也就是
y2=G(C,y1),y3=G(C,y2,y1),yn=G(C,yn−1,...,y1)。这种设计也是不合理的。因为target序列的每个元素所依赖的source序列元素往往不同。例如对于机器翻译任务来说,target序列的当前元素应该依赖于source序列的某个位置开始的一个或若干个元素,而不是整个source序列。这就是所谓的翻译问题重点对齐问题。
由此我们引入注意力机制。
Attention
普通seq2seq模型中target序列的生成方法为:
y1=G(C)
y2=G(C,y1)
y3=G(C,y2,y1)
yn=G(C,yn−1,...,y1)
回忆上节的两个问题,其实可以归纳为一个问题,就是source序列的中间表示C的问题,沿着这个思路进行改进如下:
y1=G(C1)
y2=G(C2,y1)
y3=G(C3,y2,y1)
yn=G(Cn,yn−1,...,y1)
我们为target序列的每个元素
hj,生成一个定制的中间表示
Cj :
一般来说,
Cj的计算方式为encoder中间状态
hi的加权求和:
hi=f(xi,...,x1)
Cj=i=1∑mhiaij
aij=∑k=1mexp(ekj)exp(eij)
其中
eij表示source序列第i个元素对targer序列第j个元素的的影响程度。一般来说是一个关于关于encoder和decoder隐状态的函数:
eij=A(sj−1,hi)
函数
A()可以有不同的具体函数,代表着不同的注意力模型,比如:
A(s,h)=s⋅h
A(s,h)=s⋅W⋅h
A(s,h)=v⋅tanh(W⋅[s ;h])
总结
上文中我们由seq2seq模型开始,一步步分析引入了Attention机制。但其实Attention本身是一种通用的思想,经过进一步抽象之后,也可以用在其他的模型中。下面我们将Attention机制从seq2seq模型中剥离出来,看看Attention机制的本质思想是什么。
- 首先,Attention值本质是对一组
{Vi∣i∈[1,n]}的加权求和。
Attention=i=1∑nwiVi
-
第一步需要决定权重
wi如何计算。这一步一般来说又分为两步:计算相关性和权重归一化。
-
相关性计算
ri=R(Q,Vi)
-
相关性归一化
wi=∑k=1nexp(rk)exp(ri)
-
最后
Attention(Q,V)=i=1∑n∑k=1nexp(R(Q,Vk))exp(R(Q,Vi))Vi
其中计算相关性的函数
R可以有多重形式,比如最简单的:
ri=R(Q,Vi)=Q⋅Vi