自然语言处理:建造序列模型
你将会学习到序列模型以及如何将它们应用于自然语言处理以及其他问题,序列模型包括:循环神经网络简写RNN以及LSTM模型全称是长短期记忆网络。接下来你将会了解其中的时期是什么含义并且有能力应用到NLP(自然语言处理)问题。总之你将学习这些模型以及能将它们应用于序列数据,比如自然语言就是一个单词序列,你也将能够理解这些模型如何应用到语音识别或者是music generation以及其它问题
1.1为什么选择序列模型
你将会学习序列模型,它是深度学习中最令人激动的内容之一,循环神经网络(RNN)之类的模型在语音识别,自然语言处理和其他领域中引起变革。在本节课中你将会学习如何自行创建这些模型,我们先看一些例子,这些例子都有效使用了序列模型。
在进行语音识别时,给定了一个输入音频片段X并要求输出片段对应的文字记录Y,这个例子里的输入数据和输出数据都是序列数据,因为X是一个按时序播放的音频片段输出Y是一系列单词,所以你之后将要学到的一些序列模型如循环神经网络等等在语音识别方面是非常有用的;音乐生成问题是使用序列数据的另一个例子,在这个例子中只有输出数据Y是序列,X可以没有或者是一个整数(可能指代风格);在处理情感分类时输出数据X是序列数据给出评论对应的星级;序列模型在DNA序列分析中也十分有用,给定一段DNA序列,你能标记出哪部分是匹配某种蛋白质;机器翻译;视频行为识别时得到一系列视频帧,判断行为;进行命名实体识别时,可能会给定一个句子要你识别出句中的人名
以上问题都可以称为使用标签数据(X,Y)作为训练集的监督学习。但是你从以上可以看出序列问题有很多不同的类型,有些问题里输出数据X和输出数据Y都是序列,但就算在那种情况下X和Y有时候也会不一样长,有些问题只有X或Y是序列。因此你将会学到适用于不同情况的序列模型
1.2 数学符号
我们先从符号定义开始一步步构建序列模型
假设你现在有x
想要识别句子中的人名位置(命名实体识别)
用
X
<
t
>
X^{<t>}
X<t>表示序列数据,
T
x
T_x
Tx?表示输入序列长度,
T
y
表示输出序列的长度
T_y表示输出序列的长度
Ty?表示输出序列的长度
不同的样本用一下方式区别
.
X
(
i
)
<
t
>
X^{(i)<t>}
X(i)<t> 第i个训练样本序列的第t个元素
y
(
i
)
<
t
>
y^{(i)<t>}
y(i)<t> 第i个训练样本序列输出的第t个元素
T
x
(
i
)
T^{(i)}_x
Tx(i)? 第i个训练样本的元素个数
T
y
(
i
)
T^{(i)}_y
Ty(i)? 第i个训练样本的输出序列的元素个数
有一件事我们需要事先决定:怎样表示一个序列里单独的单词,你会怎么表示像Harry这样的单词,
x
<
1
>
x^{<1>}
x<1>实际应该是什么?
你可以先构造一个词典,然后使用One-Hot编码
x
<
t
>
x^{<t>}
x<t>指代句子中的任意词,它就是个One-Hot向量,说它是One-Hot是因为它只有一个值是1其余值都是0,所以你会有9个one-hot向量来表示这个句子中的9个单词。
词典中列出你的表示方法中要用到的单词,在这个例子中使用了10000个单词大小的词典,这对现代自然语言处理应用来说太小了,对于一般规模的商业应用来说30000到50000词大小的词典比较常见 但是100000词的也不是没有,而且有些大型互联网公司会用百万词甚至更大的词典。这里使用10000个单词大小的词典构造这个词典的一个方法是遍历你的训练集并且找到前10000个常用词,你也可以去浏览一些网络词典它能告诉你英语里最常用的10000个单词
这是个监督学习给定带有(x,y)标签的数据。还有一点如果你遇到了一个不在你的词典中的单词,答案就是创建一个新的标记,Unknown Word的伪造单词,用作为标记来表示不在词典中的单词。我们之后会讨论更多有关这个的内容
1.3 循环神经网络
建立一个神经网络来学习X到Y的映射
为什么不能使用标准神经网络?
把9个输入单词可能是9个one-hot向量输入标准神经网络,经过一些隐层最后会输出9个值为0或1的项,它表明每个单词是否是人名的一部分,但结果表明这个方法并不好
主要有两个问题
一:输入和输出在不同的例子里可以有不同的长度,即便每个句子都有最大长度也许你能填充(pad)或零填充使每个输入句子都达到最大长度但仍然看起来不是一个好的表达方式
二:这个问题可能更严重,就是标准神经网络它并不共享从文本的不同位置上学到的特征比如如果神经网络已经学习到了在位置1出现的Harry可能是人名的一部分,那么如果Harry出现在其他位置比如
X
<
t
>
X^{<t>}
X<t>时它也能自动识别其为人名的一部分就很棒了。
这可能类似于你在卷积神经网络中看到的你希望部分图片里学到的内容快速推广到图片的其他部分,而我们希望对序列数据也有相似的效果,和你在卷积网络中学到的类似,用一个更好的表达方式也能够让你减少模型中的参数数量。这些
X
<
t
>
X^{<t>}
X<t>都是10000维的one-hot向量因此这会是一个十分庞大的输入层,如果总的输出大小是最大单词数乘以10000,那么第一层的权重矩阵就会有着巨量的参数。而循环神经网络就没有这两个缺点
如果你以从左到右的顺序读这个句子,第一个单词就是
X
<
1
>
X^{<1>}
X<1>,把它输入网络,输出一个
y
^
<
1
>
\hat{y}^{<1>}
y^?<1>判断是否是人名的一部分,循环神经网络做的是当它读到句中的第二个单词,假设是
X
<
2
>
X^{<2>}
X<2>,它不仅仅是用
X
<
2
>
X^{<2>}
X<2>预测出
y
^
<
2
>
\hat{y}^{<2>}
y^?<2>它也会输入一些来自时间步1的信息,具体而言时间步1的激活值就会传递到时间步2
在每一个时间步中循环神经网络传递一个激活值到下一个时间步中。要开始整个流程我们在零时刻需要编造一个激活值
a
<
0
>
a^{<0>}
a<0>这通常是零向量,有些研究人员会随机用其他方法初始化
a
<
0
>
a^{<0>}
a<0>不过使用零向量作为零时刻的伪激活值是最常见的选择。在一些研究论文或一些书中,你会看到下面这种表示
为了表示循环连接,画了一个圈,黑色方块处会延迟一个时间步。但这种循环图很难理解,所以本文画图更倾向于使用上面的分步画法
循环神经网络是从左向右扫描数据,同时每个时间步的参数也是共享的,用
W
a
x
W_{ax}
Wax?来表示管理着从X^{<1>}到隐藏层的连接,每个时间步使用的都是相同的参数
W
a
x
W_{ax}
Wax?,而激活值也就是水平联系是由参数W_{aa}决定的,同时每一个时间步都使用相同的参数
W
a
a
W_{aa}
Waa?,同样的,输出结果由
W
y
a
W_{ya}
Wya?决定.后面会详细的介绍这些参数怎么起作用的
在这个循环神经网络中它的意思是在预测
y
^
<
3
>
\hat{y}^{<3>}
y^?<3>时,不仅要使用
X
<
3
>
X^{<3>}
X<3>的信息还要使用来自
X
<
1
>
X^{<1>}
X<1>和
X
<
2
>
X^{<2>}
X<2>的信息
在这个循环神经网络的一个缺点就是它只使用了这个序列中之前的信息来做出预测,对于预测
y
^
<
3
>
\hat{y}^{<3>}
y^?<3>来说没有使用后面X{<4>}$,X^{<5>}$,X{<6>}$…的信息,所以这就有一个问题
你想要判断Teddy是否是人名,只给前三个单词是不可能确切的知道Teddy是否是人名的一部分。所以这个特定的神经网络的限制是它在某一时刻的预测仅使用了从序列中之前的 输入信息并没有使用序列中后部分的信息。我们会在之后的双向循环神经网络(BRNN)中解决这个问题(只要在此基础上作出修改就能同时使用序列中前面和后面的信息)
接下来具体看看这个神经网络计算了些什么
W
a
x
W_{ax}
Wax?第二个下标意味着
W
a
x
W_{ax}
Wax?要乘以某个x类型的量,然后这个a的意思是它是用来计算某个a类型的量的。
循环神经网络用的激活函数经常是选用tanh,不过有时候也会用ReLU,虽然tanh是更通常的选择我们有其他方法来避免梯度消失问题,将在之后进行讲述。选用哪个激活函数是取决于你的输出y,如果它是一个二分类问题,你可能会用sigmoid函数作为激活函数,如果是k分类问题那么可以选用softmax作为激活函数。对于这里的命名实体识别y只可能是0或1,所以激活函数可以是sigmoid函数
所以这些等式定义了神经网络的前向传播。为了构建更加复杂的网络,我们需要简化一些符号
假设a的维度是100
因此
这种记法的好处是我们可以不使用两个参数矩阵W_aa和W_ax而是将其压缩成一个参数矩阵W_a,所以当我们建立更复杂模型的时这就能简化我们使用的符号。
y
^
<
t
>
\hat{y}^{<t>}
y^?<t>的式子也会简化
现在
W
y
W_y
Wy?和
b
y
b_y
by?符号仅有一个下标,它表示计算时会输出什么类型的量,
W
y
W_y
Wy?和
b
y
b_y
by?就表示它是计算y类型的量的权重矩阵
1.4 通过时间的反向传播
当你在编程框架中实现循环网络时,编程框架通常会自动的处理反向传播,但是在循环网络中对反向传播的运行有一个粗略的认识还是非常有用的
反向传播于前向传播基本上是相反的,先分析一下前向传播的计算
根据x{<1>}$和a^{<0>}$计算出时间步1的激活项,再用x{<2>}
和
a
<
1
>
和a^{<1>}
和a<1>计算出a^{<2>}$,当然你还需要一些参数
W
a
,
b
a
W_a, b_a
Wa?,ba?每个时间步都会被用到。所有的这些激活项最后都要取决于参数
W
a
,
b
a
W_a, b_a
Wa?,ba?。有了激活项就可以计算
y
^
\hat{y}
y^?,为了计算
y
^
\hat{y}
y^?你需要参数W_y,b_y
为了计算反向传播 你还需要一个损失函数
y
<
t
>
y^{<t>}
y<t>如果它是某个人的名字那么
y
<
t
>
y^{<t>}
y<t>=1,神经网络输出
y
^
<
t
>
\hat{y}^{<t>}
y^?<t>(这个词是名字的概率值)比如0.1
在之前的文章中已经介绍了反向传播,所以你应该能想到反向传播算法需要在相反的方向上进行计算和信息传递,最终你要做的就是红色箭头
这样你就可以计算出所有合适的量,然后就可以通过导数进行梯度下降。
目前你见识了输入和输出序列长度相同,下面会介绍更多的RNN架构,能让你处理更加广泛的应用
1.5 不同类型的循环神经网络
事实上有些应用的T_x不一定等于T_y。比如电影评价“there is nothing to like in this movie” 所以x 是一个序列而y可能是从1到5的一个数字(你认为电影是1星还是2星等)或者是0或1(正面评价和负面评价)。
我们不再在每个时间上都有输出了而是让这个RNN网络读入整个句子,然后在最后一个时间上得到输出,这样输入就是整个句子。所以这个网络是 多对一 结构
除了上面结构,还有 一对多 的结构比如音乐生成
x可以是一个整数表示你想要的音乐类型或者是你想要的音乐的第一个音符,并且如果你什么都不想输入可以设为0向量
还有一种many to many 但是输入序列和输出序列长度不同,比如机器翻译中英文翻译
总结
one to many(音乐生成或序列生成) ;many to one (电影评论打分);many to many (Tx = Ty)命名实体识别;many to many (Tx!=Ty)机器翻译。用这些基础的RNN模块组合在一起就可以构造各种各样的模型
1.6 语言模型和序列生成
在自然语言处理中构建语言模型是最基础的也是最重要的工作之一
NLP需要一个很大的语料库,如果你在训练集中得到一个文体 Cat average 15 hours of sleep a day.你首先要做的就是将这个句子标记化,比如像之前一样建立一个字典进行one-hot编码,你还需要定义句子的结尾,常用的做法是怎加一个额外的标记< EOS >表示一个句子什么时候结束。
如果有的单词你的词典(比如你的词典只有10000个常用词)中没有就用< UNK >代替
将输入的句子编码后,然后构建一个RNN模型来构建这些序列的概率模型
在第0个时间步,
a
<
1
>
a^{<1>}
a<1>会通过softmax进行预测来计算第一个词可能是什么,其结果就是
y
<
1
>
y^{<1>}
y<1>,其实就是预测字典中每个词是句子第一个词的概率,这里字典有10000个词 ,所以softmax可能有10002个输出(加上< EOS> 和 < UNK>)在这个例子中
y
<
1
>
y^{<1>}
y<1>是cat。
然后RNN进入下一个时间步,会把第一步得到的结果
y
<
1
>
y^{<1>}
y<1>=cat输入,也就是
x
<
2
>
x^{<2>}
x<2>=
y
<
1
>
y^{<1>}
y<1>,然后
y
<
2
>
y^{<2>}
y<2>是在
y
<
1
>
y^{<1>}
y<1>=cat的情况下字典中
y
<
2
>
=
y^{<2>}=
y<2>=每个词的概率
最终得到
y
<
9
>
y^{<9>}
y<9>的值,我们希望p(< EOS> | cats average …)的概率最大
所以在RNN的每一步都会考虑前面得到的单词,比如给出前三个词,让它给出下个词的分布
接下来为了训练网络需要定义代价函数
1.7 新序列采样
在训练一个序列模型后要想了解这个模型学到了什么,一种非正式的方法就是进行新序列采样
一个序列模型模拟了任意特定单词序列的概率,我们要做的就是对这个概率分布进行采样 来生成一个新的单词序列
根据
y
<
1
>
y^{<1>}
y<1>的预测概率进行采样,比如如果
y
<
1
>
y^{<1>}
y<1>=[0.5,0.3,0.2] 通过np.random.choice(),如果运行一百次,50次取0.5代表的结果,30次取0.3代表的结果,20次取0.2代表的结果。
这样在同一个输入的情况下,会有不同的结果。
你也可以构建基于字符的RNN,如下
在之前的例子中
y
<
1
>
y^{< 1>}
y<1>=C,
y
<
2
>
y^{< 2>}
y<2>=a,
y
<
3
>
y^{< 3>}
y<3>=t,
y
<
4
>
y^{< 4>}
y<4>=空格。这样做的优点就是不用担心会出现未知的标识,因为字符序列模型会将jkkl这样不是单词的序列也视为可能性非零的序列(基于词汇的序列模型字典中没有的单词就会标记为< UNK>),字符序列缺点就是运算量很大,而且在捕捉句子中的依赖关系不如字典序列模型。
1.8 带有神经网络的梯度消失
基本的RNN有一个很大的问题就是梯度消失。
这两个句子有长期的依赖,cat…was ; cats…were,但是我们目前见到的基本RNN模型不擅长捕捉这种长期依赖。因为L(层数)很深的时候梯度是很难传播回去的,很难影响前面层的计算
这就意味着很难让一个神经网络记住看到的单词是单数还是复数,然后在序列后面生成依赖单复数形式的was和were.
我们知道神经网络层数过多时,会产生梯度爆炸和梯度消失,事实上梯度消失是RNN训练的首要问题,因为梯度爆炸很明显,因为指数级大的梯度会使你的参数变得极其大以至于网络参数崩溃,你会看到很多NaN或者不是数字的情况,这意味着你的网络计算出现了数值溢出,如果你发现了梯度爆炸,一种解决方法就是梯度修剪(当你的梯度向量大于某个阈值缩放梯度向量保证它不会太大)这就是通过一些最大值来修剪的方法。
然而梯度消失的问题更难解决,下面会介绍GRU门控循环单元网络,这个网络可以有效的解决梯度消失问题并且使神经网络能捕捉更长的长期依赖
1.9 GRU单元
下面会介绍门控循环单元,它改变了RNN的隐藏层使其可以更好的捕捉深层连接 并改善了梯度消失问题。寻常的RNN单元如下图
上一个时间步的激活值
a
<
t
?
1
>
a^{< t-1>}
a<t?1> 和
x
<
t
>
x^{< t>}
x<t>经过激活函数tanh 算出激活值
a
<
t
>
a^{< t>}
a<t>,然后激活值
a
<
t
>
a^{< t>}
a<t>将会传递给softmax或者其他 产生输出
y
<
t
>
y^{< t>}
y<t>的东西。
下面我们看看门控循环单元有何不同
之前你已经见过这个句子,你需要记住cat是单数,所以是was而不是were,当我们从左往右读这个句子,GRU单元会有一个新的变量c(记忆细胞)提供了记忆的能力,比如一只猫是单数还是复数,所以当它看到之后的句子的时候它仍能判断句子的主语是单数还是复数。于是记忆细胞在时间t处的值是
c
<
t
>
c^{< t>}
c<t>,GRU实际上输出了激活值
a
<
t
>
a^{< t>}
a<t>这等于
c
<
t
>
c^{< t>}
c<t>的值,于是我们想要用不同的符号c和a表示来记忆细胞的值和输出的激活值,即使它们是一样的,现在使用这个标记是因为接下来的LSTM这两个符号代表两个不同的值,但是对于GRU
c
<
t
>
c^{< t>}
c<t>的值等于
a
<
t
>
a^{< t>}
a<t>
在每个时间步我们将用一个候选值
c
~
<
t
>
\tilde{c}^{< t>}
c~<t>重新记忆细胞,我们用tanh激活函数来计算
所以
c
~
<
t
>
\tilde{c}^{< t>}
c~<t>的值就是个替代值。在GRU中真正重要的思想是我们有一个门 这是一个0到1之间的值,为了直观理解GRU的工作机制sigmoid函数的输出总在0-1之间,大多数情况下的输出都是非常接近0或者1的,在这样的直觉下可以想到在大多数情况下非常接近0或1
然后GRU的关键部分就是
c
~
<
t
>
\tilde{c}^{< t>}
c~<t>更新
c
<
t
>
c^{< t>}
c<t>的等式,然后门决定是否要真的更新它,于是我们这么看待它,记忆细胞被设定为0或1这取决于你考虑的单词在句子中是单数还是复数,比如单数设定为1,然后GRU单元会一直记住
c
<
t
>
c^{< t>}
c<t>的值
一直到was这里
c
<
t
>
c^{< t>}
c<t>还是1, 这就告诉它这是单数,所以我们用was,于是门的作用就是决定什么时候你会更新这个值,特别是当你看到词组the cat,即句子的主语猫,你知道在说一个新的概念,这就是一个好的时机去更新这个bit,然后当你使用它的时候,猫什么的吃饱了然后好了不需要记住它了,可以忘记它了。
所以我们接下来要GRU用的式子就是
你应该注意到了 如果门等于1,就把候选值
c
~
<
t
>
\tilde{c}^{< t>}
c~<t>设为
c
<
t
>
c^{< t>}
c<t>,把门设为1然后往前再更新这个值,对于所有在这中间的值,你应该把门的值设为0,意思就是不更新它,就用旧的值(如果门为0,那么
c
<
t
>
c^{< t>}
c<t>=
c
<
t
?
1
>
c^{< t-1>}
c<t?1>) 甚至你从左往右扫描这个句子时就是不更新它的值也不要忘记这个值是什么,这样即使你处理到句子的was处
c
<
t
>
c^{< t>}
c<t>一直等于
c
<
t
?
1
>
c^{< t-1>}
c<t?1>于是它仍然记得猫是单数的
下面画图来解释以下GRU单元
这就是GRU单元 ,它的优点就是通过门决定当你从左到右扫描一个句子的时候,这个时机是要更新某个记忆细胞还是不更新, 直到你使用记忆细胞的时候。这可能在句子之前就决定了因为sigmoid的值,现在因为门很容易取到0,
只要绿线部分是一个很大的负数,再四舍五入上面这些门的值就大体上是0,非常接近0,所以在这种情况下
c
<
t
>
c^{< t>}
c<t>的更新式子就会变成
c
<
t
>
c^{< t>}
c<t>=
c
<
t
?
1
>
c^{< t-1 >}
c<t?1>,这非常有利于维持记忆细胞的值,因为门的值接近0,这就不会有梯度消失的问题了,因为门的值非常接近0,这就是说
c
<
t
>
c^{< t>}
c<t>几乎等于
c
<
t
?
1
>
c^{< t-1 >}
c<t?1>,而
c
<
t
>
c^{< t>}
c<t>的值也很好的被维持了即使经过很多很多很多的时间步,这就是缓解梯度消失的关键。因此允许神经网络运行在非常庞大的依赖词上,比如cat和was单词即使被中间的很多单词分开。
接下来说一些实现的细节,
c
<
t
>
c^{< t>}
c<t>可以是一个向量,如果你有100维的隐藏的激活值那么
c
<
t
>
c^{< t>}
c<t>也是100维的,
c
~
<
t
>
\tilde{c}^{< t>}
c~<t>也是,门也是。*就是对应元素的乘积,乘积要做的就是告诉GRU单元哪个记忆细胞的向量维度在每个时间步需要更新,所以可以选择保持一些位不变,去更新其他位,比如说你可能需要一位(bit)来记忆猫是复数还是单数,其他bits来理解你正在讨论的食物因为你在谈论吃饭或食物,然后你可能会讨论到猫是否是四个单词,你可以每个时间点只改变一些bits
上面讨论的是简化后的GRU,下面看一下完整的GRU单元
这里有一个新的门r,你可以认为r代表相关性,这个门告诉你下一个
c
<
t
>
c^{< t>}
c<t>跟
c
<
t
?
1
>
c^{< t-1>}
c<t?1>有多大的相关性。正如你所见有很多方法可以设计这些类型的网络,为什么用门r,为什么不用简易版,这是多年实验的结果。你也可以尝试发明新版本的单元。还有另一个常用的版本LSTM(长短期记忆网络),GRU和LSTM是在神经网络结构中最常用的两个具体实例
1.10 长短期记忆
LSTM长短期网络其实是在GRU之前出现的,下面看看GRU和LSTM的不同
左侧是GRU,由两个门构成,更新门u 和相关门 r ,右侧是LSTM,LSTM是一个比GRU更加强大和通用的版本,在LSTM中
c
<
t
>
c^{< t>}
c<t>不等于
a
<
t
>
a^{< t>}
a<t>
可以发现多了一个f门,所以这给了记忆细胞选择权去维持旧的值
c
<
t
?
1
>
c^{< t-1>}
c<t?1>或者就加上新的值
c
~
<
t
>
\tilde{c}^{< t>}
c~<t>,所以这里用了单独的更新门u和遗忘门f。最后
a
<
t
>
a^{< t>}
a<t>的值等于输出门的值(o)元素对应乘积
c
<
t
>
c^{< t>}
c<t>
下面用图片稍微解释一下,其实公式比图片更好理解
? 如果你把几个时间步连起来就会发现
最上面的这条红线显示了只要你正确的设置了遗忘门和更新门,LSTM是相当容易把
c
<
0
>
c^{< 0>}
c<0>的一直往下传递到右边,比如
c
<
3
>
c^{< 3>}
c<3>=
c
<
0
>
c^{< 0>}
c<0>.这就是为什么LSTM和GRU非常擅长处理长时间记忆的某个值。
如你所见LSTM主要的区别在于一个技术上的细节,比如这有一个100维的向量,你有一个100维的隐藏的记忆细胞单元,然后比如第50个
c
<
t
?
1
>
c^{< t-1>}
c<t?1>的元素,只会影响第50个元素对应的那个门,所以关系是一对一的 ,于是并不是任意这100维的
c
<
t
?
1
>
c^{< t-1>}
c<t?1>可以影响所有的门元素,第一个
c
<
t
?
1
>
c^{< t-1>}
c<t?1>只能影响门的第一个元素 。
1.11双向神经网络
现在你已经了解了大部分RNN模型的关键构件,还有两个方法可以让你构建更好的模型,其中之一就是双向RNN网络。先看下面这两个句子
仅凭借前三个单词是无法判别Teddy是小熊还是人名,因此普通的RNN不能很好的处理这个问题。这就需要BRNN,为了简便,我们假设只有四个输入
这是我们之前见过的基础的RNN网络,下面我们需要增加反向循环层
给定一个输入序列
x
<
1
>
x^{< 1>}
x<1>到
x
<
4
>
x^{< 4>}
x<4>,这个序列首先计算前向的
a
<
1
>
a^{< 1>}
a<1>,然后计算
a
<
2
>
a^{< 2>}
a<2>…
a
<
4
>
a^{< 4>}
a<4>,而反向序列从
a
<
4
>
a^{< 4>}
a<4>开始,反向计算
a
<
3
>
a^{< 3>}
a<3>,
a
<
2
>
a^{< 2>}
a<2>,
a
<
1
>
a^{< 1>}
a<1>,你计算的是网络激活值,这不是反向传播而是前向传播,图中的前向传播一部分计算是从左到右,一部分计算是从右到左。把这些值都计算完了就可以计算预测结果了。
注意图中的神经单元不仅可以是基础的RNN单元,也可以是LSTM单元或GRU单元。
这个BRNN的缺点就是你需要完整的数据的序列,才能预测任意位置,如果你要构建语音识别系统,那么BRNN模型需要考虑整个语音表达,必须等这个人说完,获取整个语音表达 ,才能处理这段语音,并进一步做到语音识别。对于实际的语音识别应用通常会有更加复杂的模块
1.12深层循环神经网络
左侧是普通的深层神经网络,有的可能有100层,右侧是深层循环神经网络,一般最多三层,因为有时间维度,RNN网络会变得非常大。你可能还会见到一种类型,
在每一个上面堆叠循环层。这些层并不水平连接只是一个很深的网络。
而且图中的这些单元不一定必须是最简单的标准RNN单元,也可以是GRU或LSTM单元。而且你也可以构建深层的双向RNN网络
|