一文搞懂 RNN(循环神经网络)

技术讨论 chengzi ⋅ 于 8个月前 ⋅ 1902 阅读

目录

1 基础篇

  • 神经网络基础
  • 为什么需要RNN(循环神经网络)
  • RNN结构
  • 小结

2 RNN的反向求导过程

  • RNN的BPTT过程

3 RNN为什么能够记忆历史信息

  • 普通神经网络(MLP)
  • 循环神经网络记录历史信息RNN

4 RNN的两种应用

  • RNN用作表示句子
  • RNN用作表示上下文语境
  • 两种应用的Loss definition



1 基础篇


神经网络基础

神经网络可以当做是能够拟合任意函数的黑盒子,只要训练数据足够,给定特定的x,就能得到希望的y,结构图如下:
file

将神经网络模型训练好之后,在输入层给定一个x,通过网络之后就能够在输出层得到特定的y,那么既然有了这么强大的模型,为什么还需要RNN(循环神经网络)呢?

为什么需要RNN(循环神经网络)

他们都只能单独的取处理一个个的输入,前一个输入和后一个输入是完全没有关系的。但是,某些任务需要能够更好的处理序列的信息,即前面的输入和后面的输入是有关系的。

比如,当我们在理解一句话意思时,孤立的理解这句话的每个词是不够的,我们需要处理这些词连接起来的整个序列;当我们处理视频的时候,我们也不能只单独的去分析每一帧,而要分析这些帧连接起来的整个序列。

以nlp的一个最简单词性标注任务来说,将我 吃 苹果 三个单词标注词性为 我/nn 吃/v 苹果/nn。

那么这个任务的输入就是:

我 吃 苹果 (已经分词好的句子)

这个任务的输出是:

我/nn 吃/v 苹果/nn(词性标注好的句子)

对于这个任务来说,我们当然可以直接用普通的神经网络来做,给网络的训练数据格式了就是我-> 我/nn 这样的多个单独的单词->词性标注好的单词。

但是很明显,一个句子中,前一个单词其实对于当前单词的词性预测是有很大影响的,比如预测苹果的时候,由于前面的吃是一个动词,那么很显然苹果作为名词的概率就会远大于动词的概率,因为动词后面接名词很常见,而动词后面接动词很少见。

所以为了解决一些这样类似的问题,能够更好的处理序列的信息,RNN就诞生了。

RNN结构

首先看一个简单的循环神经网络如,它由输入层、一个隐藏层和一个输出层组成:
file

不知道初学的同学能够理解这个图吗,反正我刚开始学习的时候是懵逼的,每个结点到底代表的是一个值的输入,还是说一层的向量结点集合,如何隐藏层又可以连接到自己,等等这些疑惑~这个图是一个比较抽象的图。

我们现在这样来理解,如果把上面有W的那个带箭头的圈去掉,它就变成了最普通的全连接神经网络。x是一个向量,它表示输入层的值(这里面没有画出来表示神经元节点的圆圈);s是一个向量,它表示隐藏层的值(这里隐藏层面画了一个节点,你也可以想象这一层其实是多个节点,节点数与向量s的维度相同);

U是输入层到隐藏层的权重矩阵,o也是一个向量,它表示输出层的值;V是隐藏层到输出层的权重矩阵

那么,现在我们来看看W是什么。循环神经网络隐藏层的值s不仅仅取决于当前这次的输入x,还取决于上一次隐藏层的值s。权重矩阵 W就是隐藏层上一次的值作为这一次的输入的权重。

我们给出这个抽象图对应的具体图:

file

我们从上图就能够很清楚的看到,上一时刻的隐藏层是如何影响当前时刻的隐藏层的。

如果我们把上面的图展开,循环神经网络也可以画成下面这个样子:

file

RNN时间线展开图

现在看上去就比较清楚了,这个网络在t时刻接收到输入 $ x_{t} $ 之后,隐藏层的值是 $ s_{t} $ ,输出值是 $ o_{t} $ 。关键一点是, $ s_{t} $ 的值不仅仅取决于 $ x_{t} $ ,还取决于 $ s_{t-1} $ 。我们可以用下面的公式来表示循环神经网络的计算方法:

用公式表示如下:

file

RNN公式

总结

好了,到这里大概讲解了RNN最基本的几个知识点,能够帮助大家直观的感受RNN和了解为什么需要RNN,后续总结它的反向求导知识点。

最后给出RNN的总括图:

file

注意:为了简单说明问题,偏置都没有包含在公式里面。



2 RNN的反向求导过程


本质上来看RNN的反向求导过程和普通的神经网络BP过程是没有任何区别的,但是由于RNN的特殊性,每一个timestep都共享参数矩阵,使得它的反向求导过程(Backpropagation Through Time (BPTT))稍微复杂一点。

一、RNN的BPTT过程

首先我们来回忆一下RNN的公式: $ \begin{array}{l}{s_{t}=\tanh \left(U x_{t}+W s_{t-1}\right)} \\ {\hat{y}_{t}=\operatorname{softmax}\left(V s_{t}\right)}\end{array} $
其中预测结果 $ {\hat{y}_{t}} $ 与 正确结果 $ {y}_{t} $ 做交叉熵得到损失值:
$ \begin{aligned} E_{t}\left(y_{t}, \hat{y}_{t}\right) &=-y_{t} \log \hat{y}_{t} \\ E(y, \hat{y}) &=\sum_{t} E_{t}\left(y_{t}, \hat{y}_{t}\right) \\ &=-\sum_{t} y_{t} \log \hat{y}_{t} \end{aligned} $
得到了损失值,我们就可以开始进行反向求导过程了。这里需要注意的是,在每个timestep,如果是做序列标注任务,我们每一个时刻都会预测一个结果,并得到一个损失值,那么最终的损失将会是所有时刻损失之和,如下所示:

总的损失表示:
$ \frac{\partial E}{\partial W}=\sum_{t} \frac{\partial E_{t}}{\partial W} $
下面以第3时刻为例,其它位置均为相同操作。
首先求对参数 $ V $ 进行求导,这个最简单,过程如下:
$ \begin{aligned} \frac{\partial E_{3}}{\partial V} &=\frac{\partial E_{3}}{\partial \hat{y}_{3}} \frac{\partial \hat{y}_{3}}{\partial V} \\ &=\frac{\partial E_{3}}{\partial \hat{y}_{3}} \frac{\partial \hat{y}_{3}}{\partial z_{3}} \frac{\partial z_{3}}{\partial V} \\ &=\left(\hat{y}_{3}-y_{3}\right) \otimes s_{3} \end{aligned} $
其中 $ z_{3}=Vs_{3} $ ,对 $ V $ 的求导最简单是因为它只依赖到当前timestep的前向值 $ \hat{y}_{3},y_{3}, s_{3} $ 。上面要求出最终结果具体还涉及到softmax求导过程,但不是这篇文章重点,就不细说了,不是很清楚的同学可以参考下面这篇文章:

忆臻:详解softmax函数以及相关求导过程

下面对参数 $ W $ 进行求导( $ U $ 完全一样),这是RNN反向传播的特殊之处:
我们也可以很轻松的由链式法则得到下面结果:
$ \frac{\partial E_{3}}{\partial W}=\frac{\partial E_{3}}{\partial \hat{y}_{3}} \frac{\partial \hat{y}_{3}}{\partial s_{3}} \frac{\partial s_{3}}{\partial W} $
但是这还没有完!
其中的 $ {s_{3}=\tanh \left(U x_{3}+W s_{2}\right)} $ , $ s_{3} $ 依赖于 $ s_{2} $ 和 $ W $ ,
这个时候不能简单的把 $ s_{3} $ 当做常数看待,继续穷追猛打链式法则,直到最开始的地方,这是核心。 于是可以继续展开公式:

file

合成公式为:
$ \frac{\partial E_{3}}{\partial W}=\sum_{k=0}^{3} \frac{\partial E_{3}}{\partial \hat{y}_{3}} \frac{\partial \hat{y}_{3}}{\partial s_{3}} \frac{\partial s_{3}}{\partial s_{k}} \frac{\partial s_{k}}{\partial W} $
到现在我们讲完了RNN的所有参数求导过程。 后面有时间也会讲一下RNN造成的梯度消失,爆炸问题,和LSTM一系列问题包括求导过程。



3 RNN为什么能够记忆历史信息

首先介绍一下为什么普通的神经网络不能记忆以前的历史信息,然后引出RNN的相应能力,因为如果普通的神经网络能够记录以前的历史信息的话,那么也就不会有RNN思想的诞生了。

普通神经网络(MLP)

首先我们有一个任务,就是进行词性标注,下面有两个训练数据。

他向我表白
我觉得他的表白不够真诚

正确的词性是:

file

file

那么将这些训练数据送给神经网络进行训练,比如第一个数据 “他/r”,神经网络学习 “他->r”的一个映射,第二个数据 “向/p”,神经网络学习一个 “向->p”的映射,这样一直将训练数据学习完,更新到最后的参数,从而学习到model,但是问题来了。 学习示例图如下:

file

在上面的训练数据中,有些词语的词性并不是唯一的,比如“表白”一词,在“他向我表白”这句话中作为动词v,在“我觉得他的表白不够真诚”这句话中作为名词n,所以对于神经网络来说,它是会学乱的。一下子神经网络要学习“表白”是动词,一下子又要学习“表白”是名词,神经网络也很无辜呀,它没有能力来处理什么情况下应该将“表白”判别为名词,什么情况下降“表白”判断为动词,因为神经网络学习不到周围的语境。喂给神经网络的数据和之前的数据并没有联系。 所以我们这个时候就需要一个能够记忆以前历史信息的网络出现,比如在第一句话中,碰到表达一词的时候,我知道他前面的词是“我”/代词,那么代词后面的表白作为动词的概率就远大于名词的表白,当然RNN还能够看到他前面好几个词语,理论上rnn可以记忆当前词语前面的任何词。 同理在第二句话的时候,碰到“表白”一词的时候,我们的网络能够知道他前面的词是“的”/助词,那么助词后面的“表白”作为名词的概率就远大于动词的”表白“。 所以我们希望能够有一个网络在预测当前任务的时候,能够记忆以前的知识帮助当前的任务完成,这样RNN就闪亮登场了,可能有些小伙伴会说,它存在很多问题,比如不能长期记忆,但是这篇文章不介绍,但是无论如何,RNN提供了这种问题解决的可能。

循环神经网络记录历史信息RNN

首先来介绍一下RNN 首先看一个简单的循环神经网络如,它由输入层、一个隐藏层和一个输出层组成:

file

不知道初学的同学能够理解这个图吗,反正我刚开始学习的时候是懵逼的,每个结点到底代表的是一个值的输入,还是说一层的向量结点集合,如何隐藏层又可以连接到自己,等等这些疑惑~这个图是一个比较抽象的图。 我们现在这样来理解,如果把上面有W的那个带箭头的圈去掉,它就变成了最普通的全连接神经网络。x是一个向量,它表示输入层的值(这里面没有画出来表示神经元节点的圆圈);s是一个向量,它表示隐藏层的值(这里隐藏层面画了一个节点,你也可以想象这一层其实是多个节点,节点数与向量s的维度相同); U是输入层到隐藏层的权重矩阵,o也是一个向量,它表示输出层的值;V是隐藏层到输出层的权重矩阵。 那么,现在我们来看看W是什么。循环神经网络隐藏层的值s不仅仅取决于当前这次的输入x,还取决于上一次隐藏层的值s。权重矩阵 W就是隐藏层上一次的值作为这一次的输入的权重。 我们给出这个抽象图对应的具体图:

file

我们从上图就能够很清楚的看到,上一时刻的隐藏层是如何影响当前时刻的隐藏层的。 如果我们把上面的图展开,循环神经网络也可以画成下面这个样子:

file

RNN时间线展开图

现在看上去就比较清楚了,这个网络在t时刻接收到输入 $ x_{t} $ 之后,隐藏层的值是 $ s_{t} $ ,输出值是 $ o_{t} $ 。关键一点是, $ s_{t} $ 的值不仅仅取决于 $ x_{t} $ ,还取决于 $ s_{t-1} $ 。我们可以用下面的公式来表示循环神经网络的计算方法: 用公式表示如下:

file

RNN公式

那么我们将第二个公式一直代入到第一个公式后,就会有下面推导:

file

从上图可以看出,当前时刻确实包含了历史信息,这也就说明了循环神经网络(RNN)为什么能够记忆历史信息,在很多任务上也确实需要用到这样的特性。



4 RNN的两种应用

RNN的应用主要有两个,一个就是用来建模表示句子,得到一个完整的句子表示。一个是用来表示句子当上下文语境,比如到某一个单词的时候,RNN的隐藏层状态能够表示为从开始到该词语的句子语境表示,下面具体说一下。

RNN用作表示句子

file

它的应用可以有情感分析,条件句子建模,抽取,比如就情感分析为例来看。

我们任务的表示是:

  • Input: a sentence
  • Output: a sentiment label (2-class)

比如说:

  • Input I hate this movie
  • Output 1(代表正情感)

那种在传统中的做法是将“I hate this movie”这句话通过特征工程,变成一个特征向量,然后送入分类器。

而在RNN表示为句子的时候,我们将“I hate this movie”通过一个RNN,在最后一个RNN的隐藏层状态得到该句子的表示,然后相当于得到它的特征向量,如下:

file

其余两个条件生成和抽取的应用也是类似。

表示上下文语境

file

我们可以看到,表示为上下文语境的应用有序列标注(词性标注),语言模型预测下一个单词。

为什么这么说呢?

比如在预测this的词性的时候,我们并不是独立的只看单个this单词对最后的预测的影响,而是前面的RNN单元一起通过时间序列传过来的隐层表示作为当前的语境表示用于最后的词性预测:

如下表示:

file

而这两种典型的不同应用也造成了loss的定义不同,一个是对所有状态预测的loss之和表示,一个是只有最后一个loss。

两种应用的Loss definition

在RNN用作表示句子的应用中,loss就是最后的预测结果与真实的gold结果产生的loss反向传回来,如下图:

file

而在RNN用作表示上下文语境的应用中,total loss是所有时刻的loss之和。

如下图表示:

file

不同的loss是根据不同的任务具体来定义的。这里需要注意一下。

作者:忆臻@知乎
致谢:夏冲@paiisall和实验室的小伙伴们
参考:
【1】零基础入门深度学习(5) - 循环神经网络
【2】 Recurrent Neural Networks Tutorial, Part 3 – Backpropagation Through Time and Vanishing Gradients​www.wildml.com
【3】双神晚茶会分享和下列材料•Neubig Lecture slides nn4nlp-06-rnn.pdf•NNM4NLP Book•Neubig Lecture slides nn4nlp-06-rnn.pdf_


相关文章:
独立循环神经网络(IndRNN):打造更长更深的 RNN
【NIPS 2018】多伦多大学提出可逆 RNN:内存大降,性能不减!
机器学习大神 Bengio 发新论文,专注 RNN 优化难题将在 NIPS 提新概念


file
△ 关注极市平台
获得最新CV干货

小迷离

成为第一个点赞的人吧 :bowtie:
回复数量: 0
暂无回复~
您需要登陆以后才能留下评论!