1. 实际应用中,网络输出 可能依赖于整个输入序列。如:语音识别任务中,当前语音对应的单词不仅取决于前面的单词,也取决于后面的单词。因为词与词之间存在语义依赖。

      双向 RNN 就是为了解决这种双向依赖问题,它在需要双向信息的应用中非常成功。如:手写识别、语音识别等。

    2. 典型的双向 RNN 具有两条子RNN

      • 四、常见 RNN 变种 - 图1 代表通过时间向未来移动的子 RNN的状态,向右传播信息; 代表通过时间向过去移动的子 RNN 的状态,向左传播信息。

      • 四、常见 RNN 变种 - 图2 时刻的输出 同时依赖于过去、未来、以及时刻 四、常见 RNN 变种 - 图3 的输入 。

      • 模型的数学表示:四、常见 RNN 变种 - 图4

      • 单个样本的损失:

      • 更新方程:

        四、常见 RNN 变种 - 图5

        其中输入到隐状态的权重为 ,隐状态到输出的权重为 四、常见 RNN 变种 - 图6 ,隐状态到隐状态的权重为 ,四、常见 RNN 变种 - 图7 为输入偏置向量和输出偏置向量。

    3. 如果输入是 2 维的(如图像),则双向 RNN 可以扩展到4个方向:上、下、左、右。

      每个子 RNN 负责一个时间移动方向,四、常见 RNN 变种 - 图8 时刻的输出 同时依赖于四个方向、以及时刻 四、常见 RNN 变种 - 图9 的输入 。

      CNN 相比:

      • RNN 可以捕捉到大多数局部信息,还可以捕捉到依赖于远处的信息;CNN 只能捕捉到卷积窗所在的局部信息。
      • RNN计算成本通常更高,而CNN 的计算成本较低。
    1. 前述RNN中的计算都可以分解为三种变换:从输入 四、常见 RNN 变种 - 图10 到隐状态 的变换、从前一个隐状态 四、常见 RNN 变种 - 图11 到下一个隐状态 的变换、从隐状态 四、常见 RNN 变种 - 图12 到输出 的变换。这三个变换都是浅层的,即:由一个仿射变换加一个激活函数组成。

      事实上,可以对这三种变换中引入深度。实验表明:引入深度会带来好处。

      • 方式一:通过将RNN的隐状态分为多层来引入深度。
      • 方式二:在这三种变换中,各自使用一个独立的MLP(可能是较浅的,也可能是较深的)。
      • 方式三:在第二种方式的基础上,类似ResNet 的思想,在 “隐状态-隐状态” 的路径中引入跳跃连接。
    2. 通过将RNN的隐状态分为多层来引入深度:如下所示,隐状态有两层: 四、常见 RNN 变种 - 图13 和 。隐状态层中层次越高,对输入提取的概念越抽象。

      • 模型的数学表示:四、常见 RNN 变种 - 图14

      • 单个样本的损失:

      • 更新方程:

        四、常见 RNN 变种 - 图15

        其中输入到隐状态的权重为 ,隐状态到输出的权重为 四、常见 RNN 变种 - 图16 ,隐状态到隐状态的权重为 ,四、常见 RNN 变种 - 图17 为输入偏置向量和输出偏置向量。

    3. 在这三种变换中,各自使用一个独立的MLP(可能是深度的),如下图所示。

      该方法有一个主要问题:额外深度将导致从时间步 四、常见 RNN 变种 - 图18 到时间步 的最短路径变得更长,这可能导致优化困难而破坏学习效果。

      四、常见 RNN 变种 - 图19

    4. 在第二种方式的基础上,类似ResNet 的思想,在 “隐状态-隐状态” 的路径中引入跳跃连接,从而缓解最短路径变得更长的问题。

    1. 目前实际应用中最有效的序列模型是门控RNN,包括基于LSTM: long short-term memory 的循环网络,和基于门控循环单元GRU: gated recurrent unit 的循环网络。

      围绕门控RNN 这一主题可以设计更多的变种。然而一些调查发现:这些 LSTMGRU架构的变种,在广泛的任务中难以明显的同时击败这两个原始架构。

    2. 门控RNN 的思路和渗漏单元一样:生成通过时间的快捷路径,使得梯度既不消失也不爆炸。

      • 可以手动选择常量的连接权重来实现这个目的,如跳跃连接。权重为固定的常量,且不随时间改变。
      • 可以使用参数化的连接权重来实现这个目的,如渗漏单元。权重是样本的函数,且不随时间改变。
      • 门控RNN 将其推广为:连接权重在每个时间步都可能改变。权重是样本和时间的函数,随时间改变。
    3. 渗漏单元允许网络在较长持续时间内积累信息,但它有个缺点:有时候希望一旦某个信息被使用(即:被消费掉了),那么这个信息就要被遗忘(丢掉它,使得它不再继续传递)。

      门控RNN 能够学会何时清除信息,而不需要手动决定。

    4.3.1 LSTM

    1. LSTM 在手写识别、语音识别、机器翻译、为图像生成标题等领域获得重大成功。

    2. LSTM循环网络除了外部的 RNN 循环之外,还有内部的 LSTM cell循环(自环)。LSTMcell代替了普通 RNN 的隐单元,而LSTM四、常见 RNN 变种 - 图20cell 的一个输出。

      LSTM引入cell循环以保持梯度长时间持续流动。其中一个关键是:cell循环的权重视上下文而定,而不是固定的。

      具体做法是:通过gate 来控制这个cell循环的权重,而这个gate 由上下文决定。

      • 注意:cell 输出是 ,而不是整个RNN 单元的输出 四、常见 RNN 变种 - 图21
      • cell 之间的连接是通过 来连接的。

      四、常见 RNN 变种 - 图22

    3. LSTM 最重要的就是cell 状态 ,它以水平线在图上方贯穿运行。

      四、常见 RNN 变种 - 图23

    4. sigmoid 函数 () 的输出在 01 之间,描述每个部分有多少量可以通过。它起到门gate 的作用:0 表示不允许通过,1 表示允许全部通过,0~1 之间表示部分通过。

      LSTM 拥有三个门:遗忘门、输入门、输出门。

    5. 输入门:控制了输入 四、常见 RNN 变种 - 图24中,有多少信息进入cell当前状态 。

      输入门 四、常见 RNN 变种 - 图25 的方程:

      写成向量的形式为:(四、常见 RNN 变种 - 图26 为逐元素的sigmoid 函数)

      其中:四、常见 RNN 变种 - 图27 为输入门的偏置, 为输入门的输入权重,四、常见 RNN 变种 - 图28 为输入门的循环权重。

    6. 输出门:控制了cell 状态 四、常见 RNN 变种 - 图29 中,有多少会进入cell 的输出 。

      输出门 四、常见 RNN 变种 - 图30 的更新方程:

      写成向量的形式: (四、常见 RNN 变种 - 图31 为逐元素的sigmoid 函数)

      其中:四、常见 RNN 变种 - 图32 为输出门的偏置, 为输出门的输入权重,四、常见 RNN 变种 - 图33 为输出门的循环权重。

    7. cell 状态更新:cell状态 四、常见 RNN 变种 - 图34 由两部分组成:

      • 一部分来自于上一次的状态 :它经过了遗忘门 四、常见 RNN 变种 - 图35 的控制,使得只有部分状态进入下一次。
      • 一部分来自于输入(包括 ):输入需要经过 四、常见 RNN 变种 - 图36 非线性层变换之后,然后经过输入门 的控制,使得只有部分输入能进入状态更新。

      因此cell 状态更新方程为:

      四、常见 RNN 变种 - 图37

      写成向量的形式为: ( 为逐元素的函数, 四、常见 RNN 变种 - 图38 为逐元素的向量乘积)

      其中:四、常见 RNN 变种 - 图39cell的偏置, 为cell的输入权重,四、常见 RNN 变种 - 图40cell的循环权重。

    8. cell 输出更新:cell 输出就是 ,它是将cell 状态经过了 四、常见 RNN 变种 - 图41 非线性层之后,再通过输出门 控制输出的流量。

      四、常见 RNN 变种 - 图42

      写成向量的形式: ( 为逐元素的函数, 四、常见 RNN 变种 - 图43 为逐元素的向量乘积)

    9. 一旦得到了 的输出 四、常见 RNN 变种 - 图44,则获取整个RNN 单元的输出 就和普通的 RNN相同。

      四、常见 RNN 变种 - 图45

      令节点 ,根据激活函数的性质: 四、常见 RNN 变种 - 图46 ,,则有:

      • 考虑到 四、常见 RNN 变种 - 图47 的后续节点为:当 为最后一个节点时,后续节点为 四、常见 RNN 变种 - 图48 ;当 不是最后一个节点时,后续节点为 四、常见 RNN 变种 - 图49 。因此有:

        四、常见 RNN 变种 - 图50

        因此有:

        • 由于 四、常见 RNN 变种 - 图51 中存在常量部分 ,因此 LSTM 可以缓解梯度消失。
        • 由于各种门的存在,因此 四、常见 RNN 变种 - 图52 中的非常量部分会被缩小,因此可以缓解梯度爆炸。
      • 考虑到 的后续节点为:当 四、常见 RNN 变种 - 图53 为最后一个节点时,后续节点为 ;当 四、常见 RNN 变种 - 图54 不是最后一个节点时,后续节点为 。因此有:

        四、常见 RNN 变种 - 图55

      • 考虑到 对于每个输出 四、常见 RNN 变种 - 图56 都有贡献,则有:

        其中 四、常见 RNN 变种 - 图57 表示 的第 四、常见 RNN 变种 - 图58 个分量。

      • 考虑到 对于每个状态 四、常见 RNN 变种 - 图59 都有贡献,则有:

        其中 四、常见 RNN 变种 - 图60 表示 的第 四、常见 RNN 变种 - 图61 个分量。

      • 考虑到 对于每个遗忘门 四、常见 RNN 变种 - 图62 都有贡献,则有:

        其中 四、常见 RNN 变种 - 图63 表示 的第 四、常见 RNN 变种 - 图64 个分量。

      • 考虑到 对于每个输入门 四、常见 RNN 变种 - 图65 都有贡献,则有:

        其中 四、常见 RNN 变种 - 图66 表示 的第 四、常见 RNN 变种 - 图67 个分量。

      • 考虑到 对于每个输出门 四、常见 RNN 变种 - 图68 都有贡献,则有:

        其中 四、常见 RNN 变种 - 图69 表示 的第 四、常见 RNN 变种 - 图70 个分量。

    10. 也可以选择使用cell 状态 作为这些门的额外输入。此时 四、常见 RNN 变种 - 图71 就多了额外的权重参数,这些参数对应于 的权重和偏置。

    4.3.2 GRU

    1. 门控循环单元GRULSTM 模型更简单:

      • GRU 的单个门控单元同时作为遗忘门和输入门,整个 GRU 模型只有两个门:更新门、复位门。
      • GRU 不再区分cell的状态 四、常见 RNN 变种 - 图72cell 的输出 。

      四、常见 RNN 变种 - 图73

    2. 更新门:控制了新的信息 ( 由 四、常见 RNN 变种 - 图74 生成)、旧的信息 中各有多少信息进入了 四、常见 RNN 变种 - 图75

      更新门 的更新方程:

      四、常见 RNN 变种 - 图76

      写成向量的形式为:( 为逐元素的sigmoid 函数)

      四、常见 RNN 变种 - 图77

      其中: 为更新门的偏置,四、常见 RNN 变种 - 图78 为更新门的输入权重, 为更新门的循环权重。

    3. 复位门:控制了新的信息 四、常见 RNN 变种 - 图79 中, 之间的比例。它表示在新的信息中,旧的信息多大程度上影响新的信息。如果 四、常见 RNN 变种 - 图80 ,则旧的信息不影响新的信息,可以理解为复位。

      复位门 的更新方程:

      四、常见 RNN 变种 - 图81

      写成向量的形式为:( 为逐元素的sigmoid 函数)

      四、常见 RNN 变种 - 图82

      其中: 为复位门的偏置,四、常见 RNN 变种 - 图83 为复位门的输入权重, 为复位门的循环权重。

    4. cell输出:cell 输出就是 四、常见 RNN 变种 - 图84

      cell 更新方程:

      写成向量的形式:(其中 四、常见 RNN 变种 - 图85 为逐元素的向量乘积; 为逐元素的函数)

      四、常见 RNN 变种 - 图86

      令 ,它刻画了本次的更新。于是cell 的输出更新方程为:

      四、常见 RNN 变种 - 图87

      其中: 为cell的偏置,四、常见 RNN 变种 - 图88cell的输入权重, 为cell的循环权重。

    5. 一旦得到了cell 的输出 四、常见 RNN 变种 - 图89,则获取整个RNN 单元的输出 就和普通的 RNN相同。

      四、常见 RNN 变种 - 图90

      令节点 ,根据激活函数的性质: 四、常见 RNN 变种 - 图91 ,,则有:

      • 考虑到 四、常见 RNN 变种 - 图92 的后续节点为:当 为最后一个节点时,后续节点为 四、常见 RNN 变种 - 图93 ;当 不是最后一个节点时,后续节点为 四、常见 RNN 变种 - 图94 。记 ,因此有:

        四、常见 RNN 变种 - 图95

        考虑到:

        因此有:

        四、常见 RNN 变种 - 图96

        • 由于 中存在常量部分 四、常见 RNN 变种 - 图97 ,因此 GRU 可以缓解梯度消失。
        • 由于各种门的存在,因此 中的非常量部分会被缩小,因此可以缓解梯度爆炸。
      • 考虑到 四、常见 RNN 变种 - 图98 对于每个输出 都有贡献,则有:

        四、常见 RNN 变种 - 图99

        其中 表示 四、常见 RNN 变种 - 图100 的第 个分量。

      • 考虑到 四、常见 RNN 变种 - 图101 对于每个状态 都有贡献,则有:

        四、常见 RNN 变种 - 图102

        其中 表示 四、常见 RNN 变种 - 图103 的第 个分量。

      • 考虑到 四、常见 RNN 变种 - 图104 对于每个复位门 都有贡献,则有:

        四、常见 RNN 变种 - 图105

        其中 表示 四、常见 RNN 变种 - 图106 的第 个分量。

      • 考虑到 四、常见 RNN 变种 - 图107 对于每个更新门 都有贡献,则有:

        四、常见 RNN 变种 - 图108

        其中 表示 四、常见 RNN 变种 - 图109 的第 个分量。

    4.3.3 讨论

    1. LSTMGRU 中有两种非线性函数: sigmoidtanh

      • sigmoid用于各种门,是因为它的阈值为 0~1,可以很好的模拟开关的关闭程度。

      • tanh 用于激活函数,是因为它的阈值为 -1~1,它的梯度的阈值为 0~1。

        • 如果使用sigmoid 作为激活函数,则其梯度范围为 0~0.5,容易发生梯度消失。

        • 如果使用relu 作为激活函数,则前向传播时,信息容易爆炸性增长。

          另外relu 激活函数也会使得输出只有大于等于0 的部分。

    2. 前面给出的 LSTMGRU 中,四、常见 RNN 变种 - 图110 是通过 feature map 直接相加,如 LSTM 中的状态更新方程:

      事实上,也可以通过 feature map 进行拼接,如:

      四、常见 RNN 变种 - 图111

      其中 表示将两个向量进行拼接。

      四、常见 RNN 变种 - 图112

    1. 前面介绍的多长度输入序列的模式中,输出序列和输入序列长度相同。实际任务中,如:语音识别、机器翻译、知识问答等任务,输出序列和输入序列长度不相等。

      编码-解码 架构就是为了解决这类问题。设输入序列为 ,输出序列为 四、常见 RNN 变种 - 图113 。长度 。

      C 为输入的一个表达representation ,包含了输入序列的有效信息。

      • 它可能是一个向量,也可能是一个固定长度的向量序列。
      • 如果 C 是一个向量序列,则它和输入序列的区别在于:序列C 是定长的、较短的;而输入序列是不定长的、较长的。
      • 编码器(也叫作读取器,或者输入RNN):处理输入序列。

        编码器的最后一个状态 四、常见 RNN 变种 - 图114 通常就是输入序列的表达C, 并且作为解码器的输入向量。

      • 解码器(也叫作写入器,或者输出RNN):处理输入的表达C

        解码器有三种处理C 的方式:输入 C 作为每个时间步的输入、输入 C 作为初始状态 且每个时间步没有额外的输入、结合上述两种方式。

      • 训练时,编码器和解码器并不是单独训练,而是共同训练以最大化 :

        四、常见 RNN 变种 - 图115

    2. 编码-解码架构的主要缺点:编码器RNN输出的上下文C的维度太小,难以恰当的概括一个长的输入序列的完整信息。

      可以通过引入attention机制来缓解该问题。

      四、常见 RNN 变种 - 图116

    1. attention 是一种提升 encoder - decoder 模型效果的机制,一般称作 attention mechanism

      • attention 被广泛用于机器翻译、语音识别、图像标注Image Caption 等领域。如:机器翻译中,为句子中的每个词赋予不同的权重。

      • attention 本身可以理解为一种对齐关系,给出了模型输入、输出之间的对齐关系,解释了模型到底学到了什么知识。

        • 在机器翻译中,解释了输入序列的不同位置对输出序列的影响程度。如下图所示为机器翻译中,输入-输出的 attention 矩阵。

        • 在图像标注中,解释了图片不同区域对输出文本序列的影响程度。如下图所示为图像标注中,影响输出单词的图像块。

          四、常见 RNN 变种 - 图117

    2. 设输入序列为 ,输出序列为 四、常见 RNN 变种 - 图118 ,长度 。设encoder 的隐向量为 四、常见 RNN 变种 - 图119decoder 的隐向量为 。

      • 对于传统的 encoder-decoder 模型,decoder 的输入只有一个向量,该向量就是输入序列经过encoder编码的上下文向量 四、常见 RNN 变种 - 图120

        通常将 encoder 的最后一个隐单元的隐向量 作为上下文向量。

      • 对于 attention encoder-decoder 模型,decoder 的输入是一个向量序列,序列长度为 四、常见 RNN 变种 - 图121

        decoder位置 的输入是采用了 attention 机制的上下文向量 四、常见 RNN 变种 - 图122,不同位置的上下文向量不同。

        • 上下文向量 由 的所有隐向量加权得到:四、常见 RNN 变种 - 图123

          其中 。

        • 权重 四、常见 RNN 变种 - 图124 刻画了:在对第 个输出进行解码时,第 四、常见 RNN 变种 - 图125 个输入的重要程度。

          一个直觉上的方法是:首先计算 与 四、常见 RNN 变种 - 图126 的相关性,然后对所有的 归一化即可得到权重系数。即:

          四、常见 RNN 变种 - 图127

          其中 score 由多种计算方式,不同的计算方式代表不同的 attention 模型( 为待学习的参数,n 为向量的维度):

          四、常见 RNN 变种 - 图128

    4.5.1 local attention

    1. 上述的 attention 机制中为了计算上下文向量 四、常见 RNN 变种 - 图129, 需要考虑 encoder 的所有隐向量。当输入序列较长时(如一段话或一篇文章),计算效率较低。

      local attention 在计算上下文向量 时只需要考虑 encoder 的部分隐向量:首选预测encoder 端对齐的位置 四、常见 RNN 变种 - 图130,然后基于位置 选择一个窗口来计算上下文向量 四、常见 RNN 变种 - 图131

      其中 四、常见 RNN 变种 - 图132 为待学习的参数, 为人工指定的固定常量。

      虽然 local attention 可以提高计算效率,但是会带来两个问题:

      • encoder 的输入序列长度 四、常见 RNN 变种 - 图133 并不是很长时,计算量并没有显著减小。
      • 位置 的预测并不是非常准确,这就直接影响了计算 attention 的准确性。

      四、常见 RNN 变种 - 图134`

    4.5.2 self attention

    1. 传统的 attention 是基于encoder 端和 decoder 端的隐向量来计算 attention 的,得到的是输入序列的每个 input 和输出序列的每个 output 之间的依赖关系。

      self attention 计算三种 attention

      • encoder 端计算自身的 attention,捕捉input 之间的依赖关系。
      • decoder 端计算自身的 attention,捕捉output 之间的依赖关系。
      • encoder 端得到的 self attention 加入到 decoder 端得到的 attention 中,捕捉输入序列的每个 input 和输出序列的每个 output 之间的依赖关系。

    2. 设输入序列为 四、常见 RNN 变种 - 图135 ,输出序列为 ,长度 四、常见 RNN 变种 - 图136

      • encoder 端的 self attention

        • 首先经过 映射得到 key 向量序列 四、常见 RNN 变种 - 图137 、经过 映射得到 query 向量序列 四、常见 RNN 变种 - 图138

        • 然后计算归一化的 self attention

          其中 四、常见 RNN 变种 - 图139 表示各输入与第 个输入的相关因子,四、常见 RNN 变种 - 图140

        • 最后得到经过加权的 encoder 输出向量: 。

      • decoder 端的 self attention:考虑到解码时 四、常见 RNN 变种 - 图141 时刻不知道 时刻及其之后的结果,因此仅考虑 四、常见 RNN 变种 - 图142 时刻之前的 attention,这被称作 masked attention 。因此对于时刻 :

        • 首先经过 四、常见 RNN 变种 - 图143 映射得到 key 向量序列 、经过 四、常见 RNN 变种 - 图144 映射得到 query 向量序列 。

        • 然后计算归一化的 self attention

          四、常见 RNN 变种 - 图145

          其中 表示各输入与第 四、常见 RNN 变种 - 图146 个输入的相关因子,。

        • 最后得到经过加权的 encoder 输出向量:四、常见 RNN 变种 - 图147

      • encoderdecoderattention

        • 计算归一化的 self attention

          其中 四、常见 RNN 变种 - 图148 表示各输入与第 个输出的相关因子, 四、常见 RNN 变种 - 图149

        • 最后得到经过加权的 attention 上下文向量: 。

      • 最后将上下文向量 四、常见 RNN 变种 - 图150 作为一个前馈神经网络的输入,其输出就是 。

    3. 上述 self attention 机制完全抛弃了 RNN 的架构,著名的 Transformer 架构就是基于它来构建的。

      self attention 未能考虑到输入序列的先后顺序,因此 Transformer 架构中引入了位置 embedding 来解决该问题。

    4. 理论上序列的 四、常见 RNN 变种 - 图151self attention 只需要简单计算:

      引入两个映射矩阵是为了更好的泛化:attention 并不仅仅考虑序列的原始信息,而是考虑了从序列中抽取的信息。

    4.5.3 Hierarchical attention

    1. 在论文《Hierarchical Attention Networks for Document Classification》 中提出了分层 attention 用于文档分类。论文提出了两个层次的 attention

      • 第一个层次是对句子中每个词进行 attention,即 word attention
      • 第二个层次是对文档中每个句子进行 attention,即 sentence attention

      四、常见 RNN 变种 - 图152

    2. 层次 attention 涉及到四个部分:

      • word encoder:(对于句子 )

        • word embedding四、常见 RNN 变种 - 图153

        • GRU 隐向量(原始论文中采用双向 GRU ):

      • word attention

        四、常见 RNN 变种 - 图154

        其中 表示这个单词序列的总信息,称作单词上下文。它是随机初始化并从网络训练得到。

      • sentence attention

        四、常见 RNN 变种 - 图155

        其中 表示这个句子序列的总信息,称作句子上下文。它是随机初始化并从网络训练得到。