循环神经网络简介
循环神经网络(Recurrent Neural Network, RNN)是一类以序列数据为输入,在序列的演进方向进行递归且所有节点(循环单元)按链式连接的递归神经网络。
我们的大脑与机器的一个最大区别就是具有记忆能力,在实际应用中,很多元素都是相互联系的,例如你想预测句子中的下一个单词,你就要知道它的前后文分别是哪些单词才能给出正确的答案,这对没有记忆能力的神经网络而言相当困难,因为传统的神经网络结构各个元素之间是相互独立的,输入与输出也是独立的。
基于传统神经网络的这种缺陷,基于记忆模型的循环神经网络应运而生。循环神经网络最大的特点就是具有记忆能力,并且能够根据这些记忆内容来进行推断。之所以称之为循环,是因为循环神经网络对序列的每个元素都会执行相同的任务,所有的输出都取决于先前的计算,依赖于当前的输入和记忆。换句话说,循环神经网络是有记忆的,可以获取它到当前为止的计算信息。需要注意的是,虽然理论上来说,循环神经网络可以在任意长的序列中使用信息,但实际上它往往只能记忆几个步骤。
循环神经网络目前已经应用在很多领域,尤其是在NLP任务中,循环神经网络取得了较大成功:
- 机器翻译:类似于语言建模,输入为源语言中的一系列单词,通过模型计算可以输出目标语言与之对应的内容。
- 语音识别:给定来自声波的声学信号的输入序列,可以预测一系列语音片段及其概率,并把语音转化成文字。
- 生成图像描述:与卷积神经网络一起使用可以生成标记图像的描述。
循环神经网络的结构
循环神经网络的基本结构非常简单,就是将网络的输出保存在一个记忆单元中,这个记忆单元会和下一次的输入一起进入到网络中。一个典型的循环神经网络如下图所示:

循环神经网络简单结构
可以看到,一个典型的循环神经网络包括一个输入X、一个输出h和一个神经网络单元A,与传统神经网络不通的是,循环神经网络中的单元A不仅与输入、输出相连接,其自身也存在一个回路,这就使得其能够将当前的网络状态信息保存并作用于下一次的网络操作。
循环神经网络可以被看做是同一神经网络的多次赋值,每个神经网络模块会把消息传递给下一个,我们可以将上述循环神经网络结构图展开如下图所示:

循环神经网络展开图
可以看到,等号右边的等价循环神经网络中最初始的输入是X0,输出是h0,表示在0时刻循环神经网络的输入为X0,输出为h0,网络神经元在0时刻的状态保存在神经元A中。当下一个时刻1到来时,此时神经元A的状态不仅由1时刻的输入X1决定,也由0时刻的神经元A状态决定。以此类推,直到t时刻为止。
根据上述的结构可以看出,循环神经网络在处理序列类型的数据上具有天然的优势,因为其网络本身就是一个序列结构。事实上,循环神经网络就是基于此设计的,这也是循环神经网络最本质的结构。
虽然循环神经网络具有较好的记忆特性,但其记忆能力却并没有很强,其中最大的问题就在于它的遗忘性,循环神经网络与人脑一样,总是会更加清楚地记得最近发生的事而遗忘很久以前发生的事。
PyTorch创建循环神经网络
PyTorch的nn模块中提供了RNN类可用于直接搭建基于序列的循环神经网络,RNN类构造函数有以下几个参数:
- input_size:输入数据X的特征值的数目。
- hidden_size:隐藏层的神经元数量,也就是隐藏层的特征数量。
- num_layers:循环神经网络的层数,默认值是 1。
- bias:默认为True,如果为False则表示神经元不使用 ias偏移参数。
- batch_first:如果设置为True,则输入数据的维度中第一个维度就是batch值,默认为False。默认情况下第一个维度是序列的长度, 第二个维度才是batch,第三个维度是特征数目。
- dropout:如果不为空,则表示最后跟一个dropout层抛弃部分数据,抛弃数据的比例由该参数指定。
其中,最主要的两个参数就是input_size和hidden_size。下面我们使用PyTorch中的nn.RNN类创建一个循环神经网络。

PyTorch创建循环神经网络
上述代码设置输入X的特征数量为20,隐藏层的特征数量为50,循环神经网络为2层,得到的输出为[100, 32, 50]的张量。在实际应用中,我们也经常通过继承nn.RNN重写循环神经网络模型。