李宏毅ML+DL学习记录:RNN

        引例:在买车票时,我们希望有一个网络,当我们说出“I would like to arrive at Taipei on November 2nd”时,它能判断出我们的目的地是Taipei,希望到达的时间是November 2nd.
        我们把这称之为slot filling,这里的两个slot就是destination 和time of arrival。其实这个问题用一般的神经网络也能判断出Taipei是destination、November 2nd是time of arrival,但是如果你说的是‘I would like to leave Taipei on November 2nd,那么它还是会认为Taipei是destination,所以这样一来,一般的前馈神经网络就不怎么好了,NN needs memory!(需要NN记住前面是leave还是arrive)

一.RNN

1.RNN的前向传播

在这里插入图片描述
        蓝色的a1、a2就是用来存储记忆的。打了红色圈圈的线表示weight。在这个例子中我们假设这个RNN已经训练好了,所有激活函数都是线性的,所有的weight都是1,a1、a2的初始值都是0,我们来看看RNN是如何运作的。
在这里插入图片描述
        设第一个输入是[1,1],左边这个2是怎么来的呢?1 * w1+1 * w3+0 * w6+0 * w8=2;右边的2也是同样的思路,hidden layer(也就是图中的绿色)变成2,2之后,就把值存储在a1,a2中,所以a1,a2变成了2,2;然后继续向前:左边的4=2 * w10+2 * w12,右边的4也是同样的思路;这样第一个输入[1,1],输出就是[4,4]了。
在这里插入图片描述
        第二个输入仍然是[1,1],左边的6=1 * w1+1 * w3+2 * w6+2 * w8,右边同样道理;hidden layer变成6、6之后,把6、6存储到a1、a2中,所以a1、a2变成了6、6;继续向前,左边的12=6 * w10+6 * w12,右边的12也是同样的思路;这样第二个输入[1,1],输出就是[12,12]了。
        以上就是RNN运作的步骤,接下来看一下RNN在我们之前的那个引例上是如何工作的:
在这里插入图片描述
        我们假设激活函数还是线性的(只是为了这里方便演示),则
        a1 = x1* w1+a0* w2,y1 = a1* w3;
        a2 = x2* w1+a1* w2,y2 = a2* w3…
在这里插入图片描述
        可以看出,由于x1不一样(一个是leave,一个是arrive),所以两个a1是不一样的,所以y2就不一样,所以arrive和leave的Taipei就能被区别出。
在这里插入图片描述
        深层的RNN就是上面这幅图这样。

        双向的RNN如上图所示。单向的RNN只考虑了t时刻前面的信息,没有考虑t时刻之后的信息,双向RNN解决了该问题。

2.RNN的训练

        我们刚刚在讲前向传播的时候,是假定我们的RNN已经训练好,各参数已经固定了,那么本小节就要讨论一下RNN的训练。
        其实RNN的训练和一般前馈神经网络的训练方法的思想基本是一致的,也是BP(back propagation),不过由于RNN是对时间序列的处理,所以要基于时间反向传播,因此RNN的训练方法叫‘随时间反向传播’(back-propagation through time)。
在这里插入图片描述
        还是以这幅图为例,由图可以看出,我们要训练的参数有3个w1、w2、w3(这3个其实应该看成参数矩阵,但这里为了简便,就当做是scalar了)。之前在前向传播时为了方便,假设激活函数都是线性的,那么这里我们就要稍微正式一点,我们设输入层到隐藏层的激活函数是f1,隐藏层到输出层的激活函数是f2。那么就有:
        ai = f1(w1* xi+w2* ai-1)
        yi’ = f2(w3* ai) = f2[w3* f1(w1* xi+w2* ai-1)]
        所以loss function:
        L=∑(yi-yi’)2
         =∑( yi-f2(w3* ai))2
         =∑( yi-f2[w3* f1(w1* xi+w2* ai-1)] )2

        那么L对w3的偏导就是:

在这里插入图片描述
        然后大家对w1、w2稍微算一下偏导,就会发现这两个参数的寻优过程需要追溯之前的历史数据(反正就是有点麻烦),这里就不再赘述,直接看下图:
在这里插入图片描述
        这里Li表示(yt-yt’)2 (即i时刻输出的loss)
        ∂Li/∂W1,只是其中一个时间点的损失函数,整体的损失函数还要将所有的 ti都相加起来。∂Li/∂W2也是同样的道理。

        但在实际试验中RNN的训练效果并不是很好(见下图):
在这里插入图片描述
        出现绿色这条线是因为the error surface is rough,也就是total loss关于参数的图像很崎岖,如下图所示:
在这里插入图片描述
        当参数在点1的时候,loss对w1、w2的gradient都比较小,所以做一次更新之后,参数由点1移动到点2,参数更新后loss值稍微有点下降;在点2时,loss对w1、w2的gradient也比较小,做一次更新之后,我们分两种情况讨论:
        1)移动到点3,参数更新后loss值稍微有点下降;但是下一次更新时,由于在点3,loss对参数的gradient异常地大,所以更新后的参数的绝对值也非常地大(像图片上那样,直接起飞)
        2)移动到点4(其实点3和点4在参数值上非常接近,只是loss值差别比较大),loss值反而变大。
        那么为什么error surface会崎岖呢?我们以下图来看:
在这里插入图片描述
        假设最开始时,w1、w3都是1,第一个输入是1,其他输入都是0,我们想让y1000的输出是2.
在这里插入图片描述
        上面这幅图就展示出了RNN在训练过程中的两种问题:
        上面绿色这块展示了gradient explode(即w2只变化一点点,loss变化超大;loss变化超大,那么gradient就超大),也就是上上图点2到点4,或者点3到点4的情况;
        下面黄色这块展示了gradient vanish(即w2变化了,但loss貌似没有什么变化;loss没什么变化,那么gradient就极小,甚至趋于0,所以就叫gradient vanish)(PS:gradient反应的是w变化一单位,loss会变化多少)

        对于gradient explode,一般的处理方式是clipping,即当gradient超过一定值时,就把它拉回来,给它强行赋一个值。
        对于gradient vanish,一般的处理方式是使用LSTM结构。

二.LSTM

在这里插入图片描述
        我们首先来介绍这个special neuron,它有4个input:z,zi,zo,zf,一个output:a。
        zi,zo,zf经过激活函数之后(即f(zi)、f(zo)、f(zf)),变成了signal that controls input gate/output gate/forget gate.激活函数一般选择sigmoid函数,则f(zi)、f(zo)、f(zf)就是0~1之间的数了。
        图中蓝色的c代表目前这个special neuron所含有的信息(也就相当于memory),g(z)表示想要传入到这个special neuron中的信息;
        f(zi) * g(z)就表示实际能传入到这个special neuron中的信息(f(zi)表示input gate ,取值为1表示新信息全部流入,取值为0,表示新信息完全不能流入);
        c * f(zf)表示原来的信息能保留多少(f(zf)代表forget gate(其实我觉得理解成remember gate更好一点),取值为1,表示原来的信息能完全保留,取值为0表示原来的信息全部不保留);
        所以c’ = c * f(zf) + f(zi) * g(z) 就代表这个special neuron经过一次输入之后所含的信息;
        h(c’)就表示这个special neuron想要传递出去的信息;
        a=f(zo) * h(c’)表示这个special neuron实际能传递出去的信息(f(zo)代表output gate,取值为1,代表想传出去的信息能全部传出去,取值为0代表想传出去的信息完全不能传出去)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
        下面就来正式介绍LSTM:
在这里插入图片描述
        ct-1就相当于刚刚special neuron里面的c,
        ct相当于c’,
        ht相当于special neuron里的a,
        yt = σ(W * ht).
        而z,zi,zo,zf是由c、h、x合起来,然后分别乘以W1、W2、W3、W4所得到的(即z,zi,zo,zf的每一个都是由c、h、x共同得来的)。
        那么LSTM为什么能较为有效地处理gradient vanish的问题呢?
        前面的简单RNN出现gradient vanish 是因为前面信息向后面传递的比率不断连乘(即当w2小于1时,通过不断连乘,最终∂ai / ∂at的结果大概率会很小,甚至接近于0),即下图:
在这里插入图片描述
        而LSTM中,前面的信息向后面传递时,由于用到了input gate 、output gate和forget gate,所以∂Ct / ∂Ct-1(相当于简单RNN中的∂ai / ∂ai-1)是四个部分相加组成的
在这里插入图片描述
        这四部分都很小的概率,比RNN中w2小于1的概率小很多,所以这四部分相加再连乘,所得的结果接近0的概率也就变小了。(这也从另一方面说明,LSTM只是缓解了梯度消失的问题,并没有完全解决。)

发布了43 篇原创文章 · 获赞 1 · 访问量 732

猜你喜欢

转载自blog.csdn.net/weixin_41391619/article/details/104589923
今日推荐