1、循环神经网络概述
循环神经网络(RNN)和DNN,CNN不同,它能处理序列问题。比如基于时间序列:一段段连续的语音,一段段连续的手写文字。这些序列比较长,而且长短不一,又比较难拆分成一个个独立的样本来训练。那么RNN又是怎么来处理这类问题的呢?RNN假设我们的样本是基于序列的。比如是从序列索引1到序列索引τ的。对于这其中的任意序列索引号t,它对应的输入是对应的样本序列中的x(t)。而模型在序列索引号t位置的隐藏状态h(t),则由x(t)和在t−1位置的隐藏状态h(t−1)共同决定。在任意序列索引号t,我们也有对应的模型预测输出o(t)。通过预测输出o(t)和训练序列真实输出y(t),以及损失函数L(t),我们就可以用DNN类似的方法来训练模型,接着用来预测测试序列中的一些位置的输出。
比如,当我们在理解一句话意思时,孤立的理解这句话的每个词是不够的,我们需要处理这些词连接起来的整个序列; 当我们处理视频的时候,我们也不能只单独的去分析每一帧,而要分析这些帧连接起来的整个序列。以nlp的一个最简单词性标注任务来说,将我 吃 苹果 三个单词标注词性为 我/nn 吃/v 苹果/nn。
那么这个任务的输入就是:
我 吃 苹果 (已经分词好的句子)
这个任务的输出是:
我/nn 吃/v 苹果/nn(词性标注好的句子)
对于这个任务来说,我们当然可以直接用普通的神经网络来做,给网络的训练数据格式了就是我-> 我/nn 这样的多个单独的单词->词性标注好的单词。但是很明显,一个句子中,前一个单词其实对于当前单词的词性预测是有很大影响的,比如预测苹果的时候,由于前面的吃是一个动词,那么很显然苹果作为名词的概率就会远大于动词的概率,因为动词后面接名词很常见,而动词后面接动词很少见。此时就需要RNN来处理该问题。
再者我们常见的语言模型有2-Gram或者是3-Gram,当n-Gram中的n大于3之后,样本容量会非常大,甚至超过现有的计算能力。此时RNN就可以解决该问题,理论上RNN可以往前往后关联任意多个词。
2、循环神经网络模型
先以一个最常见的RNN模型来展开
上图中左边是RNN模型没有按时间展开的图,如果按时间序列展开,则是上图中的右边部分。我们重点观察右边部分的图。
这幅图描述了在序列索引号t 附近RNN的模型。其中:
1)x(t)代表在序列索引号t时训练样本的输入。同样的,x(t−1)和x(t+1)代表在序列索引号t−1和t+1时训练样本的输入。
2)h(t)代表在序列索引号t时模型的隐藏状态。h(t)由x(t)和h(t−1)共同决定。
3)o(t)代表在序列索引号t时模型的输出。o(t)只由模型当前的隐藏状态h(t)决定。
4)L(t)代表在序列索引号t时模型的损失函数。
5)y(t)代表在序列索引号t时训练样本序列的真实输出。
6)U, W, V这三个矩阵是我们的模型的线性关系参数,它在整个RNN网络中是共享的,这点和DNN很不相同,和CNN中的共享类似。 也正因为是共享了,它体现了RNN的模型的“循环反馈”的思想。
3、循环神经网络的前向传播算法
循环网络的前向传播算法非常简单,对于t时刻:
其中ϕ()为激活函数,一般来说会选择tanh函数,b为偏置。则t时刻的输出:
最终模型的预测输出为:
其中σ为激活函数,通常RNN用于分类,故这里一般用softmax函数。
4、循环神经网络的反向传播算法
BPTT(back-propagation through time)算法是常用的训练RNN的方法,其实本质还是BP算法,只不过RNN处理时间序列数据,所以要基于时间反向传播,故叫随时间反向传播。BPTT的中心思想和BP算法相同,沿着需要优化的参数的负梯度方向不断寻找更优的点直至收敛。当然这里的BPTT和DNN中的BP算法也有很大的不同点,即这里所有的U, W, V在序列的各个位置是共享的,反向传播时我们更新的是相同的参数。
对于RNN,由于我们在序列的每个位置都有损失函数,因此最终的损失L为:
因此可以得到U,V,W的偏导,其中V的比较好求
而在求W和U时就比较的复杂了。从RNN的模型可以看出,在反向传播时,在在某一序列位置t的梯度损失由当前位置的输出对应的梯度损失和序列索引位置t+1时的梯度损失两部分共同决定。对于W在某一序列位置t的梯度损失需要反向传播一步步的计算。
比如以t=3时刻为例
因此,在某个时刻的对W或是U的偏导数,需要追溯这个时刻之前所有时刻的信息。根据上面的式子可以归纳出L在t时刻对W和U偏导数的通式:
而对于里面的乘积部分,我们引入激活函数,则可以表示为:
或者是
然而对于Sigmoid函数和tanh函数及其导数有以下的特点
sigmoid函数及其导数
tanh函数及其导数
Relu函数及其导数
我们可以从中观察到,sigmoid函数的导数范围是(0, 0.25],tanh函数的导数范围是(0, 1],他们的导数最大都不大于1。因此在上面求梯度的乘积中,随着时间序列的不断深入,小数的累乘就会导致梯度越来越小直到接近于0,这就会引起梯度消失现象。梯度消失就意味着那一层的参数再也不更新了,则模型的训练毫无意义。Relu函数一定程度上可以解决梯度消失的问题,但是容易引起梯度爆炸的问题。此外tanh函数的收敛速度要快于sigmoid函数,而且梯度消失的速度要慢于sigmoid函数。
利用BPTT算法训练网络时容易出现梯度消失的问题,当序列很长的时候问题尤其严重,因此上面的RNN模型一般不能直接应用。而较为广泛使用的是RNN的一个特例LSTM。
5、LSTM 网络
Long Short Term 网络,一般就叫做 LSTM ,是一种 RNN 特殊的类型,可以学习长期依赖信息。LSTM 通过刻意的设计来避免长期依赖问题。记住长期的信息在实践中是 LSTM 的默认行为,而非需要付出很大代价才能获得的能力!
所有 RNN 都具有一种重复神经网络模块的链式的形式。在标准的 RNN 中,这个重复的模块只有一个非常简单的结构,例如一个 tanh 层。
LSTM 同样是这样的结构,但是重复的模块拥有一个不同的结构。不同于 单一神经网络层,整体上除了h在随时间流动,细胞状态c也在随时间流动,细胞状态c就代表着长期记忆。
上面我们给出了LSTM的模型结构,下面我们就一点点的剖析LSTM模型在每个序列索引位置t时刻的内部结构。
从上图中可以看出,在每个序列索引位置t时刻向前传播的除了和RNN一样的隐藏状态h(t),还多了另一个隐藏状态,如图中上面的长横线。这个隐藏状态我们一般称为细胞状态(Cell State),记为C(t)。如下图所示:
细胞状态类似于传送带。直接在整个链上运行,只有一些少量的线性交互。信息在上面流传保持不变会很容易。LSTM 有通过精心设计的称作为“门”的结构来去除或者增加信息到细胞状态的能力。LSTM在在每个序列索引位置t的门一般包括遗忘门,输入门和输出门三种。下面我们就来研究上图中LSTM的遗忘门,输入门和输出门以及细胞状态。
5.1 遗忘门
遗忘门(forget gate)顾名思义,是控制是否遗忘的,在LSTM中即以一定的概率控制是否遗忘上一层的隐藏细胞状态。遗忘门子结构如下图所示:
该门会读取ht−1和xt,输出一个在 0 到 1 之间的数值给每个在细胞状态Ct−1 中的数字。1 表示“完全保留”,0 表示“完全舍弃”。
这里可以抛出两个问题:这个门怎么做到“遗忘“的呢?怎么理解?既然是遗忘旧的内容,为什么这个门还要接收新的xt? 对于第一个问题,“遗忘“可以理解为“之前的内容记住多少“,其精髓在于只能输出(0,1)小数的sigmoid函数和粉色圆圈的乘法,LSTM网络经过学习决定让网络记住以前百分之多少的内容。对于第二个问题就更好理解,决定记住什么遗忘什么,其中新的输入肯定要产生影响。
例如在语言模型中,基于已经看到的预测下一个词。在这个问题中,细胞状态可能包含当前主语的性别,因此正确的代词可以被选择出来。当我们看到新的主语,我们希望忘记旧的主语。
5.2 输入门
输入门(input gate)负责处理当前序列位置的输入,确定什么样的新信息被存放在细胞状态中。这里包含两个部分。第一,sigmoid 层称 “输入门层” 决定什么值我们将要更新。然后一个 tanh 层创建一个新的候选值向量C̃ t,会被加入到状态中。它的子结构如下图:
在我们语言模型的例子中,我们希望增加新的主语的性别到细胞状态中,来替代旧的需要忘记的主语。
现在是更新旧细胞状态的时间了,Ct−1 更新为 Ct。前面的步骤已经决定了将会做什么,我们现在就是实际去完成。
5.3 输出门
有了新的隐藏细胞状态C(t),我们就可以来看输出门了,子结构如下:
从图中可以看出,隐藏状态h(t)的更新由两部分组成,第一部分是o(t), 它由上一序列的隐藏状态h(t−1)和本序列数据x(t),以及激活函数sigmoid得到,第二部分由隐藏状态C(t)和tanh激活函数组成,。
6、LSTM前向传播算法
LSTM模型有两个隐藏状态h(t), C(t),模型参数几乎是RNN的4倍,因为现在多了Wf, Uf, bf, Wa, Ua, ba, Wi, Ui, bi, Wo, Uo, bo这些参数。
前向传播过程在每个序列索引位置的过程为:
1)更新遗忘门输出:
2)更新输入门两部分输出:
a(t) = tanh(Wah(t−1) + Uax(t) + ba)
3)更新细胞状态:
4)更新输出门输出:
5)更新当前序列索引预测输出:
知道了前向传播,反向传播和RNN中的一样,也是借助梯度下降来训练模型
总归LSTM模型结构是非常复杂的,而且参数众多,因此调参时要非常仔细,并且要深刻理解模型的每个结构才能更好的选取参数。