假如我们现在需要做一个句子翻译,"dog is beautiful",我们如果单独分开预测的话,不知道上下文的意思,会影响预测的value,但是如果连在一起,会很好“这段话有问题,后面再改”
于是我们就引入一个循环神经网络,在我预测下一个单词/动作/其他的时候,网络的参数是保留之前预测的特点!
1. RNN的结构和流程
直接上花书的图:
一开始是真的看不懂这个图,后面看了宝可梦训练大师的才知道怎么玩
譬如还是上面的三个单词,整个流程就是:
首先我先输入"cat"譬如是t-1时刻,进网络,然后在网络走一圈到输出
,这里期间会产生网络的隐藏状态(其实就是矩阵),也就是
有value了。
然后我们输入下一个单词进网络"is",此时是t时刻。但是这个时候,是和上一时刻的隐藏状态
一块输入到t时刻的网络里面进行,然后运算得到t时刻单词的对应输出
以及隐状态的值
最后就是"beautiful" 这个单词进去,和上面做同样的事情,也是拿上一时刻的隐藏状态的值和当前的输入一块送进去网络,得到输出。
上面的整个流程再细致一点就是:
在送单词进去网络的时候,我们先对单词做一个处理,因为网络肯定不知道是什么玩意儿,我们学到的就是onehot coding 将单词转化为一个向量X来表示。
然后这个向量X也不是直勾勾地送进去网络,得先做一些变换,就是 real_input = X*U,其中U是一个矩阵,暂且理解某些网络自己认为可以对输入做比较好的处理吧
然后就是计算隐藏状态的值了,输入就是,最后在做一次非线形变换就是当前时刻的隐藏层的值了(后面有代码)
然后就是输出了,也是还要乘一个矩阵去做处理:
以上就是整个RNN的流程了。
2. 一些小细节和代码
1. 注意这里面的V,W,U三个矩阵在每时每刻,都是他们都是共享的,也就是他们每个时刻t计算的时候都是用一样的哈。在每次做反向传播的时候都会更新这三个矩阵的values
2. RNN会造成梯度消失或者梯度爆炸,后面讲,其实就是用全链接的思维去考虑就好了
3. 看一些博客就很迷,RNN的隐藏状态只有一层,代码里确实也确实只有一层,但是我觉得可以有多层,也就是在同一时刻有这么多个隐藏状态在里面,隐藏状态之间也是像只有一个隐藏状态那样先计算output,然后再把整个output作为下一个隐藏状态的input。
3. 为什么会出现 梯度消失/ 梯度爆炸
我们就拿三个序列来说:
而某个时刻t,当前网络的损失函数,其实是截止当前t时刻,从0-t所有时刻的损失函数总和,也就是,而我们知道越往后的时刻,它自己的loss就叠加了越多的以前的loss
上面这个式子的其实是我们说的U,V,W三个矩阵,还有对应bias。
其中,中间那一项是t时刻隐藏层对t-1时刻隐藏层的求导,结果就是
所以我们也可以看出来,当某一时刻的梯度非常异常 ,要么就是tanh小了,要么就是W大了。所以,会造成梯度爆炸,梯度消失。
也就是换句话说,当连乘的东西一多了,就非常容易造成梯度消失/爆炸了,也就是当前时刻譬如t=100,然后计算t=3的梯度,当我们求到t=3的连乘式时,一个不小心,就造成这个连乘式的结果等于0,也就是(t=3,t=2,t=1)这三个时刻对于t=20的参数更新的贡献都是0作用。
上面相当于分析,现在给出贡献0作用的大白话就是RNN并没有办法捕捉这种长期的依赖关系, 只能捕捉局部的依赖关系, 没法再捕捉序列之间的长期关联或者依赖关系。