在这篇文章中,我们介绍一下其他的RNN。
一.深层RNN
循环神经网络的架构是可以任意设计的,之前提到的 RNN 只有一个隐藏层,但 RNN 也可以是深层的。比如把 xt 丢进去之后,它可以通过一个隐藏层,再通过第二个隐藏层,以此类推 (通过很多的隐藏层) 才得到最后的输出。
每一个隐藏层的输出都会被存在记忆元里面,在下一个时间点的时候,每一个隐藏层会把前一个时间点存的值再读出来,以此类推最后得到输出,这个过程会一直持续下去。
二. Elman 网络 &Jordan 网络
循环神经网络会有不同的变形,如下图所示,刚才讲的是简单循环网络(Simple Recurrent Network,SRN),即把隐藏层的值存起来,在下一个时间点在读出来。
Jordan 网络存的是整个网络输出的值,它把输出值在下一个时间点在读进来,把输出存到记忆元里。Elman 网络(简单循环网络也称为 Elman 网络)没有目标,很难控制说它能学到什么隐藏层信息(学到什么放到记忆元里),但是 Jordan 网络是有目标,比较很清楚记忆元存储的东西。
三. 双向循环神经网络
循环神经网络还可以是双向。
刚才 RNN 输入一个句子,它就是从句首一直读到句尾。如下图所示,假设句子里的每一个单词用 xt 表示,其是先读 xt,再读 xt+1、xt+2。
但其读取方向也可以是反过来的,它可以先读 xt+2,再读 xt+1、xt。我们可以同时训练一个正向的循环神经网络,又可以训练一个逆向的循环神经网络,然后把这两个循环神经网络的隐藏层拿出来,都接给一个输出层得到最后的 yt。所以把正向的网络在输入 xt 的时候跟逆向的网络在输入 xt 时,都丢到输出层产生 yt,产生 yt+1, yt+2,以此类推。
双向循环神经网络(Bidirectional Recurrent Neural Network,Bi-RNN)的好处是,神经元产生输出的时候,它看的范围是比较广的。
如果只有正向的网络,再产生 yt、yt+1 的时候,神经元只看过 x1 到xt+1的输入。但双向循环神经网络产生yt+1的时候,网络不只是看过x1,到xt+1所有的输入,它也看了从句尾到xt+1的输入。网络就等于整个输入的序列。
假设考虑的是槽填充,网络就等于看了整个句子后,才决定每一个单词的槽,这样会比看句子的一半还要得到更好的性能。
四、长短期记忆网络
最常用的记忆元是长短期记忆网络(Long Short-Term Memory network,LSTM),长时间
的短期记忆(之前的循环神经网络,它的记忆元在每一个时间点都会被洗掉,只要有新的输入进来,每一个时间点都会把记忆元洗掉,所以的短期是非常短的,但如果是长时间的短期记忆元,它记得会比较久一点,只要遗忘门不要决定要忘记,它的值就会被存起来)。
LSTM 是比较复杂的。LSTM 有三个门(gate),当外界某个神经元的输出想要被写到记忆元里面的时候,必须通过一个输入门(input gate),输入门要被打开的时候,才能把值写到记忆元里面。如果把这个关起来的话,就没有办法把值写进去。
输入门的开关是神经网络自己学的,其可以自己学什么时候要把输入门打开,什么时候要把输入门关起来。
输出的地方也有一个输出门(output gate),输出门会决定外界其他的神经元能否从这个记忆元里面把值读出来。把输出门关闭的时候是没有办法把值读出来,输出门打开的时候才可以把值读出来。跟输入门一样,输出门什么时候打开什么时候关闭,网络是自己学到的。
第三个门称为遗忘门(forget gate),遗忘门决定什么时候记忆元要把过去记得的东西忘掉。这个遗忘门什么时候会把存在记忆元的值忘掉,什么时候会把存在记忆元里面的值继续保留下来,这也是网络自己学到的。
整个 LSTM 可以看成有 4 个输入、1 个输出。在这 4 个输入中,一个是想要被存在记忆元的值,但不一定能存进去,还有操控输入门的信号、操控输出门的信号、操控遗忘门的信号,有着四个输入但它只会得到一个输出。
记忆元的对应计算公式:
如下图所示,下面这个是外界传入单元的输入,还有输入门、遗忘门和输出门。
假设要被存到单元的输入叫做 z,操控输入门的信号为 zi,操控遗忘门的信号为 zf,操控输出门为 zo,综合这些东西会得到一个输出记为 a。
假设单元里面有这四个输入之前,它里面已经存了值 c。输出 a 会长什么样子呢,把 z 通过激活函数得到 g(z),zi 通过另外一个激活函数得到 f(zi) (激活函数通常会选择 sigmoid 函数),因为其值介在0到1之间的(sigmoid函数不清楚的可以去看之前的文章),这个0到1之间的值代表了这个门被打开的程度。(如果 f 的输出是1,表示为被打开的状态,反之代表这个门是关起来的)。
把 g(z) 乘以 f(zi) 得到 g(z)f(zi),对于遗忘门的 zf,也通过 sigmoid 的函数得到f(zf)
接下来把存到记忆元里面的值 c 乘以 f(zf) 得到 c f(zf),加起来 c′= g(z)f(zi)+cf(zf),那么 c′ 就是重新存到记忆元里面的值。所以根据目前的运算,这个 f(zi) 控制这个 g(z)。
假设输入 f(zi)=0,那 g(z)f(zi) 就等于 0,就相当于没有输入,如果 f(zi) 等于 1 就等于是把 g(z) 当做输入。
那这个 f(zf ) 决定是否要把存在记忆元的值洗掉,假设 f(zf ) = 1,遗忘门开启的时候,这时候 c 会直接通过,把之前的值还会记得。
如果 f(zf) = 0(遗忘门关闭的时候) cf(zf ) 等于 0。
然后把这个两个值加起来 (c′= g(z)f(zi) + cf(zf)) 写到记忆元里面得到c′。这个遗忘门的开关是跟直觉是相反的,遗忘门打开的时候代表的是记得,关闭的时候代表的是遗忘。
那这个 c′ 通过 h(c′),将 h(c′) 乘以 f(zo) 得到 a = f(c′f(zo))。
输出门受 f(zo) 所操控,f(zo) 等于 1 的话,就说明 h(c′) 能通过,f(zo) 等于 0 的话,说明记忆元里面存在的值没有办法通过输出门被读取出来。
在下一篇文章中我们再来详细探讨LSTM的原理。