RNN基本结构解读


在计算机视觉领域,最常用的网络结构就是CNN卷积神经网络。但是在现实中我们存在很多序列型数据,比如某一天的温度记录,一段时间内某支股票的变化情况,文本序列,乃至视频流,我们都可以认为其实序列型数据,它们在时间上存在先后关系。处理这些序列数据最常用、最传统的深度学习模型就是 循环神经网络RNN(Recurrent Neural Network)。自然语言处理所要面对的主要是这种文本序列。本文将详细介绍RNN的基本机构。

1. RNN的多种结构

与CNN不同的是,RNN具有多种网络结构。联系实际很容易想到,在不同的时间段内,序列数据的长短总是不一致的。就像我们说话,每一句的长度都是不确定的。由此我们得出了以上五种基本结构。

1.1 单层网络结构

最基本的单层网络结构,输入是 x x x,经过变换 W ⋅ x + b W·x + b Wx+b和激活函数 f f f得到输出 y y y

img
1.2 经典RNN网络结构

序列型的数据不太好用原始的神经网络处理。为了处理序列建模问题,RNN引入了隐藏态 h h h(hidden state)的概念。 h h h可以对序列型的数据提取特征,接着再转换为输出。

img

如上图,我们从 h 1 h_1 h1开始逐步推到其计算过程。首选阐述图中网络结构的基本含义:

  • 圆圈或方块表示向量
  • 一个箭头表示对该向量做一次变换

如图所示, h 0 h_0 h0 x 1 x_1 x1分别有一个箭头连接 h 1 h_1 h1,表示对 h 0 h_0 h0 x 1 x_1 x1分别作了一次变化。图中的 U U U W W W是参数矩阵, b b b是偏置项参数, f f f是激活函数。在经典的RNN网络结构中,通常使用 t a n h tanh tanh作为激活函数。有了 h 1 h_1 h1的计算,我们很容易可以推出之后的计算流程,每一步的过程与第一步基本一致。

img

这里需要特别强调的是:🙄🙄🙄***在计算时每一步使用的参数 U U U W W W b b b都是一样的,即每一个步骤的参数都是共享的,这是RNN的重要特性。***🙄🙄🙄

根据上面的计算法则,我们把对应的四个 x x x输入全部计算,得到下图:

img

这里我们只给了四个输入,其实它是可以一直无限循环下去的。此时我们并未得到真正的输出,我们得到的是一些列的隐藏层 h i h_i hi。要得到真正的输出 y y y,我们还需要一下的计算:

img

这里使用了🙄🙄🙄***新的参数*** V V V c c c。🙄🙄🙄

一般我们在处理多分类问题时,都会使用 s o f t m a x softmax softmax函数将输出转换为各个类别的概率。我们在前文说过,一个箭头表示一次转换操作,这里 h 1 h_1 h1经过 S o f t m a x ( V ⋅ h 1 + c ) Softmax(V·h_1 + c) Softmax(Vh1+c)得到 y 1 y_1 y1。同样地,我们通过相同的转换将剩下的隐藏层 h h h转换为对应的输出,如下图:

img

这就是经典的RNN网络结构,怎么样是不是很简单,如果不简单的话一定是我没有写好,不是网络结构的问题,是我表达的问题🙄🙄🙄。

从我们最后得到的结果我们可以看出,输入序列是 X i X_i Xi,经过RNN循环神经网络的计算得到输出序列 Y i Y_i Yi。你一定发现了一个问题,这里我们的输入序列 X i X_i Xi和输出序列 Y i Y_i Yi是等长的,也就是我们文章开头给出的五种RNN网络结构中的第五种。

1.3 其它RNN结构

如何将等长序列转化成其他类似one to many或者many to one呢?回顾一下我们是怎么将隐藏态 h i h_i hi转化成输出 y i y_i yi的,我们对每一个隐藏态 h i h_i hi进行了 S o f t m a x Softmax Softmax操作。对应的,当我们只想获得一个输出时怎么办,我们

仅需对最后一个隐藏态 h n h_n hn进行 S o f t m a x Softmax Softmax操作即可,如下图:

img

这样我们就得到了many to one结构。是不是很简单,这是我们更有理由相信**"Less is more, simple is all."这时候肯定有人会问,那我们的one to many怎么实现呢?毕竟我们没有办法像得到 Y Y Y那样,仅对最后的隐藏态 h n h_n hn进行 S o f t m a x Softmax Softmax操作。基本的one to many**结构如下:

img

我们只有一个输入 X X X,我们是不是说过**“Less is more, simple is all.”**根据这句话你想想你应该怎么办?对,就是把输入 X X X复制 n n n次,在每一个隐藏态 h i h_i hi所对应的输入位置都填入相同的输入 X X X。变成下图所示的结构:

img

我们简化一下上图的结构,将输入 X X X分别对应到隐藏态 h i h_i hi

对于这种one to many的网络结构,一般应用于:

  • 从图像生成文字(image caption),此时输入的X就是图像的特征,而输出的y序列就是一段句子,就像看图说话等
  • 从类别生成语音或音乐等

2. Encoder-Decoder

2.1 Encoder-Decoder的基本结构

细心的小伙伴一定发现了,不对啊,差一种啊,对于那种输入和输出都是多个值,但是不相等的形式你没有说啊。没错,这个结构比较特殊,所以我们单独拿出来说一下。对于这种输入输出不等长的形式,我们暂且称其为n to m。其实他就是我们标题所写的Encoder-Decoder,也称为Seq2Seq

Seq2Seq是RNN的一个变种形式,其出现源自具体的现实需求,正如我们所说,在大多数时候,文本序列的输入和输出是不等长的,例如翻译过程中:"I hava a pen, I hava an apple, en… apple pen."翻译成中文是:“我有一支笔,我有一个苹果,嗯。。。苹果笔”。🙄🙄🙄这里英文和中文的长度明显就是不一样的,而且大多数情况下,目标语言和源语言之间的长度都是不一致的。为此,Encoder-Decoder结构先将输入数据编码成一个上下文语义向量c:

img

语义向量c可以有多种表达方式,最简单的方法就是把Encoder的最后一个隐状态赋值给c,还可以对最后的隐状态做一个变换得到c,也可以对所有的隐状态做变换。

拿到c之后,就用另一个RNN网络对其进行解码,这部分RNN网络被称为Decoder。Decoder的RNN可以与Encoder的一样,也可以不一样。具体做法就是将c当做之前的初始状态h0输入到Decoder中:

img

如果只看上图语义向量c及其右边的部分,你是不是很眼熟,想想我们上面将的one to many结构,我想你一定知道该怎么做了。对,我们还有另一种结构,将c当做每一步的输入:

img
2.2 Encoder-Decoder应用范围:

于这种Encoder-Decoder结构不限制输入和输出的序列长度,因此应用的范围非常广泛,比如:

  • 机器翻译:Encoder-Decoder的最经典应用,事实上这结构就是在机器翻译领域最先提出的。
  • 文本摘要:输入是一段文本序列,输出是这段文本序列的摘要序列。
  • 阅读理解:将输入的文章和问题分别编码,再对其进行解码得到问题的答案。
  • 语音识别:输入是语音信号序列,输出是文字序列。
2.3 Encoder-Decoder 缺点
  • 最大的局限性:编码和解码之间的唯一联系是固定长度的语义向量c
  • 编码要把整个序列的信息压缩进一个固定长度的语义向量c
  • 语义向量c无法完全表达整个序列的信息
  • 先输入的内容携带的信息,会被后输入的信息稀释掉,或者被覆盖掉
  • 输入序列越长,这样的现象越严重,这样使得在Decoder解码时一开始就没有获得足够的输入序列信息,解码效果会打折扣

3. LSTM

终于到了本片文章最重要的部分了——LSTM。听到终于到了你是不是很崩溃,前面写了那么多,居然不是最重要的,主角没出场就罗里吧嗦的写了这么多了,脑子是不是秀逗了。其实我们前面写了那么多,但是基本都是浅尝辄止,并未深入其数学原理与计算过程,之所以主角是LSTM,在实际应用中你会发现,由于经典RNN存在"记忆力"的问题,大多数情况下,我们都需要使用LSTM作为网络的基本机构 。LSTM通过"记忆门"和"遗忘门"克服了经典RNN"记忆力"不足的缺点,更适合处理序列型数据。

3.1 LSTM基本结构

从外部结构看,LSTM和RNN的输入输出是一模一样的,同样是在每一步接受外部输入和前一阶段的隐藏态,并输出一个值。因此,RNN中可以使用的每一结构都可以无无缝切换到LSTM,而不会产生任何问题。

回顾RNN的公式:$ h_t = f(U·x_t + W·h_{t-1} + b) $。从式子我们可以看出,RNN每一层的隐藏态都由前一层的隐藏态经过变换和激活函数得到,反向传播求导时,最终得到的导数会包含每一步梯度的连乘,这会引起梯度爆炸梯度消失,所以RNN很难处理"长程依赖"问题,也就是我们所说的"记忆力"不足的问题,即无法学到序列中蕴含的间隔距离较长的规律。LSTM在隐藏态计算时,使用加法替换了这里的迭代变换,可以避免梯度消失的问题,能够学到长程的规律。

img

从上图我们可以看到: h t − 1 h_{t-1} ht1 x t x_t xt合到一起,经过激活函数 t a n h tanh tanh得到了 h t h_t ht h t h_t ht还会被传到下一步的RNN单元中。这样就对应了我们所讲的RNN公式:$ h_t = f(U·x_t + W·h_{t-1} + b) , 激 活 函 数 使 用 了 图 中 的 ,激活函数使用了图中的 使tanh$。

如果我们把上图中所示的网络机构进一步细化,就会得到下图,更加具体的显示了神经元内部的计算流程:

A LSTM neural network.

这里我们明确一下图中个符号的具体含义:

img
  • 黄色方框(Neural Network Layer)代表网络层
  • 粉色圆圈(Pointwise Operation)表示各点的具体计算操作,具体指两个形状完全相同的矩阵进行相加、相乘或其他运算。
  • 单箭头表示向量转换
  • 归一箭头表示合并
  • 拆分箭头表示复制

与经典RNN结构不同的是,LSTM的隐藏层有两部分组成,分别是 h t h_t ht C t C_t Ct

C t C_t Ct是在各个步骤中传到的主要信息,下图中的水平线可以看做是信息传递的"主干道",通过加法 C t C_t Ct可以在主干道上进行传递,因此较远的梯度也可以在长程上传播,这是LSTM的主要思想。

img

这里的 C t C_t Ct是一个向量,其长度是我们自行设定的,如果我们选择256,就表示我们想要用256位来保存记忆信息,这个维度越大,相当于记忆的容量越大,可保存的信息自然越多,但是需要训练的参数也会越多。

我们看到,从 C t − 1 C_{t-1} Ct1 C t C_t Ct经过了两次运算,一次乘法,和一次加法。第一步是忘记一些不再有用的记忆,第二步是把$ x_t $中有用的信息加到记忆中。这里我们先讲一下遗忘的过程,如下图所示的结构:

image-20191101225754189

经过sigmoid函数后,原有矩阵中的值会被归一到区间 [ 0 , 1 ] [0, 1] [0,1]之间,然后经过乘法运算,矩阵中数值接近于0的元素将会被弱化,相反的,矩阵中数值接近于1的元素将会被增强。正是通过这种操作,LSTM实现了"遗忘"的功能,能够将一些不重要的信息忘记。

下面我们讲一下输入到sigmoid函数中的矩阵是怎么得来的,如下图所示:

img

输入到sigmoid函数中的矩阵是由上一层的隐藏态 h t − 1 h_{t-1} ht1和本层输入 x t x_t xt拼接得来的,在PyTorch可以通过concat函数实现其拼接,拼接后的矩阵与权重矩阵 W f W_f Wf相乘,最后加上对应的偏置项 b f b_f bf,以此得到输入到sigmoid函数中的参数矩阵。

我们前面说了,LSTM除了"遗忘门",还有"记忆门",其记忆结构如下:

img

相信有了上一部分对于"遗忘门"的介绍,理解这里的"记忆门"应该变得非常简单,因为它的操作是一毛一样的。这里我们看到了两步计算结果: i t ~ \tilde{i_t} it~ C t ~ \tilde{C_t} Ct~

i t ~ \tilde{i_t} it~的计算和上一步中的 f t f_t ft是一样的,都是将 h t − 1 h_{t-1} ht1 x t x_t xt进行拼接,然后通过乘以权重矩阵 W i W_i Wi,然后再通过sigmoid函数。这里注意,前面我们使用的是权重矩阵 W f W_f Wf,这里使用的 W i W_i Wi,这说明这两个过程中我们使用的权重矩阵是不同的,对应的下一步计算 C t ~ \tilde{C_t} Ct~也是,但是 C t ~ \tilde{C_t} Ct~使用的激活函数是tanh,并不是sigmoid,这是为什么呢?这里就又涉及到sigmoid函数和tanh函数的值域问题了。

对于sigmoid函数,其值域是 [ 0 , 1 ] [0, 1] [0,1];而tanh函数的值域是 [ − 1 , 1 ] [-1, 1] [1,1],其实你可以将tanh函数看成是sigmoid函数的"长高"版:

两个函数对输入起到了不同的调节作用,sigmoid使用来将数据映射到 [ 0 , 1 ] [0, 1] [0,1]空间,而tanh是将数据映射到 [ − 1 , 1 ] [-1, 1] [1,1] i t ~ \tilde{i_t} it~ C t ~ \tilde{C_t} Ct~同样起到了增强和衰弱的作用,是的想要记住的东西记得更牢靠,不想记住的东西,进一步淡化。

通过上面的介绍我们得到了 f t f_t ft i t ~ \tilde{i_t} it~ C t ~ \tilde{C_t} Ct~,根据下图我们计算得出 C t C_t Ct:$ C_t = f_t·C_{t-1} + \tilde{i_t}·\tilde{C_t} $。

img

到这里,我们已经完成了"遗忘"和"记忆"的工作,一路走来是不是很简单,千万不要看到公式就害怕,其实每个公式都很简单,只是看上去形式比较吓人而已。

我们还有一项工作没有做,就是计算输出项,同样地,我们给出流程图如下:

img

右边的公式看着是不是依然很熟悉,我们首先通过原本的输入 h t − 1 h_{t-1} ht1 x t x_t xt的拼接与权重矩阵 W o W_o Wo相乘,然后加上新的偏置项 b o b_o bo,上述计算结果经过sigmoid函数得到 o t o_t ot,最后将 o t o_t ot与经过tanh激活的传输信息 C t C_t Ct相乘,就得到了我们想要的 h t h_t ht,同样的,这里的 h t h_t ht并不是真正的输出,也只是一个隐藏状态而已,要想得到真正的输出依然需要经过一次额外的变换才能得到。

至此,我们神经元内部的计算就都结束了,这里我们做一个简单的总结:

  • 首先每个神经元计算的输入项由两部分组成,分别是上一个隐藏态 h t − 1 h_{t-1} ht1和当前输入 x t x_t xt,两者通过拼接得到 [ h t − 1 , x t ] [h_{t-1}, x_t] [ht1,xt],这是今后所有矩阵运算的基础

  • 每一步计算中的权重矩阵 W W W和偏置项 b b b都是不同的,下面我们来罗列一下这些权重矩阵和偏置项:

    • 计算遗忘内筒时的中间结果 f t f_t ft,这里我们使用了 W f W_f Wf b f b_f bf
    • 为了计算记忆内筒,我们计算得到了中间结果 i t ~ \tilde{i_t} it~ C t ~ \tilde{C_t} Ct~,其分别对应 W i W_i Wi b i b_i bi以及 W C W_C WC b C b_C bC
    • 最后我们在计算输出的时候,得到中间结果 o t o_t ot,这里有 W o W_o Wo b o b_o bo

    在神经元内部,不同计算内筒间的参数矩阵和偏置项是不同的,但是整个串接的网络层中,对应位置的参数矩阵和偏置项一定是相同的。

  • 在计算过程中,我们大量使用了sigmoid函数,在这里它的主要作用看上去就是对数据进行"增强":重要的变得更重要(趋近于1),不重要的变得更不重要(趋近于0)。

  • 除了累加记忆结果的部分我们使用了矩阵的加法运算,其他地方使用的都是矩阵的乘法运算。

到此为止,我们算是将LSTM内部结构以及计算过程详细剖析了一边。对应的还有很多LSTM的变体形式,这里我们就不在一一说明了。

参考:

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: RNN(递归神经网络)是一种常用的深度学习技术,它具有记忆功能,能够学习序列数据中的规律和模式。RNN基本原理是,它以一种“循环”的方式来处理序列数据,它可以从输入序列中抽取相应的特征,然后再根据这些特征输出预测结果。RNN的运行过程主要包括:输入层、隐藏层和输出层。输入层用于获取输入序列的特征,而隐藏层以某种形式学习从输入序列中获取的特征,并将它们组合成一个新的特征向量,这个特征向量称为“状态”。最后,输出层利用这个特征向量来获得最终的预测结果。RNN还可以通过多种方式来提升训练的准确度,其中最常用的方法是“长短期记忆”(LSTM)和“门控循环单元”(GRU)。这两种方法都可以用来解决训练中的梯度消失问题,从而提高训练的准确度。总之,RNN可以让深度学习模型更加准确,更加有效地处理序列数据。 ### 回答2: RNN(循环神经网络)是一种常用于处理序列数据的神经网络模型。相较于传统的前馈神经网络RNN在处理序列数据时具有记忆功能,能够利用之前的信息来影响后续的预测。 RNN基本原理是通过引入循环结构来处理序列数据。它的每一个时间步都接收一个输入向量,同时还接收一个来自上一时间步的隐藏状态(hidden state)。隐藏状态可以理解为神经网络的记忆,它会持续地被更新和传递。 在RNN中,一个时间步的计算可以分为三个步骤:输入层到隐藏层的计算、隐藏层之间的传递、隐藏层到输出层的计算。 首先,输入向量和上一时间步的隐藏状态作为输入,通过一个权重矩阵进行线性变换,并经过激活函数得到隐藏层的输出。 其次,当前时间步的隐藏层输出会与一个新的隐藏状态相结合,用于传递到下一时间步。隐藏层之间的传递可以保证之前的信息在序列中传递。 最后,隐藏层的输出通过另一个权重矩阵进行线性变换,并再次经过激活函数得到最终的输出。 RNN的训练过程主要涉及到权重矩阵的更新。通常使用反向传播算法来计算损失函数对于参数的梯度,然后使用梯度下降算法来更新权重矩阵。 然而,传统的RNN在处理长序列时存在梯度消失和梯度爆炸的问题,即随着时间步的增加,梯度会呈指数级地增大或减小。为了解决这些问题,人们提出了改进的RNN模型,如LSTM(长短期记忆网络)和GRU(门控循环单元)。 LSTM和GRU通过引入门控机制来控制信息的流动,从而解决了长序列时的梯度问题。这些门控机制可以过滤掉不重要的信息,只保留对当前任务有用的信息。 总之,RNN是一种适用于处理序列数据的神经网络模型。它通过循环结构和隐藏状态的传递,能够利用之前的信息对后续的预测产生影响。然而,传统的RNN存在着梯度消失和梯度爆炸的问题,因此改进的RNN模型如LSTM和GRU被提出来以解决这些问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值