Skip to content

图文介绍RNN注意力机制

📅 发表于 2017/10/10
🔄 更新于 2017/10/10
👁️ 次访问
📝 0 字
0 分钟
自然语言处理
#自然语言处理
#Attention Model
#Encoder-Decoder
#注意力
#机器翻译

用图文简单介绍基于RNN的Encoder-Decoder中注意力机制

Encoder-Decoder

基本介绍

举个翻译的例子,原始句子X=(x1,x2,,xm) ,翻译成目标句子Y=(y1,y2,,yn)

现在采用Encoder-Decoder架构模型,如下图

Encoder会利用整个原始句子生成一个语义向量,Decoder再利用这个向量翻译成其它语言的句子。这样可以把握整个句子的意思、句法结构、性别信息等等。具体框架可以参考Encoder-Decoder框架

Encoder对X 进行非线性变换得到中间语义向量c

c=G(x1,x2,,xn)

Decoder根据语义c 和生成的历史单词(y1,y2,,yi1)生成第i 个单词 yi

yi=f(c,y1,y2,,yi1)

Encoder-Decoder是个创新大杀器,是个通用的计算框架。Encoder和Decoder具体使用什么模型,都可以自己选择。通常有CNN,RNN,BiRNN,GRU,LSTM, Deep LSTM。上面的内容任意组合,只要得到的效果好,就是一个创新,就可以毕业了。(当然别人没有提出过)

缺点

在生成目标句子Y的单词时,所有的单词yi使用的语义编码c 都是一样的。而语义编码c是由句子X 的每个单词经过Encoder编码产生,也就是说每个xi对所有yj的影响力都是相同的,没有任何区别的。所以上面的是注意力不集中的分心模型

句子较短时问题不大,但是较长时,所有语义完全通过一个中间语义向量来表示,单词自身的信息已经消失,会丢失更多的细节信息

例子

比如输入XTom chase Jerry,模型翻译出 汤姆 追逐 杰瑞。在翻译“杰瑞”的时候,“Jerry”对“杰瑞”的贡献更重要。但是显然普通的Encoder-Decoder模型中,三个单词对于翻译“Jerry-杰瑞”的贡献是一样的。

解决方案应该是,每个单词对于翻译“杰瑞”的贡献应该不一样,如翻译“杰瑞”时:

(Tom,0.3),(Chase,0.2),(Jerry,0.5)

Attention Model

基本架构

Attention Model的架构如下:

如图所示,生成每个单词yi时,都有各自的语义向量Ci,不再是统一的C

yi=f(Ci,y1,,yi1)

例如,前3个单词的生成:

y1=f(C1)y2=f(C2,y1)y3=f(C3,y1,y2)

语义向量的计算

注意力分配概率 aij 表示 yi收到xj 的注意力概率

例如X=(Tom,Chase,Jerry)Y=(,,)a12=0.2表示汤姆 收到来自Chase的注意力概率是0.2。

有下面的注意力分配矩阵:

A=[aij]=[0.60.20.20.20.70.10.30.10.5]

i行表示**yi 收到的所有来自输入单词的注意力分配概率**。yi 的语义向量Ci 由这些注意力分配概率和Encoder对单词xj的转换函数相乘,计算而成,例如:

C1=C=g(0.6h(Tom),0.2h(Chase),0.2h(Jerry))C2=C=g(0.2h(Tom),0.7h(Chase),0.1h(Jerry))C3=C=g(0.3h(Tom),0.2h(Chase),0.5h(Jerry))

h(xj) 就表示Encoder对输入英文单词的某种变换函数。比如Encoder使用RNN的话,h(xj)往往都是某个时刻输入xj隐层节点的状态值

g函数 表示注意力分配后的整个句子的语义转换信息,一般都是加权求和,则有语义向量计算公式:

Ci=j=1Txaijhj,hj=h(xj)

其中Tx 代表输入句子的长度。形象来看计算过程如下图:

注意力分配概率计算

语义向量需要注意力分配概率和Encoder输入单词变换函数来共同计算得到。

但是比如汤姆收到的分配概率a1=(0.6,0.2,0.2)是怎么计算得到的呢?

这里采用RNN作为Encoder和Decoder来说明。

注意力分配概率如下图计算

对于aij 其实是通过一个对齐函数F来进行计算的,两个参数:输入节点j,和输出节点i,当然一般是取隐层状态

ai=F(i,j),j[1,Tx],h(j)Encoder,H(i)Decoder

F(i,j)代表yixj对齐可能性。一般F输出后,再经过softmax就得到了注意力分配概率。

AM模型的意义

一般地,会把AM模型看成单词对齐模型,输入句子单词和这个目标生句子成单词的对齐概率。

其实,理解为影响力模型也是合理的。就是在生成目标单词的时候,输入句子中的每个单词,对于生成当前目标单词有多大的影响程度。

AM模型有很多的应用,思想大都如此。

文本摘要例子

比如文本摘要的例子,输入一个长句,提取出重要的信息。

输入"russian defense minister ivanov called sunday for the creation of a joint front for combating global terrorism"。

输出"russia calls for joint front against terrorism"。

下图代表着输入单词对输出单词的影响力,颜色越深,影响力越大,注意力分配概率也越大。

PyTorch翻译AM实现

思想

参考这篇论文

生成目标单词yi 的计算概率是

p(yi(y1,,yi1),x)=g(yi1,si,ci)

符号意义说明

  • yi 当前应该生成的目标单词,yi1 上一个节点的输出单词
  • si 当前节点的隐藏状态
  • ci 生成当前单词应该有的语义向量
  • g 全连接层的函数

隐层状态si

求当前Decoder隐层状态si:由上一层的隐状态si1,输出单词yi1 ,语义向量ci

si=f(si1,yi1,ci)

语义向量ci

语义向量:分配权值aij,Encoder的输出

ci=j=1Txaijhj,hj=h(xj)

分配概率aij

注意力分配概率aij yi 收到xj 的注意力:分配能量eij

aij=exp(eij)k=1Txexp(eik)

分配能量eij

xj 注意yi 的能量,由encoder的隐状态hj 和 decoder的上一层的隐状态si1 计算而成。a函数就是一个线性层。也就是上面的F函数。

eij=a(si1,hj)

实现

Decoder由4层组成

  • embedding : word2vec
  • attention layer: 为每个encoder的output计算Attention
  • RNN layer:
  • output layer:

Decoder输入 si1 , yi1 和encoder的所有outputs h

Embedding Layer

输入yi1,对其进行编码

python
# y(i-1)
embedded = embedding(last_rnn_output)

Attention Layer

输入si1,hj,输出分配能量eij, 计算出aij

python
attn_weights[j] = attn_layer(last_hidden, encoder_outputs[j])
attn_weights = normalize(attn_weights)

计算语义向量

求语义向量ci, 一般是加权求和

python
context = sum(attn_weights * encoder_outputs)

RNN Layer

输入si1,yi1,ci ,内部隐层状态,输出si

python
rnn_input = concat(embeded, context)
rnn_output, rnn_hidden = rnn(rnn_input, last_hidden)

输出层

输入yi1,si,ci ,输出yi

python
output = out(embedded, rnn_output, context)
总访客数:   ·   总访问量:
PLM's Blog @ 2016 - 2025