有两个方法可以让你构建更好的模型,其中之一就是双向RNN模型,这个模型可以让你在序列的某点处,不仅可以获取之前的信息,还可以获取未来的信息;第二个就是深层的RNN,会在之后进行介绍。这里先介绍双向神经网络。
为了了解双向RNN的动机,我们先看一下之前在命名实体识别中已经见过多次的神经网络。给定两个句子:
“He said,“Teddy bears are on sale””
“He said,“Teddy Roosevelt was a great President””
这个网络有一个问题,在判断第三个词Teddy是不是人名的一部分时,光看句子前面部分是不够的。为了判断
y
^
<
3
>
\hat{y}^{<3>}
y^<3>是0还是1,除了前3个单词,还需要更多的信息,因为根据前3个单词无法判断他们说的是teddy熊还是前总统,所以这是一个非双向的或者说只有单向的RNN,这总是成立的,不管这些单元是标准的RNN块还是GRU单元,或者是LSTM,只要这些构建都是只有前向的。
那么一个双向的RNN是如何解决这个问题的,下面解释双向RNN的工作原理,为了简单说明,我们用一个只有4个单词的句子,这样输入只有4个。
给定一个输入
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
<
3
>
a^{<3>}
a<3>,你计算的是网络激活值,这不是反向而是前向的传播,而图中这个前向传播一部分计算是从左到右,一部分计算是从右到左,计算完反向的
a
<
3
>
a^{<3>}
a<3>,可以用这些激活值计算反向的
a
<
2
>
a^{<2>}
a<2>,然后是反向的
a
<
1
>
a^{<1>}
a<1>,把所有这些激活值都计算完了,就可以计算预测结果了。
举个例子,为了预测结果,你的网络会有 y ^ < t > = g ( W y [ a → < t > , a ← < t > ] + b y ) \hat{y}^{<t>}=g(W_y[\overrightarrow{a}^{<t>},\overleftarrow{a}^{<t>}]+b_y) y^<t>=g(Wy[a<t>,a<t>]+by)所以这就是双向循环神经网络,并且这些基本单元不仅仅是标准RNN单元,也可以是GRU单元或者是LSTM单元。
事实上,很多的NLP问题,对于大量有自然语言处理问题的文本,有LSTM单元的双向RNN模型是用的最多的。所以如果有NLP问题并且文本句子都是完整的,首先需要标定这些句子,一个有LSTM单元的双向RNN模型,有前向和反向过程,是一个不错的首选。
这个双向RNN网络模型的缺点就是你需要完整的数据的序列才能预测任意位置。比如说你要构建一个语音识别系统,那么双向RNN模型需要你考虑整个语音表达。如果直接用这个去实现的话,你需要等这个人说完,然后获取整个语音表达才能处理这段语音。并进一步做语音识别。对于实际的语音识别的应用,通常会有更加复杂的模块,而不是仅仅用我们见过的标准的双向RNN模型。
但是对于很多自然语言处理的应用,如果你总是可以获取整个句子,这个标准的双向RNN算法实际上很高效。