循环神经网络(RNN)相关知识 rnn递归神经网络

   2023-02-10 学习力766
核心提示:文章目录RNN概述前向传播公式通过时间反向传播(BPTT)RNN确定序列长度方式其他RNN结构基于RNN的应用1,序列数据的分析2,序列数据的转换3,序列数据的生成RNN的不足1,从隐藏变量h角度来看2,从梯度传播角度来看RNN概述循环神经网络(RNN)是用于处理序列数据

RNN概述

循环神经网络(RNN)是用于处理序列数据的神经网络,该序列在时刻 t(从1 到 τ)包含向量 x(t)x^{(t) }。典型的网络结构如下图所示:

循环神经网络(RNN)相关知识

RNN每个时间步都需要将 x 值的输入序列映射到输出值 o 的对应序列。其中 o 是未归一化的对数概率,并且在损失函数 L 内部计算 y^=softmax(x)\hat y = softmax(x)。损失函数 L 用于衡量每个 o 与相应的训练目标 y 的距离。

RNN输入到隐含单元的连接由权重矩阵 U 参数化,隐含单元与隐含单元连接由权重矩阵 W 参数化,隐含单元到输出节点的连接由权重矩阵 V 参数化。从上面的图中也可以看出,与CNN类似,在RNN中同样有参数共享的思想(共享了参数WUVW,U,V等)。这使得模型的泛化能力更强,因为模型不会依赖于特定位置上的输入xx。例如考虑这两句话:“I went to Nepal in 2009’’ 和 “In 2009, I went to Nepal.” ,他们表达的意思完全相同,但是时间2009出现在不同的地方,RNN的参数共享机制可以更有效的提取到这个时间信息。参数共享也允许模型泛化到没有见过的序列长度,并且训练模型所需的训练样本远远少于不带参数共享的模型。

当训练循环网络根据过去的信息去预测未来的信息时,网络通常要使用隐含状态 h (t) 来表示时刻 t 之前的序列信息:
h(t)=g(t)(x(t),x(t1),x(t2),,x(2),x(1))=f(h(t1),x(t);θ). \begin{aligned} h^{(t)} &=g^{(t)}(x^{(t)},x^{(t-1)},x^{(t-2)},\dots,x^{(2)}, x^{(1)}) \\ & = f(h^{(t-1)}, x^{(t)} ; \theta) . \end{aligned}
函数g(t)g^{(t)}将过去的序列(x(t),x(t1),x(t2),,x(2),x(1))(x^{(t)},x^{(t-1)}, x^{(t-2)},\dots,x^{(2)}, x^{(1)})作为输入来生成当前的隐含状态h(t)h(t)。实际上,我们可以递归调用函数ff来完成隐含状态的计算。这么做主要有两个优点:

  1. 无论序列的长度如何,模型始终具有相同的输入数据。因为它只关注给定输x(t)x^{(t)}后,从一种状态h(t1)h(t-1)到另一种状态h(t)h(t)的转移, 而不是在可变长度的历史输入数据x(t1),x(t2),,x(2),x(1)x^{(t-1)},x^{(t-2)},\dots,x^{(2)}, x^{(1)}上的操作。
  2. 我们可以在每个时间步(tt时刻)使用相同参数的状态转移函数ff

在不同的NLP场景中,h(t) 需要保存的信息也不同。例如在词性标注任务中,h(t) 更多的是要保存前一个单词的信息;而在机器翻译任务中,则需要保存输入序列的所有信息。

前向传播公式

上面的图中没有指明**函数,假设使用tanhtanh作为**函数,并且假设输出值是离散的,例如用于预测类别。一种表示离散变量的方式是:把输出 o 作为离散变量每种可能值的非标准化对数概率。然后,我们可以应用 softmax 函数获得标准化后概率的输出向量y^\hat y

RNN从特定的初始状态 h (0) 开始前向传播。从 t = 1 到 t = τ 的每个时间步,我们应用以下更新方程:
a(t)=b+Wh(t1)+Ux(t)h(t)=tanh(a(t))o(t)=c+Vh(t) \begin{aligned} &\mathbf a^{(t)} = \mathbf b + \mathbf W \mathbf h^{(t-1)} + \mathbf U \mathbf x^{(t)} \\ &\mathbf h^{(t)} = \tanh(\mathbf a^{(t)}) \\ &\mathbf o^{(t)} = \mathbf c + \mathbf V \mathbf h^{(t)} \\ \end{aligned}

y^(t)=softmax(o(t))=eo(t)t=1τeo(t) \hat {\mathbf y} ^{(t)} = softmax(\mathbf o^{(t)}) = \frac{e^{o^{(t)}}}{\sum_{t=1}^\tau e^{o^{(t)}}} \\

其中的参数的偏置向量 b 和 c 连同权重矩阵 U、V 和 W,分别对应于输入到隐藏单元、
隐藏单元到输出和隐藏单元到隐藏单元的连接。这个循环网络将一个输入序列映射到相同长度的输出序列。与 x 序列配对的 y 的总损失就是所有时间步的损失之和,例如定义损失L为所有时间步的负对数似然函数:
L({x(1),,x(τ)},{y(1),,y(τ)})=tL(t)=tlogPmodel(y(t){x(1),,x(τ)}) \begin{aligned} &L(\{x^{(1)},\ldots,x^{(\tau)}\},\{y^{(1)},\ldots,y^{(\tau)}\}) \\ &= \sum_{t} L^{(t)} \\ &= -\sum_{t} \log P_{model}(y^{(t)}|\{x^{(1)},\ldots,x^{(\tau)}\}) \end{aligned}
了解正向传播的计算内容之后,就可以讨论通过时间反向传播算法来更新网络参数了。

通过时间反向传播(BPTT)

回顾之前的计算图:

循环神经网络(RNN)相关知识

对于每一个节点 N,我们需要先 N 后面的节点的梯度,然后递归地计算梯度 NL∇ _N L。我们从最后一个节点开始递归:
LL(t)=1 \frac{\partial L}{\partial L^{(t)}} = 1
观察正向传播的计算公式,不难发现 L(t)L^{(t)}是关于y^(t)\hat {\mathbf y} ^{(t)}的函数,y^(t)\hat {\mathbf y} ^{(t)}softmaxsoftmax的结果, 而softmaxsoftmax是关于 o(t)o^{(t)}的函数。求LL对非标准化对数概率 o(t)o^{(t)}求偏导(相关求导过程可以参考Softmax求导),得到:
(o(t)L)i=Loi(t)=LL(t)L(t)y^i(t)y^i(t)oi(t)={y^i(t)1,yi(t)=labely^i(t)0,yi(t)label \begin{aligned} (\nabla_{\mathbf o^{(t)}} L)_i &= \frac{\partial L}{\partial o_{i}^{(t)}}\\ &= \frac{\partial L}{\partial L^{(t)}} \frac{\partial L^{(t)}}{\partial \hat {\mathbf y} ^{(t)}_i} \frac{\partial \hat {\mathbf y} ^{(t)}_i}{\partial o_{i}^{(t)}} \\ &= \begin{cases} \hat {y}_i ^{(t)} - 1 , \qquad {y}_i ^{(t)} =label\\ \hat {y}_i ^{(t)} - 0, \qquad {y}_i ^{(t)} \ne label \end{cases} \end{aligned}
从序列的末尾开始,反向进行计算。在最后的时间步 τ,只有 o (τ) 依赖于h (τ) ,不存在h (τ+1)依赖于h (τ) ,因此这个梯度很简单。由o(t)=c+Vh(t)\mathbf o^{(t)} = \mathbf c + \mathbf V \mathbf h^{(t)},可以知道:
h(τ)L=o(τ)h(τ)o(τ)L=VTo(τ)L \nabla_{\mathbf h^{(\tau)}}L = \frac{\partial o^{(\tau)}}{\partial h^{(\tau)}}\nabla_{\mathbf o^{(\tau)}} L = \mathbf V^T \nabla_{\mathbf o^{(\tau)}} L
然后我们可以从时刻 t = τ − 1 到 t = 1 反向迭代,通过时间反向传播梯度。由下面的式子:
a(t)=b+Wh(t1)+Ux(t)h(t)=tanh(a(t))o(t)=c+Vh(t) \mathbf a^{(t)} = \mathbf b + \mathbf W \mathbf h^{(t-1)} + \mathbf U \mathbf x^{(t)} \\ \mathbf h^{(t)} = \tanh(\mathbf a^{(t)}) \\ \mathbf o^{(t)} = \mathbf c + \mathbf V \mathbf h^{(t)}
不难发现当t < τ时, o (t) 和 h (t+1) 都依赖于h (t) 。因此,它的梯度由两个部分组成:
h(t)L=(h(t+1)h(t))(h(t+1)L)+(o(t)h(t))(o(t)L)=W(h(t+1)L)diag(1(h(t+1))2)+V(o(t)L) \begin{array}{l} \nabla_{h^{(t)}} L=\left(\frac{\partial \boldsymbol{h}^{(t+1)}}{\partial \boldsymbol{h}^{(t)}}\right)^{\top}\left(\nabla_{\boldsymbol{h}^{(t+1)}} L\right)+\left(\frac{\partial \boldsymbol{o}^{(t)}}{\partial \boldsymbol{h}^{(t)}}\right)^{\top}\left(\nabla_{\boldsymbol{o}^{(t)}} L\right) \\ =\boldsymbol{W}^{\top}\left(\nabla_{\boldsymbol{h}^{(t+1)}} L\right) \operatorname{diag}\left(1-\left(\boldsymbol{h}^{(t+1)}\right)^{2}\right)+\boldsymbol{V}^{\top}\left(\nabla_{\boldsymbol{o}^{(t)}} L\right) \end{array}
其中:
tanh(x)=1(tanh(x))2 \tanh'(x) = 1- (tanh(x))^2

h(t+1)h(t)=tanh(b+Wh(t)+Ux(t+1))h(t)=WTdiag(1(h(t+1))2) \begin{aligned} \frac{\partial \boldsymbol{h}^{(t+1)}}{\partial\boldsymbol{h}^{(t)}} &= \frac{\partial \tanh(\mathbf b + \mathbf W \boldsymbol h^{(t)} + \mathbf U \mathbf x^{(t+1)} )}{\partial\boldsymbol{h}^{(t)}} \\ &= \mathbf W^T diag(1-(\boldsymbol h^{(t+1)})^2) \end{aligned}

基于前面的步骤,接下来进行参数的跟新:
cL=t(o(t)c)o(t)L=to(t)LbL=t(h(t)b(t))h(t)L=tdiag(1(h(t))2)h(t)LVL=ti(Loi(t))Voi(t)=t(o(t)L)h(t)W=ti(Lhi(t))W(t)hi(t)=tdiag(1(h(t))2)(h(t)L)h(t1)UL=ti(Lhi(t))U(t)hi(t)=tdiag(1(h(t))2)(h(t)L)x(t) \begin{aligned} \nabla_{c} L &=\sum_{t}\left(\frac{\partial \boldsymbol{o}^{(t)}}{\partial \boldsymbol{c}}\right)^{\top} \nabla_{\boldsymbol{o}^{(t)}} L=\sum_{t} \nabla_{\boldsymbol{o}^{(t)}} L \\ \nabla_{\boldsymbol{b}} L &=\sum_{t}\left(\frac{\partial \boldsymbol{h}^{(t)}}{\partial \boldsymbol{b}^{(t)}}\right)^{\top} \nabla_{\boldsymbol{h}^{(t)}} L=\sum_{t} \operatorname{diag}\left(1-\left(\boldsymbol{h}^{(t)}\right)^{2}\right) \nabla_{\boldsymbol{h}^{(t)}} L \\ \nabla_{\boldsymbol{V}} L &=\sum_{t} \sum_{i}\left(\frac{\partial L}{\partial o_{i}^{(t)}}\right) \nabla_{\boldsymbol{V}} o_{i}^{(t)}=\sum_{t}\left(\nabla_{o^{(t)}} L\right) \boldsymbol{h}^{(t)^{\top}} \\ \nabla_{\boldsymbol{W}} &=\sum_{t} \sum_{i}\left(\frac{\partial L}{\partial h_{i}^{(t)}}\right) \nabla_{\boldsymbol{W}^{(t)}} h_{i}^{(t)} \\ &=\sum_{t} \operatorname{diag}\left(1-\left(\boldsymbol{h}^{(t)}\right)^{2}\right)\left(\nabla_{\boldsymbol{h}^{(t)}} L\right) \boldsymbol{h}^{(t-1)^{\top}} \\ \nabla_{U} L &=\sum_{t} \sum_{i}\left(\frac{\partial L}{\partial h_{i}^{(t)}}\right) \nabla_{\boldsymbol{U}^{(t)}} h_{i}^{(t)} \\ &=\sum_{t} \operatorname{diag}\left(1-\left(\boldsymbol{h}^{(t)}\right)^{2}\right)\left(\nabla_{\boldsymbol{h}^{(t)}} L\right) \boldsymbol{x}^{(t)^{\top}} \end{aligned}

RNN确定序列长度方式

第一种是添加一个表示序列末端的特殊符号。在训练集中,我们将该符号作为序列的一个额外成员,即紧跟每个训练样本 x (τ) 之后。

第二种选择是在模型中引入一个额外的Bernoulli输出,表示在每个时间步决定继续或停止。相比向词汇表增加一个额外符号,这种方法更普遍,因为它适用于任何RNN。在这种方法中,sigmoid被训练为最大化正确预测的对数似然,即在每个时间步序列决定结束或继续。

第三种是将一个额外的输出添加到模型并预测整数 τ 本身。模型可以预测 τ 的值,然后使用 τ 步有价值的数据。这种方法需要在每个时间步的循环更新中增加一个额外输入,使得循环更新知道它是否是靠近所产生序列的末尾。

其他RNN结构

除了上面介绍的RNN结构,还有一些其他结构:

1, 每个时间步都产生一个输出,但是只有当前时刻的输出 o 与下个时刻的隐藏单元之间有连接的RNN:

循环神经网络(RNN)相关知识

这样的RNN没有最开始介绍的 RNN 那样强大,上图中的RNN被训练为将特定输出值放入 o 中,并且 o 是允许传播到未来的唯一信息。此处没有从 h 前向传播的直接连接。之前的 h 仅通过产生的预测间接地连接到当前。o 通常缺乏过去的重要信息,除非它非常高维且内容丰富。这使得该图中的RNN不那么强大,但是它更容易训练,因为每个时间步可以与其他时间步分离训练,允许训练期间更多的并行化。

2, 隐藏单元之间存在循环连接,但读取整个序列后只在最后一个时间步产生单个输出的RNN:

循环神经网络(RNN)相关知识

这样的网络可以用于概括序列,并产生一个向量 o 用于表示整个输入序列,然后可以对 o 进行进一步的处理。例如在翻译任务中,先输入原始输入的句子,得到句子的向量表示 o ,然后对 o 展开进一步的翻译任务。

3,包含上下文的RNN:

循环神经网络(RNN)相关知识

此RNN包含从前一个输出到当前状态的连接。这些连接允许RNN在给定 x 的序列后,对相同长度的 y 序列上的任意分布建模。

4,双向RNN

在许多应用中,我们要输出的 y (t) 的预测可能依赖于整个输入序列。例如,在语音识别中,当前声音作为音素的正确解释可能取决于未来几个音素,甚至可能取决于未来的几个词,因为词与附近的词之间的存在语义依赖。双向RNN结构如下:

循环神经网络(RNN)相关知识

隐藏状态变量 h 在时间上向前传播信息(向右),而隐藏状态变量 g 在时间上向后传播信息(向左)。因此在每个点 t,输出单元 o (t) 可以受益于输入 h (t) 中关于过去的相关信息以及输入 g (t) 中关于未来的相关信息。

5,编码—解码结构(序列到序列)的RNN

编码—解码结构的RNN支持将输入序列映射到不一定等长的输出序列,结构如下图所示:

循环神经网络(RNN)相关知识

这在许多场景中都有应用,如语音识别、机器翻译或问答,其中训练集的输入和输出序列的长度通常不相同。它由读取输入序列的编码器RNN以及生成输出序列的解码器RNN组成。编码器RNN的最终隐藏状态用于计算一般为固定大小的上下文向量 C,C 表示输入序列的语义概要信息并且作为解码器RNN的输入。

基于RNN的应用

RNN通常用于处理序列形式的输入数据,如文本,语音等。输出也可以是序列或者某个预测值。常见的应用如下:

1,序列数据的分析

例如情感分析,输入一句话的每个字的向量表示,输出其情感的预测标签。网络结构如下:

循环神经网络(RNN)相关知识

2,序列数据的转换

例如机器翻译,输入是某种语言的字序列,输出是翻译后的字序列。网络结构如下:

循环神经网络(RNN)相关知识

再如,词性标注,输入是字的向量表示,输出是每个字对应的词性标注信息,常见网络结构如下:

循环神经网络(RNN)相关知识

3,序列数据的生成

例如,图片描述生成,输入是一张图片的向量表示,输出图片的描述信息。网络结构如下:

循环神经网络(RNN)相关知识

RNN的不足

RNN很难解决长依赖问题,即经过许多个时间步的传播之后,梯度值倾向于0或者无穷大,这样的现象称之为梯度消失和梯度爆炸。

1,从隐藏变量h角度来看

为了简化说明,我们认为:
h(t)=WTh(t1) \boldsymbol h^{(t)} = \boldsymbol W^T \boldsymbol h^{(t-1)}
根据递推关系,可以转换为:
h(t)=(Wt)Th(0) \boldsymbol h^{(t)} = (\boldsymbol W^t)^T \boldsymbol h^{(0)}
W\boldsymbol W 符合下列形式的特征分解:
W=QΣQT \boldsymbol W = \boldsymbol Q \boldsymbol \Sigma \boldsymbol Q^T
其中Q\boldsymbol Q是正交矩阵。于是有:
h(t)=QTΣtQh(0) \boldsymbol h^{(t)} = \boldsymbol Q^T \boldsymbol \Sigma^t \boldsymbol Q \boldsymbol h^{(0)}
经过多个阶段的传播后,如果$ \boldsymbol \Sigma^t11中的特征值小于1,特征值将衰减到零。如果特征值大于1,经过t次相乘后,特征值将激增。任何不与最大特征向量对齐的\boldsymbol h^{(0)}$的部分将最终被丢弃,无法做到长期依赖。

2,从梯度传播角度来看

梯度的反向传播过程如下图所示:

循环神经网络(RNN)相关知识

不难得到:
Jy0=Jh3h3h2h2h1h1y0 \frac{\partial J}{\partial y_0} = \frac{\partial J}{\partial h_3}\frac{\partial h_3}{\partial h_2} \frac{\partial h_2}{\partial h_1} \frac{\partial h_1}{\partial y_0}
上面的式子是多个偏导数的累乘,如果每个偏导数的值都小于1,那么传播到 t=0t=0 时刻的梯度几乎等于0了,也就是梯度消失了。梯度消失意味着只有靠近输出的几层才真正起到学习的作用,无法通过加深网络层数来提升预测效果,这样RNN很难学习到输入序列中的长距离依赖关系。

反之,如果每个偏导数的值都大于1,那么传播到 t=0t=0 时刻的梯度被指数倍放大,也就是梯度爆炸了。可以通过梯度裁剪来缓解,即当梯度的范式大于某个给定值的时候,对梯度进行等比缩放。

为了能学习到更长的依赖关系,需要对RNN网络加以改进,下一篇文章提到的LSTM模型可以一定程度上得到改善。

参考文章:

《深度学习》

RNN详解

 
反对 0举报 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • 【深度学习】循环神经网络教程 循环神经网络 知乎
    【深度学习】循环神经网络教程 循环神经网络 知
    这是在公司做培训时制作的PPT,教程对循环神经网络以及其应用进行了简单地介绍,主要分为以下六个部分:Why do we need Recurrent Neural Networks?Vanilla Recurrent Neural NetworkBackpropagation Through Time (BPTT)Gradient exploding/vanishing proble
    03-08
  • 深度学习 - 循环神经网络RNN
    深度学习 - 循环神经网络RNN
    当数据是有顺序的时候,我们就可以使用RNN了,比如说话的顺序 有序列化的数据等的。   在介绍RNN之前,我有篇博客是介绍了CNN,简单提一下,在一张大的图片是上,我们有一个fliter滤波器,通过共用参数来扫描这张图片,提取出一张精髓的图片,再在这这张图片
    03-08
  • 拓端tecdat|R语言深度学习Keras循环神经网络(RNN)模型预测多输出变量时间序列
    拓端tecdat|R语言深度学习Keras循环神经网络(RN
    原文链接:http://tecdat.cn/?p=23902原文出处:拓端数据部落公众号递归神经网络被用来分析序列数据。它在隐藏单元之间建立递归连接,并在学习序列后预测输出。在本教程中,我们将简要地学习如何用R中的Keras RNN模型来拟合和预测多输出的序列数据,你也可以
    03-08
  • 【吴恩达deeplearning.ai】深度学习(9):循环神经网络
    【吴恩达deeplearning.ai】深度学习(9):循环神
    随深度学习技术的发展,使用循环神经网络(Recurrent Neural Network,RNN)建立的各种序列模型,使语音识别、机器翻译及自然语言理解等应用成为可能。表示与类型自然语言、音频等数据都是前后相互关联的数据,比如理解一句话要通过一整句而不是其中的几个词
    02-10
  • 学习记忆循环神经网络心得
    学习记忆循环神经网络心得
          如有缪误欢迎指正  GRU结构向前传播 心得(欢迎指正)当遗忘门等于0的时候当前信息抛弃 之前记忆前传当遗忘门等于1 的时候之前记忆抛弃 当前信息前传当遗忘门的值为0和1之间的时候 调控前传的记忆与信息的比例 QAQQ:LSTM与GRU 的区别A: LSTM
    02-10
  • 协同过滤结合循环神经网络的推荐系统——期末作业
    协同过滤结合循环神经网络的推荐系统——期末作
    Recommendation System using Collaborative Filtering and Recurrent Neural Networkauthor:Fu-ze ZhongEmail: [email protected]School of Data and Computer Science, Sun Yat-sen University, Guangzhou, China.abstractThe behavior of user in an e-c
    02-10
  • 第六讲 循环神经网络--LSTM--stock
    1 !pip install tushare2 import tushare as ts3 import numpy as np4 import tensorflow as tf5 from tensorflow.keras.layers import Dropout, Dense, LSTM6 import matplotlib.pyplot as plt7 import os8 import pandas as pd9 from sklearn.preprocessing
    02-10
  • 循环神经网络RNN 循环神经网络RNN可以处理哪些情况
    循环神经网络RNN 循环神经网络RNN可以处理哪些
    前言我们在思考和判断问题的时候,并不是总是以一个空白的状态进行思考的。我们的思考都是基于我们以前的知识或者经验,比如我们读到这篇博客的时候,考虑到这些词语或者语句表达的是什么意思,都是基于我们以前所学到的知识。也就是说我们的思想具有持续性。
    02-10
  • 循环神经网络系列(二)Tensorflow中dynamic_rnn
    循环神经网络系列(二)Tensorflow中dynamic_rn
    1.回顾上一篇博文(循环神经网络系列(一)Tensorflow中BasicRNNCell)中我们介绍了在Tensoflow中,每个RNN单元的实现,以及对应各个参数的含义。自那之后,我们就能通过Tensorflow实现一个单元的计算了。import tensorflow as tfimport numpy as npx = np.array
    02-09
  • 双向循环神经网络和深层循环神经网络 (吴恩达老师_学习笔记)
    双向循环神经网络和深层循环神经网络 (吴恩达
    目录双向循环神经网络(Bidirectional RNN)深层循环神经网络(Deep RNNs)双向循环神经网络(Bidirectional RNN)双向RNN模型(BRNN),可以在序列的某点处不但获取之前的信息,同时还可以获取这个序列点之后的信息,说的炫酷点就是get information from the
    02-09
点击排行