0%

循环神经网络(RNN)简单理解

循环神经网络(Recurrent Nerual Networks,简称RNN)近年来被业界视作处理序列数据以及做自然语言处理的灵丹妙药。其变种LSTM仍是当今最先进的数据处理模型之一。

理解RNN的工作原理,可帮助机器学习人员建立起有效的模型,更好地对数据进行有效的处理。

概念

什么是RNN?首先让我们比较下传统前向神经网络与RNN的网络架构。

左:传统神经网络架构 右:RNN架构

从图中可以看出,两者的差异主要在于网络是如何接收输入数据的。

  • 传统前向神经网络:接受固定数量(所有数据量)的输入,进行定量的输出
  • RNN:并非一次性使用所有的数据作为输入。反之,RNN有多个步骤,每个步骤将一部分数据序列化输入,经过一系列计算产生输出,直到所有的序列结束。

这样讲可能仍然难以理解,下把这张序列化的动图可以辅助大家更好地理解。

上图可以看到,每一步的计算会将上一步的计算输出对应的隐藏状态(Hidden State)作为一部分输入。由此看出,RNN对处理序列化相关的数据有天生的优势。

另外我们可以看到,RNN每一步的神经元计算,是采用相同的网络结构,这是RNN的另外一个重要特点。

RNN网络的输入输出

您可能会有疑问了:RNN输出来自于网络的哪一步?答案是,这取决于您要解决的问题是什么。例如,如果您用RNN做分类任务,那么您所需要的是从所有输入得到的最终输出;或者您要做单词预测任务,那么您会需要RNN网络序列的每一步都作出输出。

RNN输出数据多种形式

上图可以看出,RNN是非常灵活的,可以根据您的需要制定RNN的网络模型,喂给网络不同类型的输入,得到不同的输出。

RNN多对一输出

上图示例中,所有时刻的输入,经过RNN网络,得到最后的输出结果。

RNN多对多输出

而本示例中(上图),RNN序列的每一步输出都是我们需要的。除此之外,在例如翻译任务中,我们可能在会先接受多个输入序列,产生一个输出。再根据这个输出,最后产生多个输出序列。如下图英语翻译为法语的示例:

RNN 翻译示例

RNN单元内部工作原理

到这里,您可能对RNN网络的框架有个基本了解。不过具体每一个RNN单元是如何工作的呢?

首先我们看传给RNN序列下一步的隐藏状态是如何产生的。有如下公式:

$$
hidden_t = F(hidden_{t-1}, input_t)
$$

即当前步的隐藏状态,由上一步的隐藏状态加上这部分的输入经过函数F处理后产生。而第一步的隐藏状态,一般会在整个RNN初始化时人为设置为0。在最简单的RNN中,函数F一般为每个输入乘以对应的权重再用激活函数做非线性处理。激活函数一般有RELU、Sigmoid或tanh。下边公式为采用tanh作为激活函数:

$$ hidden_t = tanh(W_{hiddent}*hidden_{t-1},W_{input} * input_t) $$

而我们若需要在RNN单元每一步产生一个输出,那么这个输出一般由该步的隐藏单元做一个线性处理产生,例如:

$$ output_t = W_{output}* hidden_t $$

可以看出,上一个RNN单元的隐藏状态会被传递给下一个RNN单元,如此重复,直到运行到我们设定的停止条件。

当然,这是一个最简单的RNN网络形式。RNN网络还有许多相对复杂的变种(当然是为了针对性解决其他网络形式的一些问题而提出),例如LSTM、GRU等。

RNN网络的训练

RNN需要经过训练才能学习“”到更精准的拟合,从而得到我们想要的数据。

RNN网络的权重更新

我们知道,神经网络通过学习和更新网络中的权重来接近最优解(见本站文章),RNN也不例外。通过一步步后传播算法来减小损失函数(Cost Function)最终得到最小值,RNN的后传播会需要前面RNN单元的数据,本文不作推导。

总结

本文对循环神经网络(RNN)的基本框架和原理做了介绍。为方便理解,略去的数学推导。接下来,计划对RNN网络的变形LSTM、GRU等做介绍,并增加Tensorflow代码实现。