起源
全连接神经网络能够很好地拟合复杂的样本特征,卷积神经网络能很好地建模局部与全局特征的关系。但它们都只能处理定长的输入、输出,而自然语言的处理对象一般是变长的语句,句子中各元素出现的顺序先后暗含着时序关系,循环神经网络(Recurrent Neural Network,下称RNN)能够较好地处理这种关系。
基本结构
RNN的基本思想是:将处理对象在时序上分解为具有相同结构的单元,单元间有着时序关联,即本单元接收上一时序对应单元的输出,并把计算结果输出到下一时序对应的单元。网络结构由这样一系列的单元构成,能够在时序上进行展开。
可以看到每一时刻,隐层不仅接收输入,还接收了上一时刻隐层的输出,综合计算得到该时刻的隐层输出。公式化过程如下:
给出框架图和具体化公式如下:
RNN每个时刻都有输入、输出。由公式可以看到,每个时刻的输入(初始时刻必须有输入)、输出其实也是可以去除的,这样就得到了以RNN为基础的不同类型的网络架构:
其中one to one架构就退化为了普通的前馈神经网络架构。而其它不同的变种可用于不同的时间序列相关场景,比如对齐的many to many可以用来做序列标注,针对当前时刻的词进行标注;错开的many to many适合做机器翻译,当源语句全部输入网络后,才开始逐步翻译过程。
RNN的训练
由于RNN涉及时间序列的运算,我们使用BPTT(Back Propagation Through Time)进行参数更新,即梯度需要沿着时间序列回流到最初的时间点。
假设我们采用对齐的many to many架构,每个时刻都有一个监督值,损失为,定义损失函数如下:
其中定义如上,则有关于的梯度为:
关于的梯度为:
由于是的函数,而又是的函数…所以是关于的函数,可以得到(注:的链式求导展开,建议手算一遍):
其中:
则有:
由于也在函数中,类似于,我们可以得到:
可以看到,和两部分都涉及到了连乘,当连乘项数很多,且乘子<1时,梯度便会接近于0;而当乘子>1时,梯度便会接近于无穷,这就是RNN的梯度消失/梯度爆炸的问题。这导致RNN只能学习到短周期的关系,当周期过长(连乘项很多),便会导致学习过程出问题,因此也叫长期依赖问题。
RNN的改进方案——LSTM、GRU
长短时记忆神经网络(Long Short-Term Memory Neural Network,下称LSTM)是RNN的一个变体,可以有效地解决简单循环神经网络的梯度消失/爆炸问题。LSTM 模型的关键是引入了一组记忆单元(Memory Units),允许网络学习何时遗忘历史信息,何时用新信息更新记忆单元。在时刻 t 时,记忆单元记录了到当前时刻为止的所有历史信息,并受三个“门”控制:输入门 , 遗忘门和输出门 。三个门的元素的值在[0, 1] 之间。LSTM与原始RNN对比如下:
可以直观感受到,原始RNN中,梯度流向的路线是相对单一的,而在LSTM中通过三个门的控制,使得梯度流向更加得复杂,公式如下:
遗忘门控制每一个内存单元需要遗忘多少信息,输入门控制每一个内存单元需要加入多少新的信息,输出门控制每一个内存单元输出多少信息,是logsitic函数。那么这样改进有什么好处呢?以为例,转化为求和。是由两部分求和构成,避免了在求导连乘时过大或过小的情况,同理。通过引入门控制,将梯度分流到了不同的部分,也就极大地降低了梯度消失/爆炸出现的风险。
可是LSTM在实际使用过程中带有大量的参数,且其中门的功能多少有重叠。既想要在保持效果的基础上加快训练速度,又要杜绝梯度消失/爆炸的出现。于是就有了LSTM的简化版本——门限循环单元(Gated Recurrent Unit,下称GRU)。GRU将输入门和遗忘门合并成一个门:更新门(Update Gate),同时还合并了记忆单元和隐层输出,更新门控制当前的状态需要遗忘多少历史和接收多少新信息。重置门用来控制接收信息中有多少时来自于历史信息。GRU视图与公式如下:
基于RNN模型基础单元衍生出的LSTM、GRU,能够很好地服务于上文提到的几种架构。在解决了梯度消失/爆炸的问题后,RNN-Based模型能够很好地处理较长的序列。本篇到此为止,就不再细致讲具体应用了。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:笔记(总结)-循环神经网络 - Python技术站