循环神经网络(RNN)小结

附上几个不错的教程:

  1. WILDML
  2. http://www.aboutyun.com/thread-21258-1-1.html
  3. http://karpathy.github.io/2015/05/21/rnn-effectiveness/

循环神经网络(Recurrent Neural Network,RNN)是一类用于处理序列数据的神经网络。所谓序列数据,即前面的输入和后面的输入是有关系的,如一个句子,或者视频帧。就像卷积网络是专门用于处理网格化数据$X$(如一个图像)的神经网络,循环神经网络是专门用于处理序列$x^{(1)},\dots,x^{m}$的神经网络。正如卷积网络可以很容易地扩展到具有很大宽度和高度的图像,以及处理大小可变的图像,循环网络可以扩展到更长的序列。大多数循环网络也能处理可变长度的序列。

语言模型

RNN在自然语言处理领域中比较流行,比如RNN可以为语言模型来建模。那么什么是语言模型呢?
我们可以和电脑玩一个游戏,我们写出一个句子前面的一些词,然后让电脑帮我们写出接下来的词。比如:

  • 我昨天上学迟到了,老师批评了____。

我们给电脑展示了这句话前面这些词,然后,让电脑写下接下来的一个词。在这个例子中,接下来的这个词最有可能是『我』,而不太可能是『小明』,甚至是『吃饭』。
语言模型就是这样的东西:给定一个一句话前面的部分,预测接下来最有可能的一个词是什么。
语言模型是对一种语言的特征进行建模,它有很多很多用处。在RNN出现之前,语言模型只要采用的是N-Gram。N可以是一个自然数,比如2或3等等。它的含义是,假设一个词出现的概率只和前面N个词相关。我们以2-Gram为例。首先对前面的一句话进行切词:

  • 我 昨天 上学 迟到 了 ,老师 批评 了 ____。

如果用2-Gram进行建模,那么电脑在预测的时候,只会看到前面的『了』,然后,电脑会在语料库中,搜索『了』后面最可能的一个词。不管最后电脑选的是不是『我』,我们都知道这个模型是不靠谱的,因为『了』前面说了那么一大堆实际上是没有用到的。如果是3-Gram模型呢,会搜索『批评了』后面最可能的词,感觉上比2-Gram靠谱了不少,但还是远远不够的。因为这句话最关键的信息『我』,远在9个词之前!
现在读者可能会想,可以提升继续提升N的值呀,比如4-Gram、5-Gram…….。实际上,这个想法是没有实用性的。因为我们想处理任意长度的句子,N设为多少都不合适;另外,模型的大小和N的关系是指数级的,4-Gram模型就会占用海量的存储空间。所以,该轮到RNN出场了,RNN理论上可以往前看(往后看)任意多个词。

RNN

RNN背后的思想是来处理序列信息。在传统的神经网络中,我们假设所有的输入和输入之间是相互独立的。但是这种普通的神经网络对于很多问题却无能为力。例如,你要预测句子的下一个单词是什么,一般需要用到前面的单词,因为句子中前后单词并不是独立的。RNN之所以成为循环神经网络,是因为它对序列的每个元素执行相同的任务(参数共享),而输出取决于前面的计算。也可以说,RNN会对前面的信息进行记忆并用于当前的计算中,即隐藏层之间不再是无连接的而是有连接的,并且隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。理论上,RNN能对任意长的数据序列进行处理,但是实践中它只能受限于与前面几个状态有关(后面会介绍)。

RNN的结构

下图是一个典型的RNN:

RNN包含输入单元(input units),$X = \{x_0,x_1,\dots,x_t,x_{t + 1},\dots\}$,输出单元(output units),$O = \{o_0,o_1,\dots,o_t,o_{t+1},\dots\}$,隐藏层单元(hidden units),$S = \{s_0,s_1,\dots,s_t,s_{t+1},\dots\}$。
共享的参数$U$,是从输入层到隐藏层的权重,$V$是从隐藏层到输出层的权重,$W$就是隐藏层到隐藏层之间的权重。你会发现,图中有一条单向流动的信息流是从输入单元到大隐藏单元的,与此同时另一条单向流动的信息流从隐藏单元到大输出单元。RNN还可能引导信息流从输出单元返回隐藏单元,这些被称为“back projections”,并且隐藏层的输入还包括上一隐藏层的状态,即隐藏层内的节点可以自连也可以互连。
上图可以将左图的RNN(可能比较抽象)可以通过unfold变为右边比较直观的网络。”unfold”的意思就是说,我们写出完整的序列表示的网络;例如我们有一个长度为5的句子,那么这个网络就unfold为长度为5的神经网络,每个单词一个layer。
让我们用公式来形式化RNN的计算过程:

(1)是隐藏层的计算公式,它是一个循环层,(2)是输出层的计算公式,是一个全连接层,也就是它的每个节点都和隐藏层的每个结点相连。$f$和$g$都是激活函数。
我们反复的将(1)代入到(2)中,可以得到:

从上面可以看出,循环神经网络的输出值$o_t$是受前面历次的输入值$\{x_0,x_1,\dots,x_{t-1}\}$影响的,这就是为什么RNN可以往前看任意多个输入值的原因(可以处理序列信息的原因)。

需要强调的是:
  • 你可以将隐藏层$s_t$看成是网络的记忆。$s_t$捕捉了发生在之前时间步(time step)的信息。输出$o_t$仅仅记忆$s_t$记忆进行计算。如上所述,在实践中有点复杂,因为$s_t$通常无法从太多的时间步骤中捕获信息。
  • 不像传统的深度神经网络在不同的layer使用不同的参数,RNN在的time step中共享相同的参数($U,V,W$)。这表示我们在每一步都执行同样的任务,只是输入不同。这大大减少了我们需要学习的参数。
  • 上图在每一个time step都有一个输出,但是根据任务有时候这并不是必须的。例如,当我们要预测一个句子的情感时,我们只关注最后的输出,并不关注每一个单词的情感。同样地,我们并不一定要每个time step都有输入。RNN的主要特征是它的隐藏层,它可以捕捉一些关于序列的信息。

    RNN的另一种结构

    在这里,$f$里是我们要设计的RNN的主要结构,它接收两个输入$h$和$x$,然后给出两个输出$y$和$h’$.
    其中,

  • $x$为当前状态下的输入
  • $h$表示接收到的上一个结点的输入,(隐藏层到隐藏层)
  • $y$为当前结点状态下的输出
  • $h’$为传递到下一个结点的输出
    同样进行unfold可以得到:

    RNN的扩展

    双向(bidirectional)RNN

    双向RNN的基本思想就是,$t$时刻的输出可能不仅取决于其前面的序列,而且还可能和后面的序列有关系。比如,
  • 我的手机坏了,我打算____一部新手机。
    可以想象,如果我们只看横线前面的词,手机坏了,那么我是打算修一修?换一部新的?还是大哭一场?这些都是无法确定的。但如果我们也看到了横线后面的词是『一部新手机』,那么,横线上的词填『买』的概率就大得多了。
    由此,上面的基本的RNN是无法对该语言模型进行建模的,所以我们需要双向RNN。 我们来看一下$y_0$是如何计算的,以便理解双向RNN的计算过程。其中,从上面的计算我们可以看出正向计算和反向计算的过程是不共享权重的,但是在同一个方向上是共享的。也就是说$U,U’,V,V’,W,W’$分别是不同的权重参数。

另一种直观的双向RNN表示

Deep RNN

前面我们提到的RNN都是只有一个隐藏层,我们当然也可以堆叠很多个隐藏层。这样我们就得到了Deep RNN。这给我们提供了更强大的学习能力,但是同时我们也需要更多的训练数据,否则很容易过拟合。

每一层的计算方法和上述完全相同,这里就省略不提。
另一种比较直观的Deep RNN表示

RNN的训练

训练RNN和训练传统的神经网络非常相似。我们也使用反向传播算法,不过稍微有点区别。因为在RNN中,参数在所有的time step都是共享的,所以在每个输出处的梯度不仅取决于当前time step的计算,也和前面的time step的有关。比如,为了计算$t=4$时的梯度,我们需要反向传播$3$并对梯度求和。这个方法叫做BackPropagation Through Time(BPTT)。
具体的推导可以看这里

RNN的梯度爆炸和梯度消失问题

不幸的是,前面介绍的几种RNNs并不能很好的处理较长的序列。一个主要原因是,RNN在训练中很容易发生梯度爆炸梯度消失,这导致训练时梯度不能在较长序列中一直传递下去,从而使RNN无法捕捉到长距离的影响。
为什么会产生梯度爆照和梯度消失问题呢?根据上面链接中的推导,式子(3) 我们可以得到:

上式中的$\beta$定义为矩阵模的上界。因为上式是一个指数函数,如果$t-k$很大的话(也就是说向前看很远的时候),会导致对应的误差项增大或缩小的非常快(取决于是大于1还是小于1),这样就会导致梯度爆炸或者梯度消失问题。神经网络中的梯度消失和梯度爆炸问题
通常来说,梯度爆炸更容易解决,因为梯度爆炸时程序会输出NaN。我们也可以设定一个阈值来进行梯度裁剪。

总结

目前为止,我们已经了解了RNN所做的事情。但是上面提到了,由于梯度消失和梯度爆炸问题,使得RNN不能解决长期依赖问题——也就是说无法真的看的很远。为了解决这个问题,下一篇文章我们会介绍几个RNN的变体如LSTM,GRU等。


-------------本文结束感谢您的阅读-------------


本文标题:循环神经网络(RNN)小结

文章作者:Statusrank

CSDN博客欢迎来访!

发布时间:2019年04月28日 - 10:04

最后更新:2019年04月28日 - 15:04

原始链接:https://statusrank.xyz/articles/5f0e8406.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

万水千山总是情,就给五毛行不行!