社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  机器学习算法

【深度学习】基础知识--循环神经网络 RNN(上)

机器学习初学者 • 3 年前 • 643 次点击  

作者:华校专

作者信息:

华校专,曾任阿里巴巴资深算法工程师、智易科技首席算法研究员,现任腾讯高级研究员,《Python 大战机器学习》的作者。

编者按:

算法工程师必备系列更新啦!继上次推出了算法工程师必备的数学基础后,小编继续整理了必要的机器学习知识,全部以干货的内容呈现,哪里不会学哪里,老板再也不用担心你的基础问题!

循环神经网络 RNN

  1. 循环神经网络recurrent neural network:RNN :用于处理序列数据 的神经网络,其中 表示第 i 个样本。 是一个序列 ,序列的长度可以是固定的、也可以是变化的。

  • 固定的序列长度:对每个样本 ,其序列长度都是常数
  • 可变的序列长度:样本 的序列长度 可能不等于样本 的序列长度
  • 循环神经网络是一种共享参数的网络:参数在每个时间点上共享。

    传统的前馈神经网络在每个时间点上分配一个独立的参数,因此网络需要学习每个时间点上的权重。而循环神经网络在每个时间点上共享相同的权重。

  • 循环网络中使用参数共享的前提是:相同参数可以用于不同的时间步。即:前一个时间步和后一个时间步之间的关系与时刻 t 无关。

  • 就像几乎所有函数都可以被认为是前馈神经网络,几乎任何涉及循环的函数都可以被认为是循环神经网络。

  • 一、RNN计算图

    1.1 展开图

    1. 考虑动态系统的经典形式: 。其中: 称作系统的状态, 为参数。

      对于有限的时间步 ,应用 次定义可以展开这个图:

      利用有向无环图来表述:



    假设 为 t 时刻系统的外部驱动信号,则动态系统的状态修改为:




    2.当训练RNN根据过去预测未来时,网络通常要将 作为过去序列信息的一个有损的representation

      • 这个representation一般是有损的,因为它使用一个固定长度的向量 来表达任意长的序列
      • 根据不同的训练准则,representation 可能会有选择地保留过去序列的某些部分。如 attention 机制。

      3.网络的初始状态 的设置有两种方式:

        • 固定为全零。这种方式比较简单实用。这种情况下,模型的反向梯度计算不需要考虑 ,因为 全零导致对应参数的梯度贡献也为 0 。

        • 使用上一个样本的最后一个状态,即: 。这种场景通常是样本之间存在连续的关系(如:样本分别代表一篇小说中的每个句子),并且样本之间没有发生混洗的情况。此时,后一个样本的初始状态和前一个样本的最后状态可以认为保持连续性。另外注意:模型更新过程中

        4.展开图的两个主要优点:

          • 无论输入序列的长度 如何,学得的模型始终具有相同的输入大小。因为模型在每个时间步上,其模型的输入 都是相同大小的。
          • 每个时间步上都使用相同的转移函数 f ,因此需要学得的参数 也就在每个时间步上共享。
          • 这些优点直接导致了:

            • 使得学习在所有时间步、所有序列长度上操作的单个函数 f 成为可能。
            • 允许单个函数 f 泛化到没有见过的序列长度。
            • 学习模型所需的训练样本远少于非参数共享的模型(如前馈神经网络)。

          1.2 网络模式

          1. 基于图展开和参数共享的思想,可以设计不同模式的循环神经网络。根据输入序列的长度,RNN 网络模式可以划分为:输入序列长度为0、输入序列长度为1 、输入序列长度为

          2. 设样本集合为 ,其中每个样本为:

            对应的网络输出为:

            设真实标记 为真实类别标签,网络的输出 为预测为各类别的概率分布(经过 softmax 归一化的概率)。则该样本的损失函数为:

            其中 为第 t 个时间步的损失函数。通常采用负的对数似然作为损失函数,则有:

            其中 K 为类别的数量, 的第 k 个分量, 为示性函数:

            如果将真实类别 标记扩充为概率分布 ,其中真实的类别 位置上其分量为 1,而其它位置上的分量为 0。则 就是真实分布 和预测分布 的交叉熵:

            数据集的经验损失函数为:

            .

          • 对于输入序列长度为1的样本,

          • 对于输入序列长度大于1的样本, ,其中 为第 i 个样本的序列长度。设样本对应的真实标记集合为 ,其中每个样本的标记为:

          • 对于输出序列长度为1的样本, 。对应的网络输出为:

          • 对于输出序列长度大于1的样本, ,其中 为第 i 个样本的序列长度。

          1.2.1 零长度输入序列

          1. 输入序列长度为0:此时网络没有外部输入,网络将当前时刻的输出作为下一个时刻的输入(需要提供一个初始的输出作为种子)。

            如文本生成算法:首先给定 作为种子,然后通过 t 时刻为止的单词序列来预测 t+1 时刻的单词;如果遇到某个输出为停止符,或者句子长度达到给定阈值则停止生成。

            在这个任务中,任何早期输出的单词都会对它后面的单词产生影响。



          2.在零长度输入序列的RNN 网络中,过去的输出序列 通过影响 来影响当前的输出 ,从而解耦

          3.该模型的数学表示为:

          其中 表示模型第 t 步输出 的第 k 个分量。

          单个样本的损失为:

          更新方程

          其中输出到隐状态的权重为 ,隐状态到输出的权重为 ,隐状态到隐状态的权重为 为输入偏置向量和输出偏置向量。

          1.2.2 单长度输入序列

          1. 输入序列长度为1 :模型包含单个 作为输入。此时有三种输入方式:输入 作为每个时间步的输入、输入 作为初始状态 、以及这两种方式的结合。

          2. 输入 作为每个时间步的输入:

            模型的数学表示:

            单个样本的损失:

            更新方程:

            其中输入到隐状态的权重为 ,输出到隐状态的权重为 ,隐状态到输出的权重为 ,隐状态到隐状态的权重为 为输入偏置向量和输出偏置向量。

            输入 作为初始状态

            模型的数学表示:

            单个样本的损失:

            更新方程:

          3. 在图注任务中,单个图像作为模型输入,模型生成描述图像的单词序列。图像就是输入 ,它为每个时间步提供了一个输入。通过图像和 t 时刻为止的单词序列来预测 t+1 时刻的单词。

            输出 有两个作用:用作 t+1 时刻的输入来预测 ;用于 t 时刻计算损失函数

          4. 当输入 作为初始状态 时,每个时间步也没有额外的输入。它与零输入RNN 网络的区别在于:

            零输入RNN 的初始输出 是需要给定的,而这里的初始状态 是给定的。

          1.2.3 多长度输入序列

          1. 多长度输入序列的RNN 包含了多输出&隐-隐连接RNN多输出&输出-隐连接RNN单输出&隐-隐连接RNN 等网络类型。

          2.多输出&隐-隐连接循环网络:每个时间步都有输出,并且隐单元之间有循环连接。

          其中输入到隐状态的权重为 ,隐状态到输出的权重为 ,隐状态到隐状态的权重为 为输入偏置向量和输出偏置向量。

            • 该网络将一个输入序列映射到相同长度的输出序列。

            • 模型的数学表示:

            • 单个样本的损失:

            • 更新方程:



            3.多输出&输出-隐连接循环网络:每个时间步都有输出,只有当前时刻的输出和下个时刻的隐单元之间有循环连接。


            其中输入到隐状态的权重为 ,隐状态到输出的权重为 ,输出到隐状态的权重为 为输入偏置向量和输出偏置向量。

              • 该网络将一个输入序列映射到相同长度的输出序列。

              • 模型的数学表示:

              • 单个样本的损失:

              • 更新方程:

              4.单输出&隐-隐连接 循环网络:隐单元之间存在循环连接,但是读取整个序列之后产生单个输出。


              其中输入到隐状态的权重为 ,隐状态到输出的权重为 ,隐状态到隐状态的权重为 为输入偏置向量和输出偏置向量。

              • 单输出&隐-隐连接RNN将一个输入序列映射到单个输出。

              • 模型的数学表示:

              • 单个样本的损失:

              • 更新方程:

              5.多输出&输出-隐连接 循环网络比较于多输出&隐-隐连接循环网络,该网络的达能力更小。

                • 多输出&隐-隐连接循环网络可以选择将其想要的关于过去的任何信息放入隐状态 中,并且通过 传播到未来。
                • 多输出&输出-隐连接循环网络中只有输出 会被传播信息到未来。通常 的维度远小于 ,并且缺乏过去的重要信息。

                6.多输出&输出-隐连接循环网络虽然表达能力不强,但是更容易训练:通过使用前一个时间步的真实标记 来代替输出 ,使得每个时间步可以与其他时间步分离训练,从而允许训练期间更多的并行化。

                1.3 输出序列长度

                1. 对于输入序列长度为零或者为1RNN模型,必须有某种办法来确定输出序列的长度。有三种方法来确定输出序列的长度:

                • 当输出是单词时,可以添加一个特殊的标记符。当输出遇到该标记符时,输出序列终止。此时需要改造训练集,对训练数据的每个输出序列末尾手工添加这个标记符。

                • 在模型中引入一个额外的二元输出单元,该输出单元用于指示:当前时间步是继续生成输出序列,还是停止生成。

                • 这种办法更普遍,适用于任何RNN

                • 该二元输出单元通常使用sigmoid单元,被训练为最大化正确地预测到每个序列结束的对数似然。

                • 在模型中引入一个额外的输出单元,该输出单元预测输出序列的长度 本身。

                • 这种方法需要在每个时间步的循环更新中增加一个额外输入,从而通知循环:是否已经到达输出序列的末尾。

                • 其原理是基于条件概率:

                二、训练算法

                2.1 BPTT 算法

                1. 多输出&隐-隐RNN为例,设:输入到隐状态的权重为 ,隐状态到输出的权重为 ,隐状态到隐状态的权重为 为输入偏置向量和输出偏置向量;激活函数为双曲正切激活函数

                  设网络从特定的初始状态 开始前向传播,从 的每个时间步,则有更新方程:

                  多输出&隐-隐RNN 的单个样本损失函数为: 。该损失函数的梯度计算代价较高:

                • 因为每个时间步只能一前一后的计算无法并行化,因此时间复杂度为
                • 前向传播中各个状态必须保存直到它们反向传播中被再次使用,因此空间复杂度也是
                • 采用 tanh 激活函数而不是 ReLU 激活函数的原因是为了缓解长期依赖。
              1. back-propagation through time:BPTT:通过时间反向传播算法,其算法复杂度为

                BPTT 计算得到梯度,再结合任何通用的、基于梯度的技术就可以训练 RNN

              2. 计算图的节点包括参数 ,以及以 t 为索引的节点序列 以及


              3. 根据 ,则有:

                令节点 ,则有: 。则有:

                其中 表示 的第 k 个分量。则有:
                表示梯度 的第 k 个分量, 为示性函数。写成向量形式为:
                其中 为真实标签 扩充得到的概率分布,其真实的类别 位置上的分量为 1,而其它位置上的分量为 0。 
                • 根据定义 ,得到:

                  根据导数: ,则有:
                  设隐向量长度为 n,定义:
                  则有: 。根据定义 ,即 ,则有: ,记作:
                  因此得到隐单元的梯度:
                • 时, 只有一个后续结点 (从而只有一个后继节点 ) ,因此有:
                • 时, 同时具有 两个后续节点,因此有:

                  由于 依赖于 ,因此求解隐单元的梯度时,从末尾开始反向计算。

                4.一旦获得了隐单元及输出单元的梯度,则可以获取参数节点的梯度。

                注意:由于参数在多个时间步共享,因此在参数节点的微分操作时必须谨慎对待。微分中的算子 在计算 对于 f 的贡献时,将计算图的所有边都考虑进去了。但是事实上:有一条边是 t 时间步的 ,还有一条边是 t+1 时间步的 。为了消除歧义,使用虚拟变量 作为 的副本。用 表示参数 在时间步 t 对于梯度的贡献。将所有时间步上的梯度相加,即可得到

                5.根据定义 。则有:

                • 考虑到 对于每个输出 都有贡献,因此有:

                • 记:

                  考虑到 对于每个输出 都有贡献,因此有:
                  其中 表示 的第 i 个分量。 

                6.根据定义 ,即:

                则有:
                • 考虑到 对于每个隐向量 都有贡献,因此有:

                  考虑到每个 都对 L 有贡献,则:
                  其中 表示 的第 i 个分量。 
                • 记:

                  考虑到每个 都对 L 有贡献,则:
                  其中 表示 的第 i 个分量。 $$ 

                7.因为任何参数都不是训练数据 的父节点,因此不需要计算


                2.2 Teacher forcing 算法

                1. 多输出&输出-隐连接RNN模型可以使用 teacher forcing 算法进行训练。

                • 模型的数学表示:
                • 单个样本的损失:
                • 训练时:在时刻 t+1 接受真实类别分布 作为输入,而不必等待 t 时刻的模型输出分布
                • 推断时:真实的标记通常是未知的,因此必须用模型的输出分布


              4. teacher forcing训练的本质原因是:当前隐状态与早期隐状态没有直接连接。虽然有间接连接,但是由于 已知,因此这种连接被切断。

                • 如果模型的隐状态依赖于早期时间步的隐状态,则需要采用 BPTT算法。
                • 某些模型训练时,需要同时使用teacher forcingBPTT算法。

                三、长期依赖

                3.1 长期依赖

                1. 长期依赖的问题是深度学习中的一个主要挑战,其产生的根本问题是:经过许多阶段传播之后,梯度趋向于消失或者爆炸。

                • 长期依赖的问题中,梯度消失占大部分情况,而梯度爆炸占少数情况。但是梯度爆炸一旦发生,就优化过程影响巨大。
                • RNN 涉及到许多相同函数的多次复合作用,每个时间步一次。这种复合作用可以导致极端的非线性行为。因此在RNN 中,长期依赖问题表现得尤为突出。
              5. 考虑一个没有非线性、没有偏置非常简单的循环结构: 。则有:

                可以正交分解时: 。其中 为正交矩阵, 为特征值组成的三角阵。则:

                • 前向传播:

                • 对于特征值的幅度不到 1 的特征值对应的 的部分将随着 t 衰减到 0 。

                • 对于特征值的幅度大于 1 的特征值对应的 的部分将随着 t 指数级增长。

                • 反向传播:

                • 对于特征值幅度不到1的梯度的部分将随着 t 衰减到 0 。

                • 对于特征值幅度大于1的梯度的部分将随着 t 指数级增长 。

              6. 若考虑非线性和偏置,即: ,有:

                • 前向传播:由于每一级的 的幅度被 函数限制在 (-1,1) 之间,因此前向传播并不会指数级增长。这也是为什么 RNN 使用 tanh 激活函数,而不使用 relu 的原因。

                • 反向传播:由于隐状态的幅度被 函数限制在 (-1,1) 之间,因此 进行了一定程度上的缩小。 越大,结果越小。

                • 如果 的特征值经过这样的缩小之后,在每个时刻都远小于1(因为每个时刻缩小的比例会变化),则该梯度部分将衰减到 0 。

                • 如果 的特征值经过这样的缩小之后,在每个时刻都远大于1,则该梯度部分将指数级增长。

                • 如果 的特征值经过这样的缩小之后,在不同的时刻有时候小于1有时候大于1(因为每个时刻缩小的比例会变化),则该梯度部分将比较平稳。

              7. 对于非循环神经网络,长期依赖的情况稍好。

                • 对于标量权重 w,假设每个时刻使用不同的权重 。假设 是独立同分布的随机变量,均值为 0、方差为 v ,则 的方差为
                • 非常深的前馈神经网络通过精心设计可以避免梯度消失和梯度爆炸问题。

                3.2 多时间尺度

                1. 缓解长期依赖的一个策略是:设计多个时间尺度的模型:在细粒度的时间尺度上处理近期信息、在粗粒度时间尺度上处理远期的信息。

                2. 得到粗粒度时间尺度的一种方法是跳跃连接:增加从远期的隐变量到当前隐变量的直接连接。

                • 普通的RNN中循环从时刻 t 隐变量连接到了时刻 t+1 隐变量,跳跃连接会增加一条从时刻 t 到时刻 t+d 隐变量的连接。注意:是增加而不是替代。

                • 引入了 d 延时的循环连接可以减轻梯度消失的问题。现在梯度指数降低的速度与 相关,而不是与 相关。这允许算法捕捉到更长时间的依赖性。但是这种做法无法缓解梯度指数级爆炸的问题。

              8. 得到粗粒度时间尺度的另一种方法是删除连接:主动删除时间跨度为 1 的连接,并用更长的连接替换。

                删除连接与跳跃连接的区别:

                • 删除连接不会增加计算图中的连接,而跳跃连接会增加计算图中的连接。
                • 删除连接强迫单元在长时间尺度上工作;而跳跃连接可以选择在长时间尺度上工作,也可以在短时间尺度上工作。

                3.3 渗漏单元

                1. 缓解梯度爆炸和梯度消失的一个方案是:尽可能的使得梯度接近1。这可以通过线性自连接单元来实现。

                  如:(其中 为隐单元, 为输入)

                  拥有类似行为的隐单元称作渗漏单元。

                • 接近1 时, 能记住过去很长一段时间的输入信息
                • 接近 0 时, 只能记住附近的一小段输入信息。
              9. 渗漏单元与跳跃连接的区别:

                • d 时间步的跳跃连接:可以确保隐单元总能够被 d 个时间步之前的输入值所影响。
                • 参数为 的渗漏单元:通过调整 值,可以更灵活的确保隐单元访问到过去不同时间步的输入值。
              10. 渗漏单元和跳跃连接的 参数有两种设置方式:

                • 手动设置为常数。如:初始化时从某些分布采样它们的值。
                • 让它们成为可训练的变量,从训练中学习出来。
              11. 可以使得不同的循环单元在不同时间尺度上工作:

                • 手动设置不同的循环单元具有不同的 参数。
                • 虽然不同的循环单元具有相同的 参数,但是在梯度下降的参数更新中,显式使得不同循环单元的参数采用不同的更新频率。

                3.4 梯度截断

                1. 对于长期依赖问题中的梯度爆炸,最常用的解决方案是梯度截断。

                  梯度截断有两种方案,设梯度

                  第二种方案可以确保截断后的梯度仍然是在正确的梯度方向上。但是实践表明:两种方式的效果相近。因为逐元素的梯度截断时,梯度更新的方向不仅不再是真实梯度方向,甚至也不是mini-batch的梯度方向。但是它仍然是一个使得目标值下降的方向。

                • 在更新参数之前,截断梯度的范数,其中 v 是梯度范数的上界:
                • 在更新参数之前,逐元素的截断参数梯度,其中 v 为 的上界:
              12. 当梯度大小超过了阈值时,即使采用简单的随机步骤,效果往往也非常好。即:随机采用大小为 v 的向量来作为梯度。因为这样通常会使得梯度离开数值不稳定的状态。

              13. 如果在mini-batch 梯度下降中应用了梯度范数截断,则真实梯度的方向不再等于所有mini-batch梯度的平均。

                对于一个mini-batch ,梯度范数截断不会改变它的梯度方向。对于许多个mini-batch,使用梯度范数截断之后,它们的平均值并不等同于真实梯度的范数截断。

                因此使用范数截断的mini-batch 梯度下降,引入了额外的梯度误差。这种误差有助于随机梯度下降算法逃离局部极小值。

              14. 3.5 引导信息流的正则化

                1. 梯度截断有助于解决梯度爆炸,但是无助于解决梯度消失。为解决梯度消失,有两种思路:

                • 让路径的梯度乘积接近1 ,如 LSTM 及其他门控机制。
                • 正则化或者约束参数,从而引导信息流。
              15. 正则化引导信息流:希望梯度向量 在反向传播时能维持其幅度。即:希望 尽可能一样大。

                考虑到

                Pascanu et al. 给出了以下正则项:

                • 计算这个正则项可能比较困难。Pascanu et al.提出:可以将反向传播梯度 考虑作为恒值来近似。
                • 实验表明:如果与梯度截断相结合,该正则项可以显著增加 RNN可以学习的依赖跨度。
                • 该方法的一个主要缺点是:在处理数据冗余的任务时,如语言模型,它并不像 LSTM一样有效 。


                 

                 Logic 

                OR

                http://www.huaxiaozhuan.com/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/chapters/6_RNN.html






                
                
                    
                
                往期 精彩回顾





                Python社区是高质量的Python/Django开发社区
                本文地址:http://www.python88.com/topic/134448
                 
                643 次点击