Deep Learning 循环神经网络

(1)循环神经网络原理

RNNs的目的使用来处理序列数据。在传统的神经网络模型中,是从输入层到隐含层再到输出层,层与层之间是全连接的,每层之间的节点是无连接的。但是这种普通的神经网络对于很多问题却无能无力。例如,你要预测句子的下一个单词是什么,一般需要用到前面的单词,因为一个句子中前后单词并不是独立的。RNNs之所以称为循环神经网路,即一个序列当前的输出与前面的输出也有关。具体的表现形式为网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐藏层之间的节点不再无连接而是有连接的,并且隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。理论上,RNNs能够对任何长度的序列数据进行处理。但是在实践中,为了降低复杂性往往假设当前的状态只与前面的几个状态相关

one-hot向量:one-hot向量将类别变量转换为机器学习算法易于利用的一种形式的过程,这个向量的表示为一项属性的特征向量,也就是同一时间只有一个激活点(不为0),这个向量只有一个特征是不为0的,其他都是0,特别稀疏。

one-hot向量表示为ti={0,0,0,...,1,...0},长度根据特征的所有离散特征值决定,所有特征的离散特征值数目相加,一般比特征数目还多,具体的场景特征数目不一样。

这个网络在t时刻接收到输入Xt之后,隐藏层的值是St,输出值是Ot。关键一点是,St的值不仅仅取决于Xt,还取决于Xt-1

式1是输出层的计算公式,输出层是一个全连接层,也就是它的每个节点都和隐藏层的每个节点相连。V是输出层的权重矩阵,g是激活函数。式2是隐藏层的计算公式,它是循环层。U是输入x的权重矩阵,W是上一次的值作为这一次的输入的权重矩阵,f是激活函数。

从上面的公式我们可以看出,循环层和全连接层的区别就是循环层多了一个权重矩阵 W。

如果反复把式2带入到式1,我们将得到:

从上面可以看出,循环神经网络的输出值Ot,是受前面历次输入值Xt、Xt-1、Xt-1、Xt-1...影响的,这就是为什么循环神经网络可以往前看任意多个输入值的原因。

(2)循环神经网络的训练算法:BPTT

BPTT算法是针对循环层的训练算法,它的基本原理和BP算法是一样的,也包含同样的三个步骤:

(一)前向计算每个神经元的输出值;

(二)反向计算每个神经元的误差项值δj,它是误差函数E对神经元j的加权输入netj的偏导数;

(三)计算每个权重的梯度。

最后再用随机梯度下降算法更新权重。

①前向计算

S/X都是向量,U是矩阵,向量的下标表示时刻

假设输入向量x的维度是m,输出向量s的维度是n,则矩阵U的维度是nm,矩阵W的维度是nn。下面是上式展开成矩阵的样子

手写体字母表示向量的一个元素,它的下标表示它是这个向量的第几个元素,它的上标表示第几个时刻

②误差项的计算

BTPP 算法就是将第l层t时刻的误差值沿两个方向传播:

1)一个方向是其传递到上一层网络,得到,这部分只和权重矩阵U有关。

2)另一个是方向是将其沿时间线传递到初始时刻,得到,这部分只和权重矩阵W有关

用向量nett表示神经元在t时刻的加权输入

也就是说

a表示列向量,用aT表示行向量。上式的第一项是向量函数对向量求导,其结果为Jacobian矩阵

同理,上式第二项也是一个Jacobian矩阵

diag[a]表示根据向量a创建一个对角矩阵

最后,将两项合在一起

......

省略推导若干,直接说结果:

这就是就是将误差项传递到上一层算法

③计算每个权重的梯度

1)权重矩阵W在t时刻的梯度为:

2)最终的梯度

3)同权重矩阵W类似,我们可以得到权重矩阵U

最终的梯度也是各个时刻的梯度之和

(3)基于RNN的语言模型

把词依次输入到循环神经网络中,每输入一个词,循环神经网络就输出截止到目前为止,下一个最可能的词

第一,建立一个包含所有词的词典,每个词在词典里面有一个唯一的编号。

第二,任意一个词都可以用一个N维的one-hot向量来表示。

高维、稀疏的向量(稀疏是指绝大部分元素的值都是0)。处理这样的向量会导致我们的神经网络有很多的参数,带来庞大的计算量。因此,往往会需要使用一些降维方法,将高维的稀疏向量转变为低维的稠密向量。

让循环神经网络计算计算词典中每个词是下一个词的概率,这样,概率最大的词就是下一个最可能的词。因此,神经网络的输出向量也是一个N维向量,向量中的每个元素对应着词典中相应的词是下一个词的概率。

怎样让神经网络输出概率呢?方法就是用softmax层作为神经网络的输出层。

 Softmax又叫归一化指数函数,压缩向量,使得每一个元素的范围都在(0,1)之间,与输出概率的需求相适应。

对于语言模型来说,我们可以认为模型预测下一个词是词典中第一个词的概率是0.03,是词典中第二个词的概率是0.09,以此类推

(4)语言模型的训练

监督学习,首先需要贴标签

使用向量化方法,对输入x和标签y进行向量化

最后,使用交叉熵误差函数作为优化目标,对模型进行优化。

例如y1 = [1,0,0,0],如果网络的输出o = [0.03,0.09,0.24,0.64]

对概率进行建模时,选择交叉熵误差函数更合理。

模型,优化目标,梯度表达式都有了,就可以用梯度下降算法进行训练

7.循环神经网络结构

(1)单向循环神经网络

假设在时刻t,网络的输入为xt,隐状态(即隐藏层神经元活性值)ht 不仅和当前时刻的输入xt相关,也和上一个时刻的隐状态ht-1相关,进而与全部过去的输入序列(x1, x2, ..., xt-1, xt)相关

其中zt是隐藏层的净输入;f(•)是非线性激活函数,通常为Sigmoid函数或Tanh函数;U是状态-状态权重矩阵,W是状态-输入权重矩阵,b为偏置

(2)双向循环神经网络

双向循环神经网络(Bidirectional Recurrent Neural Network,Bi-RNN),它由两层循环神经网络组成,这两层网络都输入序列x,但是信息传递方向相反。

假设第1层按时间顺序传递信息,第2层按时间逆序传递信息,这两层在时刻t的隐状态分别为ht(1)和ht(2):

第三个式子表示把两个隐状态向量拼接起来。

8.循环神经网络的参数学习

需求参数:状态-状态权重矩阵U,态-输入权重矩阵W,和偏置b

学习方法:梯度下降法

(1)损失函数和梯度:

计算整个序列上的损失函数对参数U的梯度为

t时刻,是损失,T是样本长度

(2)随时间反向传播算法

随时间反向传播算法和前馈神经网络中的误差反向传播算法比较类似,只不过是把循环神经网络看做是一个展开的多层前馈网络,每一层对应于循环神经网络中的每个时刻。

在展开的多层前馈网络中,所有层的参数是共享的,因此参数的真实梯度是所有前馈网络层的参数梯度之和。

首先计算第t时刻损失对参数U的偏导数,再计算整个序列的损失函数对参数U的梯度。

①计算第t时刻损失对参数U的偏导数

第t时刻的损失函数,是从净输入zt按照以下的公式一步步计算出来

    

隐藏层第k个时刻(1 ≤ k ≤ t,表示第t时刻所经过的所有时刻)的净输入zk=Uhk-1+Wxk+b可以得到,第t时刻的损失函数关于参数Uij的梯度为

注意zk=Uhk-1+Wxk+b来计算zk对Uij的偏导数时,要保持hk-1不变

求第t时刻的损失函数关于参数Uij的梯度:

②计算整个序列的损失函数对参数U的梯度

③随时间反向传播算法(BPTT)中,参数的梯度需要在一个完整的“前向”计算和“反向”计算后才能得到,并进行参数更新,因此需要保存所有时刻的中间梯度,空间复杂度较高。而实时循环学习(RTRL)算法在第t时刻,可以实时计算损失关于参数的梯度,不需要梯度回传,空间复杂度低

9.循环神经网络的长期依赖问题

(1)长期依赖问题

长期依赖是指当前系统的状态,可能受很长时间之前系统状态的影响,是RNN中无法解决的一个问题.

虽然循环神经网络理论上可以建立长时间间隔的状态之间的依赖关系,但是由于梯度爆炸或梯度消失问题,实际上可能只能学习到短期的依赖关系。

将误差δt,k的公式展开为:

可化为

  

如果定义

则有

(2)改进方案

可以通过缓解循环神经网络的梯度爆炸和梯度消失问题来避免长期依赖问题

①梯度爆炸:

可以通过权重衰减和梯度截断来避免梯度爆炸问题。权重衰减是通过给参数增加L1正则化和L2正则化来限制参数的取值范围,从而使得γ≤1。而梯度截断则是当梯度的模大于一定阈值时,就将它截断为一个比较小的数。

②梯度消失:

可以改变模型,比如让U=I,同时使得f′(zi)=1

③记忆容量问题:

梯度消失的解决办法中,是通过引入了一个函数g(•),使得ht与ht-1之间既有线性关系,也有非线性关系。这会带来记忆容量问题,也就是随着ht不断存储新的输入信息,会变得越来越大,也就是发生饱和现象。而隐状态ht可以存储的信息是有限的,随着记忆单元存储的内容越来越多,其丢失的信息也越来越多。

为了解决容量问题,可以用两种方法。一是增加一些额外的存储单元,即外部记忆单元;二是进行选择性遗忘和选择性更新,即长短期记忆网络(LSTM)中的门控机制。

10.循环神经网络的模式

  循环神经网络模式:

序列到类别模式、

同步的序列到序列模式、

异步的序列到序列模式。

(1)序列到类别的模式

序列到类别模式主要用于序列数据的分类问题:输入为序列(T个数据),输出为类别(一个数据)。典型的就是文本分类任务,输入数据为单词的序列(构成一篇文档),输出为该文本的类别。

假设有一个样本x1:T = (x1, x2, ..., xT)为一个长度为T的序列,输出为一个类别y∈{1, 2, ..., C}。将样本x按不同的时刻输入到循环神经网络中去,可以得到不同时刻的隐状态h1, h2, ..., hT,然后将hT看做整个序列的最终表示,输入给分类器g(•)做分类

还可以对整个序列的所有状态进行平均,用平均隐状态来作为整个序列的表示

(2)同步的序列到序列模式

同步的序列到序列模式主要用于序列标注任务,即每一时刻都有输入和输出,输入序列和输出序列的长度相同。比如词性标注(Pos Tagging),每个单词都需要标注它的词性。命名实体识别(Name Entity Recognition,NER)也可以看做是序列标注问题,与词性标注的做法类似,特点在于对于命名实体,输出它的命名实体标签来代替词性。

假设有一个样本x1:T = (x1, x2, ..., xT)为一个长度为T的序列,输出序列为y1:T = (y1, y2, ..., yT)。将样本x按不同的时刻输入到循环神经网络中去,可以得到不同时刻的隐状态h1, h2, ..., hT,然后把每个时刻的隐状态输入给分类器g(•),得到当前时刻的标签。

(3)异步的序列到序列模式

异步的序列到序列模式也称为编码器-解码器(Encoder-Decoder)模型,即输入序列和输出序列不需要有严格的对应关系,也不用保持相同的长度。比如机器翻译中,输入为源语言的单词序列,输出为目标语言的单词序列。

在异步的序列到序列模式中,输入为一个长度为T的序列:x1:T = (x1, x2, ..., xT),输出一个长度为M的序列:y1:M = (y1, y2, ..., yM),通过先编码后解码的方式实现。

先将样本x按不同时刻输入到一个循环神经网络(编码器)中,得到其编码hT,然后在另一个循环神经网络(解码器)中得到输出序列ý1:M。为了建立输出序列之间的依赖关系,在解码器中通常使用非线性的自回归模型。

其中f1(•)和f2(•)分别表示用作编码器和解码器的循环神经网络,g(•)为分类器