【序列模型】第一课--循环序列模型

一. why sequence models?

在这里插入图片描述
(1)序列模型广泛应用于语音识别,音乐生成,情感分析,DNA序列分析,机器翻译,视频行为识别,命名实体识别等众多领域。
(2)上面那些问题可以看成使用(x,y)作为训练集的监督学习,但是输入与输出的对应关系有非常多的组合,
比如一对一,多对多,一对多,多对一,多对多(个数不同)等情况来针对不同的应用。

二.数学符号说明 Notation

假设有这样一句话:
X:Harry Potter and Hermoine Granger invented a new spell.
目的是想识别出句子中的实体词。所谓实体词包括人名, 地名,组织机构名称等等。
可见,输入的句子可以看成是单词的序列,那么我们期望的输出应是如下对应的输出:
Y:1 1 0 1 1 0 0 0 0
1代表的是“是实体”;0代表的是“非实体”
(当然,实际的命名实体识别比这输出要复杂得多,还需要表示实体词的结束位置与开始位置,在这个栗子中我们暂且选择以上这种简单的输出形式来讲解)

显而易见,输入的x与输出的y的序列个数一致,且索引位置相对应,我们用如下符号来表示输入与输出:
在这里插入图片描述
\(t\)表示第t时刻的输入;
\(T_x\) 表示样本\(x\)的序列长度;\(T_y\) 表示样本\(x\)输入模型后,输出序列的词长度,在本例中,输出与输出序列的长度相等,为9;
\(x^{(i)<t>}\),\(y^{(i)<t>}\)
样本往往有很多个,用以下符号表示,第i个样本t时刻的输入与输出:
用以下符号表示第i个样本的输入序列的长度与输出序列的长度:
\(T^{(i)}_x\), \(T^{(i)}_y\)

三.What is the Recurrent Neural Networks

(1) 为什么叫循环神经网络呢?

  • 1.输入和输出在不同的样本中可以有不同的长度,即使能找到输入输出的最大值,对某个样本来说填充来使他达到最大长度,但是这种表示方式依然不够好;
  • 2.标准神经网络不能讲从文本不同位置学习到的特征共享,比如在第一个位置学习到了Harry是一个人名,如果Harry再次出现在其他位置的时候,不能自动识别它是一个人名,还需要重新识别
    在这里插入图片描述

(2) 什么是循环神经网络?

仍然使用这句话作为例子
X:Harry otter and Hermoine Granger invented a new spell.
首先将第一个词Harry作为第一个输入\(x\),中间经过一堆隐藏层,然后输出\(y\)
接着将第二个词Potter作为第二个输入, 通用经过相同的隐藏层结构,获得输出。但这次,输入不但来自于第二个单词Potter,
还有一个来自上一个单词隐藏层中出来的信息(一般叫做激活值)\(a\)作为输入;
同理,接着是输入第3个词and, 同样也会输入来自第二个词的激活值;以此类推,直到最后一个词;
另外,第一个单词前面也需要一个激活值,这个可以人为编造,可以是0向量,也可以是用一些方法随机初始化的值。
在这里插入图片描述
词一个一个输入的,可以看成每个时间输入一次,所有输入的隐藏层是共享参数的。设输入层到隐藏层到参数为\(W_{ax}\),激活值到隐藏层到参数记为\(W_{aa}\).
根据以上结构,显而易见,第一次输入的单词会通过激活值影响下一个单词的预测,甚至影响接下去的所有单词的预测,这就是循环神经网络。

(3)前向传播

在这里插入图片描述
\(a^{<0>}\)是人为初始化的到的;
\(x^{<1>}\)是t=1时刻的输入;
输入层的权重是\(W_{ax}\);
激活层的权重是\(W_{aa}\);
输出层的权重是\(W_{y1}\);

要计算的是每个时刻的激活值\(a^{<t>}\)与输出值\(y^{<t>}\)
\(a^{<1>}\)的计算:
在这里插入图片描述
\(\hat{y}^{<1>}\)的计算
在这里插入图片描述
g()是一个激活函数,通常选用tanh,有时也是用relu用于避免梯度弥散。若是输出是2分类,往往采用sigmoid作为激活函数,因为本例中是要判别是否为实体店而分类,因此采用sigmoid函数。
扩展的一般情况\(a^{<t>}\)与输出值\(\hat{y}^{<t>}\)如下计算:
在这里插入图片描述

(4)简化RNN表示

其中\(W_a\)\(W_{aa}\)\(W_{ax}\)的左右拼接,若\(W_{aa}\)纬度10010000,\(W_{ax}\)纬度10010000,则组合后\(W_{a}\)纬度是100*10100
在这里插入图片描述
同理第二个公式也简化成:
在这里插入图片描述

四.RNN中的时间反向传播

(1)回顾前向传播

回顾前向传播算法,有一个长度为\(T_x\)的序列
在这里插入图片描述
通过输入的\(x\),可以求出每一个时间上的激活值\(a\):

回顾上一节,时间\(t\)上的激活值\(a\)是由\(t-1\)时刻的\(a\),与\(t\)时刻的输入\(x\)乘以参数而得:
\(a^{<t>}=g(W_{aa}a^{<t-1>}+W_{ax}x^{<t>}+b_a)\) ====>>\(a^{<t>}=g(W_{a}[a^{<t-1>},x^{<t>}]+b_a)\)

每一个时间上的运算都是共享一组参数\(W_a\),\(W_b\),如下:
在这里插入图片描述

接着,计算RNN的输出y:

同样,回顾y是通过当前时刻的激活值与参数相乘的到的:
在这里插入图片描述

每一时刻的计算也是共享了一组参数\(W_y\)
在这里插入图片描述
于是前向传播就完成了。

(2)损失函数 loss function

前向传播的过程是反向传播的基础, 而为了计算反向传播,还需要定义一个损失函数。
此处使用交叉熵损失函数

  • 首先计算每个时间t上的损失,即计算序列中单次输入x,计算得到y的损失L( )
  • 接着计算总的损失,即计算所有时间上的损失的总和

(3)反向传播

将损失函数对各个参数求导,利用梯度下降法更新参数,红色箭头表示反向传播的过程
在RNN中的反向传播亦叫时间反向传播back propogation through time

五.RNN的不同类型

(1)多对多

命名实体识别中,输入的序列与输出的序列都有多个元素,且长度相同,称之为many-to-many结构,多对多结构。
1】输入输出序列长度一致
在这里插入图片描述
2】多对多也可以实现输入与输出序列长度不等的情况,最常见的是机器翻译,先来看看结构:
在这里插入图片描述
模型由2部分组成,前面一部分叫做encoder(编码), 将要翻译的文本序列逐次输入,但不产生输出;后一部分叫做decoder(解码),编码器的输出是解码器的输入,
而接下去的每个时间上都不再有输入,但每次都会有一个输出。解码器输出的序列就是对编码器输出序列的翻译。

(2).多对一

文本情感分析中,输入的是文本的序列,每个词都是一个输入,而输出的往往是类别标签,比如给电影的评价等级分为5档,或者判别文章正面情感与负面情感的2档。
在这里插入图片描述
最后一个时间上会有y输出,而其他时间上都不再有y输出。这种结构叫做many-to-one结构,多对一结构。

(3).一对多

比如音乐生成的例子,输出的是一段音符的序列,而输入的可以是整数,表示你想要的音乐风格,或者是第一个音符,表示你想要用这个音符开头,或者什么都不输入,让模型自由发挥。
在这里插入图片描述
首先,只在第一个时间有输入x,其他时刻都没有;
其次,每一个时刻都会有输出,总的输出形成一个序列;
要注意的是,有一个技术细节,通常用RNN生成序列的时候,会把前一个时刻的输出y也作为t时刻的输入,以上红色箭头表示。

(4).总结

在这里插入图片描述

六.语言模型与序列生成 Language model and sequence generation

(1)什么是语言模型?

比如speech recognition语音识别,即将声音识别成文字(国内语音识别做得不错的是科大讯飞)。
假如人说一句话“The apple and pear salad”,可以识别成以下两句话:
在这里插入图片描述
其中,pair与pear读音相同,显然第二句话才是正确识别说话人的意图。那要如何来选择最正确的句子呢?这就要用到语言模型了。
语言模型计算出两句话概率:
在这里插入图片描述

显然第二句的概率是第一句概率的近100倍,因此选择第二句话。也就是说语言模型会给你任何一句的概率,从而可以根据概率来选择最有可能正确的句子。

语言模型的应用目前有两大范畴,第一就是上面说的语音识别;第二就是机器翻译,同理,通过计算句子概率找到最正确的那句翻译。

(2)怎么建立用RNN建立语言模型呢?

1】首先要拥有一个训练集:巨大的语料库,越大越好
2】对语料库进行标记化,在前面几节中提高过,根据语料库整理出一个词典,并用one-hot的词向量表示每个词。有三个注意点:
A.一般会用的符号来表示句子的结尾
B.对于之后新的文本中出现了语料库中未出现过的词,则将其用表示
C.至于要不要将标点符号作为词典的一部分,这个看具体需求与问题来定夺。
3】接着,建立RNN模型
假设有这样一句话:
在这里插入图片描述
在第一个时间\(t=1\)时,输出的\(x^{<1>}\)为0向量,因为第一个词之前没有词;激活值\(a^{<0>}\)也初始化为0向量;如此计算后,得到的\(y^{<1>}\)是softmaxt里出来的一个向量,
其长度为词典的长度,每一个位置上的值都是对应词典中的词的概率。注意字典也包括\(<EOS>\),与\(<UNK>\)
在这里插入图片描述
在第二个时间\(t=2\)时,输入的\(x^{<2>}\)实际上就是第一个单词\(y^{<1>}:cat\);通过softmax计算,同样会得到词典长度的概率分布向量,这个概率是\(P(Word / cat)\)即前面为单词cat时,
词典中每个词出现的条件概率。
在这里插入图片描述
以此类推,一直到最后一个时刻,输入的\(x^{<9>}=y^{<8>}="day"\)
在这里插入图片描述
4】计算损失函数
每次计算输出的概率分布时预测值,与实际值比较从而计算损失,对于单词次时刻,损失的公式为:
在这里插入图片描述
\(i\) 遍历词典,对词典中每个词的值进行汇总
总的损失,是所有时间上的损失的和:
在这里插入图片描述

七.采样新序列 Sampling novel sequences

当你训练好一个RNN之后,想要知道这个模型到底学到了什么呢?最基本的应用就是进行一次新序列采样,换一种说法,就是让RNN去随机生成一个新的序列。

(1) 采样生成新序列过程

假设我们用大量的英文语料根据如下过程训练出了一个RNN模型:

接着我们要用这个训练好的RNN来采样生成一个新的序列。
首先时刻t=1,仍然输入的是初始化的\(x^{<1>}=0\),\(a^{<0>}=0\),通过softmaxt的计算,会输出一个词典大小的概率分布向量,此时我们对这个向量进行采样,随机采出一个词作为输出(注意是随机,不是取最大概率)
在这里插入图片描述
接着来到了t=2时刻,此时的输入是上一个时间随机采样的词,同理对softmaxt概率分布随机采样,又采出了第二个词。
在这里插入图片描述

同理,每一个时间t,都取t-1点输出词作为输入,直到某个时刻的输出为,则采样终止。
在这里插入图片描述

当然有的时候会采样出,若是不想它出现,可以判断一下,若出现了则继续重新采样另一个词。

(2) 基于字符的语言模型

也有许多人尝试基于字的RNN模型,即每次的输入不再是一个单词,而是一个字母,字典里还包括空格,符号等等。但这有两个问题:
第一:一句话有10-20个单词,但却有上百个字母,这使得序列的长度大大加大了,序列约长,则前面的词对后面的词传递的信息就会越来越弱,从而使词的依赖关系逐渐丧失。
第二:训练起来会比较复杂和耗资源

但是也有两个原因使得现在越累越多的应用中会尝试基于的RNN模型:
第一:目前的计算能力越来越大
第二:在某些领域中,有专有名词,而专有名词往往很稀少得不被词典包含,从而产生许多,而使用基于字母的字典结构,将不会遇到这个问题,因为再不常见的英文单词都是由24个字母组成。

笔者:以上讲的是英文的应用,中文其实略有不同。
首先英文的单词是被空格天然地分割,因此不会产生把一个单词错误地一劈为二的情况,但中文是没有任何符号表示单词与单词之间的分割,中文分词的瓶颈仍然是一大阻碍。因此,有时候尝试基于字的建模可能反而效果会比基于词的要好。

基于字符的模型举例:
根据news,用莎士比亚的样本训练后,模仿出莎士比亚的文笔
在这里插入图片描述

八.RNN的梯度弥散 Vanishing gradients with RNNs

前面我们介绍了RNN的结构,前向传播与反向传播,RNN在命名实体、语言模型中的应用,这一节要讲述在构建RNN中会遇到的一个问题:梯度弥散问题。本节讲述什么是梯度弥散,后面几节会讲述如何解决这个问题。

(1)什么是梯度弥散

首先来看传统的深层神经网络:
在这里插入图片描述

假设这个网络很深,有1000层甚至更多,那么经过前向传播得到输出层的y之后,很难再通过梯度下降法将y的梯度传播回去,即后面的梯度很难影响前面的权重。

对于RNN也是同样的道理,你已经很熟悉RNN的结构了:
假设有两个训练样本,句子的长度非常长:
The cat, with already ate…………, was full.
The cats, with already ate…………, where full.
第一个句子的was是依赖于cat, 第二个were是依赖于cats,但是这两个单词被隔得非常远,以至于后者的单词很难依赖于前者得到。

因为,与传统的深层神经网络类似,经过前向传播之后,反向传播中后面的\(y^{<t>}\)误差很难通过梯度影响到前面层的计算,因此当RNN在计算后面的单词was还是were的时候,对前面出现过的cat或cats已经忘得差不多了。

也因此,其实每次的输出\(y^{<t>}只能反向传播影响到前面附近的几层计算,也就是说,在训练时无论\)y^{}的预测是正确的还是错误的,或者说损失是大是小,都无法通过反向传播告诉很前面的层,并且对前面的层有效调整权重。

这是基本的RNN算法的一个缺点

(2)梯度爆炸exploding gradients

除了梯度弥散的问题,RNN也会遇到梯度爆炸的问题,但这个问题比较好解决,因此在这里顺带讲述。

如何发现梯度爆炸?
梯度爆炸很好发现,因为指数极大的梯度,会让你的参数变得极其大,以至于你的网络参数奔溃,你会看到很多NaN或者不是数字的情况,这说明你的网络出现了数值溢出。

如何解决梯度爆炸?
当发现梯度爆炸时,一个解决方式就是梯度修剪
观察你的梯度向量,一旦发现超过某个阀值,就缩放梯度向量,保证他不会太大。比如通过一些最大值来修剪的方法

九.GRU单元Gated Recurrent Unit

上一节中讲了RNN有个梯度弥散的缺陷,难以捕捉深层依赖,于是,这一节要讲述一个解决该问题的方法,即在隐藏层加入GRU(Gated Recurrent Unit, 门控循环神经单元)。它可以捕捉深层链接,并大大改善梯度消散问题。

(1) 前戏

首先,回顾一下,我们之前讲的时间t上的神经元计算过程:
在这里插入图片描述

对于t时刻,有一个t-1时刻的激活值作为输入,有一个t时刻的x值作为输入,两个输入乘以各自的权重之后,作为激活函数tanh的输入,tanh的输出一边传给softmaxt层得到\(y^{<t>}\), 一边直接传给下一个时间。\(a^{<t>}\)的公式如下:
\(a^{<t>}=g(W_a[a^{<t-1>},x^{<t>}] + b_a)\)

(2) GRU的计算过程

(1)首先我们用\(C\)表示记忆细胞,\(C^{<t-1>}\)表示\(t-1\)时刻的记忆信息,在GRU中,你暂且认为\(c^{<t>}=a^{<t>}\),是层与层之间传递的激活值,只是计算过程略有不同。
(2)同样,有两个输入,一个是上一层的\(c^{<t-1>}\), 一个是本时刻的输入\(x^{<t>}\)
(3)第一步计算:\(c^{<t-1>}\)\(x^{<t>}\)分别乘以各自的权重之后经过tanh激活函数,输出\(\hat{c}^{<t>}\)
这个计算过程就相当于之前讲述的传统RNN计算过程,只是现在输出的c不是最终输出值,将它放在一边等待,我们来看另一步计算。
在这里插入图片描述
(4)第二步计算:可以看成是与第一步计算平行进行,将输入的\(c^{<t-1>}\)\(x^{<t>}\)分别乘以另一组权重,经过一个sigmoid函数,输出\(Γ_u\): sigmoid函数是分布在0与1之间,大部分值会非常接近0或着1.
在这里插入图片描述
(5)第三步计算:第一步与第二步计算中我们得到了两个值,一个来自于tanh函数,一个来自于sigmoid函数。这一步我们将这两个值整合如下,计算出最终的c
在这里插入图片描述
上一步可知,\(Γ_u\)是sigmoid函数的输出,因此大部分值会分布在0或者1的附近,假设\(Γ_u=1\),它与\(\hat{c}\)相乘之后,\(\hat{c}\)的信息被原封不动地保留下来了,而\(c^{<t-1>}\)的信息被去除了;反之,若\(Γ_u=0\), 则该层原来的激活值\(\hat{c}\)被去除,而上一层的信息\(c^{<t-1>}\)被全部保留。因此可以发现\(Γ_u\)其实就像是一个记忆门,由它决定是否需要记忆上一层的信息或着这一层的信息。
(6)上面计算所得的\(c^{<t>}\)为最终的激活值,继续按照老套路,一边传给softmaxt函数输出\(y^{<t>}\), 一边传给下一层神经元

以上就是GRU的整个过程,或者说是一个简化版的GRU。

(3) GRU的优点

(1)大部分时候,其实\(Γ_u\)是为0的,那么其实大部分时候\(c^{<t>}=c^{<t-1>}\)这非常有利于维持细胞的值
(2)由于大部分时候\(c^{<t>}=c^{<t-1>}\),因此就一定程度上解决了梯度弥散的问题,深处的神经元也可依赖到很前面的信息,可以使神经网络运行在很深的层次上

(4) 更复杂一点的GRU

上面讲的GRU是简单版本的,在实际应用中的GRU会更复杂,接下去详细讲述。

首先,上面的公式回顾一下:
在这里插入图片描述
在上面的公式的基础之上做一些改变:
(1)\(\hat{c}\)的计算中加上一个另一个门\(Γ_r\):
在这里插入图片描述
可以看成是一个表示相关性的门,将它乘以\(c^{<t-1>}\)表示\(\hat{c}\)\(c^{<t-1>}\)有多大的相关性,即有\(c^{<t-1>}\)向量中有哪些位置上的信息相关性大则保留得更多。
(2)计算\(Γ_r\)的公式如下:
在这里插入图片描述

嗯嗯,就结束了。

(5) 总结

研究者们前赴后继地寻找着探索着更优的神经单元结构来使得RNN有更好的深层次依赖能力,来解决梯度弥散等问题,GRU算是一个非常标准或者基础,且被学术界和工业界广泛使用的结构,当然你也可以自己去探索出更优的结构。下一节将讲述另一个非常常用的RNN结构:LSTM。

十.长短时记忆单元LSTM unit (long short term memory)

上一节中学习了GRU,能够有效避免梯度弥散,而这一节要学习的LSTM,可谓是比GRU有更大的能力,因此也备受业界喜爱。

首先我们从图形上直观地看一下LSTM unit的运行结构:
在这里插入图片描述

第一步:忘记门

先来看上图中最左边的这块运算,
在这里插入图片描述
首先下方有一个叫做forget gate的小方块,它有两个输入,一个是上一个时刻的\(a^{<t-1>}\),另一个输入是这一个时刻的\(x^{<t>}\).
接着这两个输入会各自乘以一组权重,并且进入一个sigmoid函数得到\(Γ_f\)
在这里插入图片描述
这个运算叫做忘记门,权重w里存储的是哪些信息对应的位置应该被忘记,这样不重要的信息,或者对之后的预测没有用的信息就可以被过滤掉。

第二步:记忆门

在这里插入图片描述
接着看到update gate的小方块,叫做记忆门,与上面的忘记门对比显然可猜测,这个门的运算应该是为了能够更新一些信息。
输入也是\(a^{<t-1>}\)\(x^{<t>}\), 将它们乘以一组权重之后,也进入一个sigmoid函数,得到\(Γ_u\),即被更新的信息
在这里插入图片描述

第三步:输出门

在这里插入图片描述
直接看输出门的计算:
在这里插入图片描述
和上面几个门是一样的,无非是换了一组参数

第四步:

在这里插入图片描述
\(a^{<t-1>}\)\(x^{<t>}\)这两个输入还会乘以第四组权重,并且过一个\(tanh\)激活函数,得到\(\hat{c}^{<t>}\):

可以看到,以上讲的四部运算,刚好是第一张全图的下面4个小框:

第五步:计算c

在这里插入图片描述
来看黄色圈出来的这块区域,圆圈里的星号表示乘法运算,加号表示求和运算。第一个乘号分别由两个箭头指向,分别是上一个时刻的c,以及第一步中计算得到的忘记门Γf;第二个乘号也分别由两个箭头指向,分别是第二部计算中得到的更新门Γu,以及c_mao.中间的加号,将两边的乘积求和。
在这里插入图片描述

第六步:计算a

在这里插入图片描述
在这里插入图片描述

第七步:输出

一个LSTM unit的输出有两个,分别是第5步与第6步计算的\(c^{<t>}\)\(a^{<t>}\)(注意与GRU的区别,GRU中\(c^{<t>}=a^{<t>}\)).
\(c^{<t>}\)会直接输给下一个时刻t+1, 它是由忘记门与更新门共同作用的,承载着滚滚黄河中前朝往事的记忆,让来世代代后人不忘初心。
\(a^{<t>}\)由两个方向的输出,一方面它会输给本时刻的softmax层去得到\(y^{<t>}\), 另一方面,它也会作为下一个时刻的输入。

将一个LSTM unit链接起来就是酱紫的:
在这里插入图片描述

红线的路径就是c的流动路线,和GRU一样,它能够掌握时间维度上的深层依赖,使得后面的计算仍然能参考到前面的信息。

上面讲述的是基础的LSTM的结构,在其他文献或者博客中你可能还会看到一个不同点,即会多一个门,叫做偷窥门。即在忘记门,更新门,输出门计算的时候,会增加一个\(c^{<t-1>}\)作为输入,以偷窥前面的记忆。:
在这里插入图片描述
公式的变动上,只是在三个门中多输入一个\(c^{<t-1>}\)即可,其他并无差别。

结束语:

无论是上一节讲述的GRU,还是这一节讲述的LSTM并不是由于它们是什么高深的算法,所以要特地拿出来讲,而是因为它们确确实实地被广泛地应用在了业界,是算法工程师们的头号青睐对象。
LSTM比GRU提出地更早,GRU的效果没有LSTM好,但是其结构简单,计算复杂度低,适合于很复杂的深层网络;LSTM效果更好,但是结构略复杂。
不过如果你硬要在建模的时候推荐一个,那么还是建议先使用LSTM哈哈。

十一.双向神经网络Bidirectional RNN

到目前为止,已经掌握了RNN的主要构件,但还有两个很重要的知识,能够帮助你的RNN产生更好的效果,一个就是双向RNN,另一个是深层RNN。本节将讲述双向RNN的内容。

(1)Why BRNN?

顾名思义,双向RNN,即可以从过去的时间点获取记忆,又可以从未来的时间点获取信息。那么我们为什么要获取未来的信息呢?还是以一开始的例子实体识别来看,假设以下两个句子,第一句话中的teddy是一只熊,非实体,第二句话中的Tedddy是一个人,是人名实体,但是仅仅是依靠这个单词前面的内容,完全无法判别它们的差异,而要继续看了后面的内容,才知道,原来第一句话讲的是bear, 第二句话将的是president.
在这里插入图片描述
因此,未来时间点的信息也对当前的预测起着至关重要的作用,双向RNN可以有效解决这个问题。

(2) How BRNN?

那么双向RNN到底是如何运作的呢?
在这里插入图片描述
双向RNN在RNN基础之上,在每一个时间上增加了一个新的激活单元;
同样,新增的激活单元也会向上连接;
最重要的是,绿色的新增激活值会向左传递,由时间t传给时间t-1;

这样就构成了一个无环图,输入一个序列,计算的过程是这样的:
(1)前向和反向的计算会同时异向进行
前向从计算\(a^{<1>}\)\(a^{<2>}\)\(a^{<4>}\),同时反向从\(a^{<4>}\)\(a^{<1>}\)
(2)两个方向的激活值都计算完毕后,就可以计算输出值\(y\)

\(y^{<3>}\)输出为例,在双向RNN中,它说到前面时间1,2的影响,即\(x^{<1>}\),\(x^{<2>}\)的影响,同时又受到了后面信息\(x^{<4>}\)的影响。
注意,以上的神经元,不仅仅可以是标准的RNN单元,还可以是GRU,LSTM等。事实上,双向 LSTM RNN用得是最广泛的。
总之,双向RNN避免了只听半语就妄下定论的不良习性,对事物有全盘了解之后再做决断,偏听则暗,兼听则明。

十二.深层循环神经网络Deep RNN

本节要讲的是深层循环神经网络。又可以顾名思义了,深层,那肯定是在原来的基础之上多加了几层而已。

(1) Deep RNN 的结构

只有一层的循环神经网络如下:
在这里插入图片描述
那么深层,其实就是这样:
在这里插入图片描述
上面是一个3层的循环神经网络,其中\(a^{[1]<0>}\)表示第1层的第0时刻的激活值。

(2) Deep RNN 激活值的计算

那么这些激活值是怎么计算的呢?以\(a^{[2]<3>}\)为例,它有两个输入:
一个来自是当前时刻的,前一层的输出;
一个是来自前一时刻,同层的输出。
公式如下:
在这里插入图片描述
其中\(W^{[2]}_a\)\(b^{[2]}_a\)是指第二层的权重,整个第二层都共享这组权重

(3)深层?

以上介绍了一个有3个隐藏层循环神经网络,但是只有3层,你确定可以叫“深层”吗?
额,是的,对于RNN来说,3层已经深得不容易了。由于时间的维度,就算只有恨少的层次,RNN的网络会变得异常大。你很少会见到向卷积神经网络那样堆叠到几十层甚至一百层的RNN。

但是如果你说,不行不行不行,人家就要放很深很深的层,那好,可以这样放:
也就是说,在3层的RNN基础之上,将每个时刻输出的y再进入一个深层的普通神经网络,注意这些神经元之间没有横向的连接。
在这里插入图片描述
同样,深层RNN中的神经单元也可以用GRU,LSTM等。

参考文献

[1]【序列模型】第一课--循环序列模型](https://blog.csdn.net/sinat_33761963/article/details/80195636)

posted @ 2018-11-02 21:34  nxf_rabbit75  阅读(1490)  评论(0编辑  收藏  举报