深度学习:循环神经网络RNN

http://blog.csdn.net/pipisorry/article/details/77776743

RNN模型

        循环神经网络(recurrent neural network,RNN)是一种具有反馈结构的神经网络,其输出不但与当前输入和网络的权值有关,而且也与之前网络的输入有关;RNN通过添加跨越时间点的自连接隐藏层,对时间进行建模;换句话说,隐藏层的反馈,不仅仅进入输出端,而且还进入了下一时间的隐藏层。 一般的RNNs有多个FNN横向连接而成,其中中间有个rnn-cell, 存储的是前面序列的隐含状态s。 分解开来的话, 就相当于三层,第一层是输入x到rnn-cell的连接,第二层是rnn-cell,得到的是隐藏状态s,第三层是rnn-cell到输出o的连接层

        RNNs 主要处理时序数据,比如一句话,词与词之间都是有顺序的,因此经常用在NLP领域,比如机器翻译,情感分析等。

Note: 还有一种网络叫递归神经网络recussive neural network,应用不广。

        RNN和浅层前馈神经网络的区别和联系:shallow feedforward neural networks (those with just one hidden layer) can only cluster similar words, recurrent neural network (which can be considered as a deep architecture [5]) can perform clustering of similar histories. [Mikolov, Tomáš, et al. "Extensions of recurrent neural network language model." ICASSP 2011]

        RNN和CNN在参数共享上的区别和联系:recurrent networks can be seen as imposing weight-sharing across layers, which makes them inflexible and difficult to learn due to vanishing gradient.  convolutional networks enjoy the flexibility of not having weight-sharing, at the expense of having redundant parameters when the networks are deep.

RNN处理序列

        序列。普通神经网络和卷积神经网络的一个显而易见的局限就是他们的API都过于限制:他们接收一个固定尺寸的向量作为输入(比如一张图像),并且产生一个固定尺寸的向量作为输出(比如针对不同分类的概率)。不仅如此,这些模型甚至对于上述映射的演算操作的步骤也是固定的(比如模型中的层数)。RNN之所以如此让人兴奋,其核心原因在于其允许我们对向量的序列进行操作:输入可以是序列,输出也可以是序列,在最一般化的情况下输入输出都可以是序列。

下面是一些直观的例子:

        上图中每个正方形代表一个向量,箭头代表函数(比如矩阵乘法)。输入向量是红色,输出向量是蓝色,绿色向量装的是RNN的状态。从左至右为:

  1. 非RNN的普通过程,从固定尺寸的输入到固定尺寸的输出(比如图像分类)。
  2. 输出是序列(例如图像标注:输入是一张图像,输出是单词的序列)。
  3. 输入是序列(例如情绪分析:输入是一个句子,输出是对句子属于正面还是负面情绪的分类)。
  4. 输入输出都是序列(比如机器翻译:RNN输入一个英文句子输出一个法文句子)。
  5. 同步的输入输出序列(比如视频分类中,我们将对视频的每一帧都打标签)。

        注意在每个案例中都没有对序列的长度做出预先规定,这是因为循环变换(绿色部分)是固定的,我们想用几次就用几次。

        相较于那些从一开始连计算步骤的都定下的固定网络,序列体制的操作要强大得多,并且对于那些和我们一样希望构建一个更加智能的系统的人来说,这样的网络也更有吸引力。RNN将其输入向量、状态向量和一个固定(可学习的)函数结合起来生成一个新的状态向量。在程序的语境中,这可以理解为运行一个具有某些输入和内部变量的固定程序。从这个角度看,RNN本质上就是在描述程序。实际上RNN是具备图灵完备性的,只要有合适的权重,它们可以模拟任意的程序。然而就像神经网络的通用近似理论一样。如果训练普通神经网络是对函数做最优化,那么训练循环网络就是针对程序做最优化。

        无序列也能进行序列化处理:将序列作为输入或输出的情况是相对少见的,但是即使输入或输出是固定尺寸的向量,依然可以使用这个强大的形式体系以序列化的方式对它们进行处理。

RNN与语言模型

        RNN是在自然语言处理领域中最先被用起来的,比如,RNN可以为语言模型来建模。

什么是语言模型呢?

        我们可以和电脑玩一个游戏,我们写出一个句子前面的一些词,然后,让电脑帮我们写下接下来的一个词。比如下面这句:

我昨天上学迟到了,老师批评了____。

        我们给电脑展示了这句话前面这些词,然后,让电脑写下接下来的一个词。在这个例子中,接下来的这个词最有可能是『我』,而不太可能是『小明』,甚至是『吃饭』。

        语言模型就是这样的东西:给定一个一句话前面的部分,预测接下来最有可能的一个词是什么。

        语言模型是对一种语言的特征进行建模,它有很多很多用处。比如在语音转文本(STT)的应用中,声学模型输出的结果,往往是若干个可能的候选词,这时候就需要语言模型来从这些候选词中选择一个最可能的。当然,它同样也可以用在图像到文本的识别中(OCR)。

        使用RNN之前,语言模型主要是采用N-Gram。N可以是一个自然数,比如2或者3。它的含义是,假设一个词出现的概率只与前面N个词相关。我们以2-Gram为例。首先,对前面的一句话进行切词:

我 昨天 上学 迟到 了 ,老师 批评 了 ____。

        如果用2-Gram进行建模,那么电脑在预测的时候,只会看到前面的『了』,然后,电脑会在语料库中,搜索『了』后面最可能的一个词。不管最后电脑选的是不是『我』,我们都知道这个模型是不靠谱的,因为『了』前面说了那么一大堆实际上是没有用到的。如果是3-Gram模型呢,会搜索『批评了』后面最可能的词,感觉上比2-Gram靠谱了不少,但还是远远不够的。因为这句话最关键的信息『我』,远在9个词之前!现在读者可能会想,可以提升继续提升N的值呀,比如4-Gram、5-Gram.......。实际上,这个想法是没有实用性的。因为我们想处理任意长度的句子,N设为多少都不合适;另外,模型的大小和N的关系是指数级的,4-Gram模型就会占用海量的存储空间。

        所以,该轮到RNN出场了,RNN理论上可以往前看(往后看)任意多个词。In conventional language models, context is represented by n-grams, so these models condition on a fixed number of preceding words. 所以说RNN相对n-grams模型要好些。

 

 

RNN网络结构

作为对比:一般化的多层多类输出的神经网络

                              

        全连接神经网络隐藏层的值只取决于输入的 x。

简单的RNN网络结构如下:

其中,t 是时刻, x 是输入层, s 是隐藏层, o 是输出层,矩阵 W 就是隐藏层上一次的值作为这一次的输入的权重。在RNN中,x_t-1 , x_t, x_t+1 是在时序上不一样的输入,而 V, U, W 三个矩阵则是共享。同时RNN网络中保存了自己的状态S,S随着输入而改变, 不同的输入/不同时刻的输入或多或少影响RNN网络的状态S,而RNN网络的状态S则决定最后的输出。

        RNN 的隐藏层的值 s 不仅仅取决于当前这次的输入 x,还取决于上一次隐藏层的值 s。RNN输出层是一个全连接层,它的每个节点都和隐藏层的每个节点相连,隐藏层是循环层。[wiki:https://en.wikipedia.org/wiki/Recurrent_neural_network#Gated_recurrent_unit]

Note: RNN图中的每个y或者o就是隐层的rnn cell(也就是神经网络中的cell加了对应的相同cell的上一个状态),而在lstm中y就被替换成了lstm cell了,而每一个lstm cell就是lstm中复杂的图。Elman and Jordan networks are also known as "simple recurrent networks" (SRN).

        动态跨时间步的rnn网络通过两个时间步来展开,将连接以无环的形式可视化:RNN通过添加跨越时间点的自连接隐藏层,对时间进行建模;换句话说,隐藏层的反馈,不仅仅进入输出端,而且还进入了下一时间的隐藏层,网络结构如下:

以上的网络可以通过两个时间步来展开,将连接以无环的形式可视化:

Note:

1 循环网络有时被描述为深度网络,其深度不仅仅发生在输入和输出之间,而且还发生在跨时间步,每个时间步可以被认为是一个层;

2 权重(从输入到隐藏和隐藏到输出)在每个时间步是相同的,时间步的个数即句子的长度;(lz:所有时间步(序列输入)完成后才进行参数更新。那么batch方法是干嘛呢:是说每个时间步连续输入一个batch_size大小的词组,从而得到两个相加的输出,每个时间步都是如此,整个句子输入完成后就可以通过batch后的输出进行w更新了。从这里看,batch方法应该不适用于句子长度不一样的场景,这样你可以将句子padding成相同长度)

一般来说,每一时间的输入和输出是不一样的,比如对于序列数据就是将序列项依次传入,每个序列项再对应不同的输出(比如可以是下一个序列项,即预测后面的状态),如encoder-decoder模型中decoder预测时。

某小皮

 

 

RNN的训练和学习

RNN前向传播

前向传播(Forward Propagation)就是依次按照时间的顺序计算一次就好了。

公式展开表示

这里写图片描述

Note: 公式1表示输出层;公式2、3表示隐层。
其中a表示汇集计算的值(未激活值),b表示经过激活函数计算的值(激活值,也就是神经网络中的激活值z),w是不同节点之间连接的参数(具体谁连谁看下标),带下标k的是输出层,带下标h的是隐藏层相关的,所有带括号的的函数都是激活函数, ϵ 和 δ 的定义看公式,L 是最后的Loss function。

这里没有给出具体的计算方法,因为这和NN是一样的,可以看到输出层和普通的NN是完全一样的,接收隐藏层传入的数据并乘以参数求和,只是每一个计算出来的值都有个时间上标t,表示它是t时刻的那个节点。而隐藏层的计算就是和NN不同的地方,从之前的拓扑图也看到了,隐藏层会接受来自上一时间隐藏层传入的数据,在公式里也体现出来了:第一个求和是和NN一致的,接收来自输入层的数据,第二个是接收来自上一隐藏层的数据。[Alex的论文]

矩阵表示

或者(RNN前向传播

隐层

输出层,lz即  p(x_t+1 | x_<=t)  =  p(x_t+1 | h_t)

最大似然解法

[seq2seq模型 ]

RNN反向传播:BPTT算法

        RNN的模型训练:RNN可以按时间展开,从而进行前向以及后向计算,从而可以将传统的BP算法应用于RNN模型的训练,由于是按照时间展开的BP算法,所以术语就叫做BPTT(backpropagation through time);反向传播(Back Propagation)就是从最后一个时间将累积的残差传递回来即可(lz:也就是说所有时间步完成后(即一个序列输入完成)才进行参数更新),跟普通的神经网络训练并没有本质上的不同。

Backpropagation through time (BPTT) 参考文献

[D. E. Rumelhart, G. E. Hinton, R. J. Williams. 1986. Learning internal representations by back-propagating errors. Nature, 323:533.536.]

Additional information and practical advices for implementation of BPTT algorithm are described in [Mikael Bodén. A Guide to Recurrent Neural Networks and Backpropagation. In the Dallas project, 2002.].

        BPTT算法是针对循环层的训练算法,它的基本原理和BP算法是一样的,也包含同样的三个步骤:

  1. 前向计算每个神经元的输出值;
  2. 反向计算每个神经元的误差项值,它是误差函数E对神经元j的加权输入的偏导数;
  3. 计算每个权重的梯度。

最后再用随机梯度下降算法更新权重。

这里写图片描述
        这里主要给出的是计算隐藏层的累积残差的公式,因为输出层和经典的NN是一回事,可以看到第一个公式括号中的两个部分,一个是接收当前时间输出层传回的残差,第二个是接收下一时间隐藏层传回的残差。

[训练过程详解详解循环神经网络(Recurrent Neural Network)] [零基础入门深度学习(5) - 循环神经网络]*

RNN的BPTT推导

lz: 看出delta^t和delta^t+1相关,所以可以将序列反向输入,将delta^t+1改为delta^t-1达到更好的效果?

 

 

几个RNN网络的问题

BPTT训练RNN的缺陷:梯度弥散

        然而用BPTT训练RNN具有一个致命的缺陷,就是梯度弥散问题,下面为了分析简便,只考虑一个输入节点,一个隐藏节点以及一个输出节点的网络,如下图1,按时间展开为图2:

                                    图1                                                                       图2

        假设只考虑从时间节点t1到时间节点t2之间的序列,在节点t1给一个输入,t1与t2之间的节点输入都为0;那么节点t1的输入传到了节点t2时的输出随着t2-t1的增大而指数下降;与此同时,下降的速度也与时间点之间的传输权重以及激活函数有关;因此RNN并不能保持长时间的上下文信息;因此为了保存长时间的上下文信息,LSTM出现。

[RNN的梯度爆炸和消失问题]

为什么循环神经网络可以往前看任意多个输入值呢?

来看下面的公式,即 RNN 的输出层 o 和 隐藏层 s 的计算方法:

如果反复把式 2 带入到式 1,将得到:

这就是原因。

RNN LSTM 网络参数问题

在NLP任务中,词向量维度(embedding size)是否一定要等于LSTM隐藏层节点数(hidden size)?

单层LSTM不必,可以通过设置不同shape的weight和bias来实现(lz:x前面的w设置成[e,h],h前面的w仍设置成[h,h]);多层LSTM的embedding size实际上也不必等于hidden size(lz:第一层与后续层数设置为不同,后续层x前面的w设置成[h,h])。

pytorch中是lstm设置多层时,是不需要相等的。

但在Tensorflow实现多层LSTM时,使用的函数tf.contrib.rnn.MultiRNNcell()会自动将累加的LSTM的参数设为相同的shape,或者说,是模块化的直接累加LSTM层数。这样得来的多层LSTM网络,其参数weight和bias的shape都是相同的,所以当设置不同的embedding size和hidden size时会报错,更改为相同值时error消失。

[RNN LSTM 网络参数问题]

RNN参数数量

(embed_dim+hidden_units)*hidden_units+hidden_units

[参考lstm中参数数量计算https://youzipi.blog.csdn.net/article/details/78361778]

 

RNN示例和应用

文本生成示例

温度。在生成文本的时候,我们可以调节Softmax的温度。将温度从1降到更低的数值(比如0.5)可以让RNN更加自信的同时变得更加保守。相反,如果将温度设置的更高,结果会更加多样化,但是代价就是可能会出现错误(比如更多的拼写错误)。

[循环神经网络惊人的有效性(上): 字母级别的语言模型]

[循环神经网络惊人的有效性(下):RNN中的预测与神经元激活可视化]

[The Unreasonable Effectiveness of Recurrent Neural Networks]

[基于字符粒度的RNN让机器学会自己生成文本1. https://github.com/karpathy/char-rnn 2. https://github.com/crazydonkey200/tensorflow-char-rnn]

基于 RNN 的语言模型例子

[详解循环神经网络(Recurrent Neural Network)]

[零基础入门深度学习(5) - 循环神经网络:RNN的应用举例——基于RNN的语言模型]*

from: http://blog.csdn.net/pipisorry/article/details/77776743

ref: [Zachary C. Lipton:A Critical Review of Recurrent Neural Networks for Sequence Learning]*

[零基础入门深度学习(5) - 循环神经网络]*

[RNN以及LSTM的介绍和公式梳理 ]*

[RNN模型]

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页