RNN概念介绍
RNN是一种特殊的神经网络结构, 它是根据"人的认知是基于过往的经验和记忆"这一观点提出的. 它与DNN,CNN不同的是: 它不仅考虑前一时刻的输入,而且赋予了网络对前面的内容的一种'记忆'功能.
RNN之所以称为循环神经网路,即一个序列当前的输出与前面的输出也有关。具体的表现形式为网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐藏层之间的节点不再无连接而是有连接的,并且隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。RNN具有时间"记忆"的功能
按照RNN的内部构造进行分类:
传统RNN
LSTM
Bi-LSTM
GRU
Bi-GRU
RNN应用:
RNN的应用领域有很多, 可以说只要考虑时间先后顺序的问题都可以使用RNN来解决.这里主要说一下几个常见的应用领域:
① 自然语言处理(NLP): 主要有视频处理, 文本生成, 语言模型, 图像处理
② 机器翻译, 机器写小说
③ 语音识别
④ 图像描述生成
⑤ 文本相似度计算
⑥ 音乐推荐、网易考拉商品推荐、Youtube视频推荐等新的应用领域.
RNN结构
如图所示, 我们可以看到RNN层级结构较之于CNN来说比较简单, 它主要有输入层,Hidden Layer, 输出层组成.并且会发现在Hidden Layer 有一个箭头表示数据的循环更新, 这个就是实现时间记忆功能的方法.
从左图中就可以看出RNN呢其实就只是相当于在全连接神经网络的隐藏层增加了一个循环的操作。至于这个循环的操作具体是怎样的呢?上右图是RNN网络结构按照时间线展开图。
t-1, t, t+1表示时间序列
Xt是t时刻的输入,是一个[x0,x1,x2…xn]的向量
St是t时刻的隐藏层的值
U是输入层到隐藏层的权重矩阵
W是上一时刻的隐藏层的值传入到下一时刻的隐藏层时的权重矩阵
V是隐藏层到输出层的权重矩阵
Ot是t时刻RNN网络的输出
从上右图中可以看出,RNN网络在t时刻接受了输入Xt之后,隐藏层的值是St,输出的值是Ot。但是从结构图中我们可以发现St并不单单只是由Xt决定,还与t-1时刻的隐藏层的值St-1有关。
这样,所谓的隐藏层的循环操作也就不难理解了,就是每一时刻计算一个隐藏层地值,然后再把该隐藏层地值传入到下一时刻,达到信息传递的目的。
具体隐藏层值St计算公式如下:
得到t时刻隐藏层的值后,再计算输出层的值:
详细说明一下公式如下:
注意:在同一层隐藏层中,不同时刻的W,V,U均是相等地,这也就是RNN的参数共享。
怎么理解这个参数共享呢?
我自己的理解是,虽然说X{t-1},X{t},X{t+1}是表示不同时刻的输入,但是他们输入到RNN网络中的时候并不是作为单独的向量一个一个输入地,而是组合在一起形成一个矩阵输入,然后这个矩阵再通过权重矩阵U的变化,其实是同一时刻输入地,只是计算的先后顺序不同。因此同一个隐藏层中,不同时刻的输入他们的W,V,U参数是共享地。
详细过程解读:
在t =1时刻, 一般初始化输入S0=0, 随机初始化W,U,V, 进行下面的公式计算:
其中,f和g均为激活函数. 其中f可以是tanh,relu,sigmoid等激活函数,g通常是softmax也可以是其他。
时间就向前推进,此时的状态s1作为时刻1的记忆状态将参与下一个时刻的预测活动,也就是:
以此类推, 可以得到最终的输出值为:
总结 : 1. 这里的W,U,V在每个时刻都是相等的(权重共享).
2. 隐藏状态可以理解为: S=f(现有的输入+过去记忆总结)
BiRNN 双向RNN
虽然RNN达到了传递信息的目的,但是只是将上一时刻的信息传递到了下一时刻,也就是只考虑到了当前节点前的信息,没有考虑到该节点后的信息。具体到NLP中,也就是一句话,不仅要考虑某个词上文的意思,也还要考虑下文的意思,这个时候普通的RNN就做不到了。于是就有了双向RNN(Bidirectional RNN)。
BiRNN结构
上面是BiRNN的结构图,蓝框和绿框分别代表一个隐藏层,BiRNN在RNN的基础上增加了一层隐藏层,这层隐藏层中同样会进行信息传递,两个隐藏层值地计算方式也完全相同,只不过这次信息不是从前往后传,而是从后往前传,这样不仅能考虑到前文的信息而且能考虑到后文的信息了。
实现起来也很简单,比如一句话,“我爱NLP”,进行分词后是[“我”,“爱”,“NLP”],输入[[“我”],[“爱”],[“NLP”]],计算forward layer隐藏层值,然后将输入数据翻转成[[“NLP”],[“爱”],[“我”]],计算backward layer 隐藏层值,然后将两个隐藏层的值进行拼接,再输出就行啦。
这就是BiRNN的原理,理解了RNN的原理,应该来说还是比较简单地。
DRNN 深层RNN
上图是DRNN的结构图,很简单,每一个红框里面都是一个BiRNN,然后一层BiRNN的输出值再作为另一个BiRNN的输入。多个BiRNN堆叠起来就成了DRNN。