论文地址
GitHub代码地址
论文题目为《基于双阶段注意力机制的循环神经网络》,文章本质上还是基于Seq2Seq的模型,结合了注意力机制实现的时间序列的预测方法,文章的一大亮点是:不仅在解码器的输入阶段引入注意力机制,还在编码器阶段引入注意力机制,编码器的阶段的注意力机制实现了特征选取和把握时序依赖关系的作用。
分为两个阶段:
- 第一阶段:使用注意力机制从而能够自适应提取每个时刻的特征,这是本文的最大亮点
- 第二阶段:使用注意力机制选取与之相关的encoder hidden states
1:模型架构图

算法实现流程:
- 编码器阶段,也就是输入阶段,利用Attention机制,即:原始xt=(xt1,xt2,…,xtn) 利用Attention机制,结合隐层信息,会对每一维特征赋予一定的权重,转变为:x~t=(αt1xt1,αt2xt2,…,αtnxtn),从而实现自适应提取每个时刻的各个维度特征,使用更新后的 x~t 作为编码器的输入。这也是本篇文章最大的亮点!
- 解码器阶段,也就是输出阶段,与传统Attention实现功能相同,使用另一个注意力机制选取与之相关的encoder hidden states
2:输入阶段的Attention
第一阶段输入阶段的编码器Attention机制实现过程如下:

文章中定义 ht∈Rm 为encoder在时刻 t 的hidden state, 其中 m 是hidden state的大小。
第一阶段,使用当前时刻的输人 xt∈Rn, 以及上一个时刻编码器的hidden state ht−1, 来计算当前时刻编码器的hidden state ht∈Rm, 其中m是编码器的size。更新公式可写为:
ht=f1(ht−1,xt)
其中f1是一个非线性**函数,我们可以使用通常的循环神经网络vanilla RNN或LSTM以及GRU作为 f1 ,在该文章中,使用的是LSTM来捕获长依赖关系。
这里,为了自适应地选取相关feature(即给每一个特征赋予一定的权重), 作者在此处引入了注意力机制。简单来说,即对每个时刻的输入 xt 为其中的每个影响因子赋予一定的注意力权重(attention weight) αtk 。 αtk 衡量了时刻 t 的第 k 个 feature的重要性。更新后的 x~t 为
x~t=(αt1xt1,αt2xt2,…,αtnxtn)
那么 αtk 如何计算得到?
文章中给出的方法:根据上一个时刻编码器的hidden state ht−1 和cell state st−1 计算得到:
etk=veTtanh(We[ht−1;st−1]+Uexk)
其中 [ht−1;st−1] 是hidden state ht−1 与cell state st−1 的连接(concatenation)。
该式即把第 k 个driving series(文章中的driving series就是特征的含义)与前一个时刻的hidden state ht−1 和cell state st−1 线性组合, 再用 tanh**得到。
计算得到 etk 后,再用softmax函数进行归一化:
αtk=∑i−1nexp(eti)exp(etk)
更新后的 x~t
x~t=(αt1xt1,αt2xt2,…,αtnxtn)作为下一个阶段temporal Attention的输入
input attention机制,使得编码器能够关注其中输入特征中重要的特征,而不是对所有特征一视同仁,这也是所有attention的本质作用。
3:temporal attention的解码器
第二阶段temporal Attention机制实现过程如下:

为了区别起见,参考知乎罗未萌的建议,与论文中公式略有不同的是,将解码器中的时间序列下标标注为 t′, 以与编码 器种的下标 t 区分。
第二阶段的解码器注意力机制设计类似于传统的seq2seq中的Attention机制,也就是第二阶段temporal attention的机制其实就是传统Attention的机制。
传统Attentionde 解决的问题是: 传统的seq2seq模型中, 编码器输出的context vector基于最后时刻的hidden state或对所有 hidden state取平均。这样输出的context vector对所有时刻 t 均相同,没有体现出差异化,就像人一样没有将注意力集中到关键部分,无法起到只选取相关时刻编码器hidden state的功能。
解决问题的思路是在不同时刻采用不同的context vector。类似于 seq2seq, 最简单的办法是对所有时刻的 ht′ 取加权平均, 即:
ct′=t=1∑Tβt′tht
βt′t 的 基于前一个时刻解码器的hidden state dt′−1 和cell state st′−1′ 计算得到:
lt′t=vdTtanh(Wd[dt′−1;st′−1′]+Udht)
βt′t=∑j=1Texp(lt′j)exp(lt′t)
根据文章中的模型流程,可以看到解码器的输入是上一个时刻的目标序列 yt′−1 和hidden state dt′−1 以及context vector ct′−1共同组成
即dt′=f2(yt′−1,ct′−1,dt′−1)
然后
dt′=f2(dt′−1,y~t′−1)
类似于编码器的最后一个公式, 这里的**函数 f2 还是选择LSTM。
4:预测部分
文章回顾了非线性自回归(Nonlinear autoregressive exogenous, NARX)模型的最终目标,需要建立当前输入与所有时刻的输人以及之前时刻的输出之间的关系,即:
y^T=F(y1,…,yT−1,x1,…,xT)
通过之前编码器解码器模型的训练,已经得到了解码器的hidden state 和context vector, hT 与 cT 。最后再使用一个全连接层对 y^T 做回归, 即
y^T=vyT(Wy[dT;cT]+bw)+bv
这样可以得到最终的预测 y^
5:总结
文章是将input Attention 和temporal Attention 分开讲述的,模型架构图是放在一起的,刚开始读完论文些不太理解的地方:
如input attention 中的f1是使用LSTM,接着x~t又作为temporal Attention 中LSTM的输入,接着解码层,又使用LSTM来进行预测,这样的话,不就是共有3个LSTM进行训练吗?
在深入阅读以及查看源代码后,发现之前理解出现偏差,其实总共只有2个阶段LSTM,分别对应input attention阶段用来提取自适应特征的attention模块中的LSTM,解码阶段的LSTM。我重新模型架构图整理了下,并进行箭头标注,表示对应的位置。
左边 input attention一大块计算得到的x~t, x~tx~t=(αt1xt1,αt2xt2,…,αtnxtn)
实际上只是temporal attention中的一个时刻的输入, 我们从input attentionht的与temporal attention中的ht对应的位置可以观察到。
也就是说,坐标的input attention 实际上只是temporal attention将某一个时刻剥离出来的计算过程细节而已。单看右边的temporal attention,实际上就是一个Seq2Seq的attention的实现,并没有不同,作者将temporal attention的输入x~t单独剥离出来,强调其计算过程,也就是input attention的实现机制,目的就是说明文章的亮点:在输入阶段也实现基于attention的自适应特征的提取
