深度学习:循环神经网络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网络结构

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

简单的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).

Note:

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

2 通过观察RNN的计算过程,可以发现整个过程在反复共享U,V,W这三个权重矩阵,所有循环的参数也被反复使用,这样可以极大的减少参数量,并且可以根据序列时间步的不一样处理不同长度的序列。

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

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

[rnn训练方法数据输入方式]

某小皮

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模型 ]

训练时的损失函数

在训练时,网络在整个序列上的损失函数可以如下定义:

 

其中L_t为t时刻的损失,Loss(,)为损失函数,通常使用交叉熵损失函数。

BiLSTM-CRF模型的损失函数

在训练过程中,我们的BiLSTM-CRF模型的参数值将会一次又一次的更新,以保持增加真实路径(在所有路径上)的分数百分比。
LossFunction = P_realpath / (P1+P2+...+Pn)
加log即变成:当前转移状态矩阵在正确路径的分数与所有路径分数之和的负对数似然。
[BiLSTM上的CRF,用命名实体识别任务来解释CRF(2)损失函数]
[BERT-BILSTM-CRF的损失函数是什么啊? - 知乎]

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. GitHub - karpathy/char-rnn: Multi-layer Recurrent Neural Networks (LSTM, GRU, RNN) for character-level language models in Torch 2. GitHub - crazydonkey200/tensorflow-char-rnn: Char-RNN implemented using TensorFlow.]

基于 RNN 的语言模型例子

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

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

from: 深度学习:循环神经网络RNN_上一次隐藏层在不同时间步_-柚子皮-的博客-CSDN博客

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

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

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

[RNN模型]

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值