深度学习——神经网络之RNN循环(递归)神经网络
- 神经网络之RNN循环(递归)神经网络)
- 1、什么是循环神经网络
- 2、RNN网络结构
- 3、RNN正向传播
- 4、RNN反向传播更新梯度
- 5、克服梯度消失和爆炸问题
- 6、Deep(Bidrectional)RNN
- 7、双向递归神经网络
神经网络之RNN循环(递归)神经网络)
1、什么是循环神经网络
我们之前学习了全连接神经网络DNN,还学了卷积神经网络CNN,为什么还需要RNN递归神经网络?有以下两种原因:
- BP神经网络和CNN神经网络的输入输出都是独立的。但是实际应用中的一些场景输出的内容和之前的内容是有关联性的。
- RNN引入了“记忆”的概念;递归指其每一个元素都指向相同的任务。但是输出依赖于输入的记忆。
什么意思?
DNN,CNN两种结构,这两种结构有一个共同的特点,就是我们给予模型的输入和输出,他是独立的,没有上下文的联系,我们在做语言任务,或者视频预测任务,问答系统的时候,输入的是一句话,输出的时候,是要考虑这句话里边的词语的先后顺序的。还例如我们做视频的预测输入的是每一帧的画面,加入此时输入的是以个张嘴的图片,那么是吃饭,还是唱歌,就要考虑上下图片,也就是说网络要有一定的 “记忆功能” 。这个时候RNN神经网络就产生了。)
2、RNN网络结构
我凑,这是什么鬼,好TM乱,我第一次看也是这种感觉。然后我看到了这个拉平以后的模型:
怎么拉平的呢?我们将序列按照时间展开,就会得到这个结构,看一下参数,以及各个参数的含义:
- Xt:时间 t 处的输入
- St:时间 t 处的记忆,
St = f(StU + WSt-1),f可以是非线性转换函数,比如tanh等- Ot:是时间 t 处的输入。
比如是预测下一个词的话,可能是sigmoid(或softmax)输出的属于每个候选词的频率,Ot = softmax(VSt)
例子:
假设输入:“预测下一个词”这句话,Xt=测,那么Xt-1=预,Xt+1=下,
但是这个词肯定不是输入的文字(词语 ),输入的是词向量,所以要先把测词转换成词向量。 后面会介绍到。
输出,如果是做分类任务,就看最后一个词的输出(在最后一个词的输出加上分类器),如果是序列标注(分词,命名实体识别,词性标注)就每个词的输出都要看,比如用维特比进行打分。
U,V,W是神经元要学习的参数,并且这个参数是每一时刻输出所共享的参数,就是说是同一个。
3、RNN正向传播
1、在 t = 0 时刻,U,V,W,都是被初始化好的,h0通常初始化为0,然后进行如下计算:
U,V,U都是矩阵,是反向传播需要训练的
x1是输入的字向量,或者词向量,不是汉子,要通过转换,变成一定维度的向量。
f,g都是激活函数。
2、时间向前推进,此时状态为h1,作为时刻0的记忆庄热爱将参与下一次的预测活动,也就是:
这一步的UVW与上一步是共享的。
3、依此类推可得
其中:
f 可以是:tanh,relu,logistic等
g 通常是softmax也可以是其他
我们所说的递归神经网络拥有记忆能力,这种记忆能力就是通过W,将以往的输入状态进行总结,而作为下次输入的辅助。
可以这样理解隐藏状态:
h = f(现有输入+ 过去记忆总结)
4、RNN反向传播更新梯度
前面提到U,V,W是共享的,也就是说UVW都是一套相同的,那么反向传播更细梯度的时候就是用最后的误差总和,反向计算每一时刻的梯度,计算到最后再更新UVW
要注意:
所有的输入都是在同一个网络上传递的,网络的层数之后一层(不超过2层),并不是一个时刻就是一层。这样才实现了不同时刻的参数共享。
对于每一个时刻t的RNN网络,网络的输出Ot都会产生一定的误差et,误差的损失函数可以是交叉熵,也可以是平方差误差等等,那么总的误差就是E = ∑tet,我们的目的就是求取:
得到梯度,就可以进行参数的更新。
再求梯度的时候,要注意依赖关系,U是直接和输出值相连的,比较好求,但是对于VW,不能直接求导,是符合函数求导,就要用链式求导法则。
推导:推到之前要注意,单层的RNN只有一组W,但是你求导的的时候反向传播要对不同时刻的W求导。最后在加在一起(有几部分就有及部分相加,并且后面的部分是相同的),之后我们会提到累加符号就是从这里来的
做文本分类任务(只有最后一个时刻有输出)
假设损失函数:mse
真实值 y
误差:e = 1/2 * (y-Ot+1)2
1、先推导前向传播(为了简便,这里不考虑激活函数)
ht-1 = U * xt-1 + ht-2 * W
ht = U * xt + ht-1 * W
ht+1 = U * xt+1 + ht * W
然后:
Ot+1 = ht+1 * V
2、更新V:
对V求梯度
再用梯度下降法更新V:V = V - lr * gred(V)
3、更新U
对U求梯度:(你就看上面的的前向传播那里边有U,都求然后相加)
再用梯度下降法更新U:U = U - lr * gred(U)
4、更新W
对W求梯度:
再用梯度下降法更新W:W = W - lr * gred(W)
5、将W整理成累加类乘的形式
6、多个输出任务时,就有多个输出y1,y2,y3…就有多个0,然后用总误差,去链式求导就可以啦。
综上所述,对于时刻t+1产生的误差et+1,我们想计算他对于w1,w2,……,wt,wt+1的梯度,计算如下:
反复计算,我们可以计算出每一个▽w1,▽w2,……,▽wt▽wt+1在不同时刻都是共享同样的参数。这样可以大大减少训练的参数,与CNN共享权重类似,对于共享参数的RNN,我们只需要将上述的式子抹去标签并求和,就可以得到:
其中:
表示不利用链式求导法则直接求导,
也就是说,假如对于函数 f((hx))对其直接求导结果如下:
也就是求导函数可以写成X的表达式,也就是将h(x)看成常数。
论文中http://proceedings.mlr.press/v28/pascanu13.pdf 证明了:
从而说明:
梯度求导的一部分环节是一个指数模型(误差计算有一部分是进行类乘的),当:
- η<1 时,就会出现梯度消失的问题
- η>1 时,梯度爆炸也就产生了
这也就是RNN模型的缺点,就是当句子过长的时候,距离当前时刻越远的,越容易被抹掉,就会出现这个缺点
5、克服梯度消失和爆炸问题
- 克服梯度消失问题的
LSTM和GRU模型被退出,原因是,LSTM和GRU模型他们采用了特殊的方式来进行"记忆"的存储,使得以前比较大的记忆不会像简单的RNN模型一样立刻被抹除掉,因此可以一定程度上克服梯度小时的问题 - 克服梯度暴涨问题
grndient clipping,梯度裁剪,当计算梯度时,加上一个为c的阈值,当梯度超过c或者小于-c的时候会置为c。从而减小梯度暴涨。
6、Deep(Bidrectional)RNN
Deep(Bidrectional)RNN(深层双向RNN),类似于RNN,区别在于:每一时刻的输入经过多层RNN网络在输出(不会超过两层),这样的网络便具有更强大的表达能力和学习能力,但是复杂性也提高了,同时需要训练更多数据。
双向:就是说对比与单向的RNN结构,不仅仅考虑上一个字词的信息,同时将句子反向输入,得到后面的词的记忆信息,然后将两个方向的输出结果做一个拼接,作为最终的输出。这样就同时兼顾了上下文的信息
这里的WV和上面的定义有出入们不要对着上面的看
注意:
这里的VW,同一层一样,不同层就不一样了
7、双向递归神经网络
双向递归神经网络的隐藏层要保留两个值,一个A参与正向计算,另一个A’参与反向计算,最终的输出值取决于A2和A’2(拼接或相加)
这样的好处就是既kaolv了前变得信息,又考虑了后边的信息
输出值进行拼接或者相加:
输出结果计算为:
A2和A’2计算为:
正向计算时,隐藏层的值St与St-1有关;
反向计算时,隐藏层的值S’t与S’t-1有关;
最终的输出取决于正向和反向计算的加和。
双向循环神经网络的计算方法为:
RNN网络重要的知识就这么多了。