为什么用RNN
在自然语言处理中,前面的内容对后面的内容有很大的影响,比如说:
今天天气很不错.
今
字后面是天
字的概率就比其他字大很多.同样天
字后面是气
字的概率也比较大.这就要求神经网络在做每一次预测的时候要结合上下文,每个时序的预测都能够结合能前面几次预测的结果.
普通的神经网络显然做不到这点,所以就有了循环神经网络 (RNN).
RNN的结构
一个基本的RNN结构如下图所示:
RNN由许多RNN单元组成,每一个单元处理一个时序.为输入,为输出.RNN做预测时会结合前面的结果.
举个例子,我们要做一个翻译的任务,将中文:
今天天气很不错.
翻译成英文:
The weather is very good today.
此时输入x为中文,长度为, ~ 对应中文中的每个汉字.输出y为英文,长度为,分别对应 ~ (后面会讨论与不一致的情况).
需要注意的是,RNN模型并不是有很多RNN单元,而是将一个RNN单元在不同时序重复使用.
在RNN单元中,前面带来的影响与当前时序带来的影响相融合:
然后RNN会使用融合后的影响进行预测,另外也会被传递到下一个时序:
RNN形态
为了满足不同的需求,RNN的形态有很多种.但是他们都有一个共同的特征就是每个RNN单元都会结合前面RNN单元所产生的影响.
在翻译或是语言识别领域,与相差很大,这种情况,我们使用Many-to-Many类型的RNN网络:
在情绪分类中,需要将一段文字转化为一个评分或是等级,可能会很大,但是为1,这种情况是Many-to-One类型的RNN:
同样我们可以得到One-to-Many类型的RNN:
当然还有与相等的Many-to-Many类型的RNN:
梯度爆炸与梯度消失
RNN的训练过程也是根据反向传播来更新权值的,因为RNN的链式结构,所以反向传播会计算比较深层的导数.
举个简单的例子,我们用反向传播对求导:
得到:
导数是很多项的连成,可以想象RNN的连乘比这还要多,连乘数过多就会造成一个现象,如果这些数都比较大,就会造成最终的结果比较大,甚至超出浮点数最大值,这就是梯度爆炸.如果这些数都比较小,那么会造成最终的结果非常小,导致前面的参数更新困难,这是梯度消失.梯度消失会导致RNN只有短期的记忆.
RNN的缺点并不能完全避免,但是以下两种RNN的升级版GRU及LSTM在一定程度上克服了RNN的弱点.
GRU
GRU比普通RNN多了一个记忆单元,的值与相等.
GRU首先计算当前时序对记忆单元的影响:
然后用计算出了一个阀值:
然后用这个反之来调节记忆对当前决策的影响:
LSTM
LSTM比普通RNN多了一个贯穿网络的变量.这个变量用来跟踪语法结构,比如说一段文字中主语是单数还是复数.定义为:
其中为上一个时序单元传递的输出,为当前时序对c的预估:
及为两个0~1之间的变量,被称作遗忘门与更新门.
当语法结构发生变化时,遗忘门帮助摆脱我们先前存储的记忆值。
当语法结构发生变化时,更新门帮助记忆当前的状态。
LSTM的输出会在RNN的基础上增加:
参考:
https://www.coursera.org/learn/nlp-sequence-models
https://www.kaggle.com/swimmingwhale/recurrent-neural-network