RNN的时间反向传播原理
本节将介绍循环神经网络中梯度的计算和存储方法,即通过时间反向传播(back-propagation through time)。正向传播在循环神经网络中比较直观,而通过时间反向传播其实是反向传播在循环神经网络中的具体应用。我们需要将循环神经网络按时间步展开,从而得到模型变量和参数之间的依赖关系,并依据链式求导法则应用反向传播计算并存储梯度。
1. 定义模型
简单起见,我们考虑一个无偏置项的循环神经网络,且激活函数简化为恒等映射 。设时间步 的输入为单样本 ,即不考虑 ,标签为 ,那么隐藏状态 的计算表达式为:
其中, 和 是隐藏层权重系数。设输出层权重系数 ,时间步 的输出层变量 计算为:
设时间步 的损失为 。时间步数为 的损失函数 定义为:
我们将 称为有关给定时间步
2.模型计算图
为了可视化循环神经网络中变量和模型参数在计算中的依赖关系,我们可以绘制模型计算图,假设时间步数为 3 的循环神经网络模型计算中的依赖关系,方框代表变量(无阴影)和模型参数(有阴影),圆圈代表运算符。
如上图所示,所有时间步的模型参数都是共享的,而且相邻时间步之间具有依赖性,即:时间步 2 的计算依赖于时间步 1 得到的隐藏状态,时间步 3 的计算又依赖于时间步 2 得到的隐藏状态。例如:时间步 的隐藏状态 的计算依赖模型参数 、、上一时间步的隐藏状态 以及当前时间步输入 。即:
有时候,一些教材或者书籍也被习惯性写成转置的形式:
这里的 , 和 。有的文章里面可能会使用下面这种表达形式,大家只要记住转置矩阵满足的运算规律
3. 方法
我们从上图中可以直观的看出模型的参数就是 , 和 。所以训练模型反向传播更新参数时,需要计算模型参数的梯度 ,,。根据图中的依赖关系,我们可以按照其中箭头所指的反方向依次计算并存储梯度。
首先,目标函数 有关各时间步输出层变量的梯度 很容易计算:
下面,我们可以计算目标函数关于模型参数 的梯度 。根据模型计算图可知, 通过 依赖 。依据链式法则,
又因为 ,于是就有 ,所以
这样写好像不是那么严谨,所以如果从一个数学家的角度出发,他可能考虑将上式写成累加的形式,也就是如下的形式:
到此为止,我们已经求出了一个模型参数 的梯度更新公式了。那我们继续来推导剩余的两个模型参数的梯度更新公式吧!前方高能,可能在没推导之前,读者应该意识到了这两个参数并不像前面那个参数的计算梯度那样好求,因为涉及到了前后时间步的隐藏状态之间也存在依赖关系。所以我们先要建立递推关系式:
在建立递推关系式之前,我们先找到递归的出口,那就是最后的时间步 。
目标函数 只通过 依赖最终时间步 的隐藏状态 。因此,我们先计算目标函数有关最终时间步隐藏状态的梯度 。依据链式法则,就可以得到:
又因为 ,所以就有
接下来对于时间步 。因为 ,而且在前向传播的时候,,所以我们说 通过 和 依赖 。依据链式法则,目标函数有关时间步 的隐藏状态的梯度 需要按照时间步从大到小依次计算:
根据上面的递推公式和递推关系出口,对于任意时间步 ,我们可以得到目标函数有关隐藏状态梯度的通项公式(这一步如何得到,我们不加证明的直接给出):
由上式中的指数项可见,当时间步数 较大或者时间步 较小时,目标函数有关隐藏状态的梯度较容易出现衰减和爆炸。这也会影响其他包含 项的梯度,例如隐藏层中模型参数的梯度 、。 通过
每次迭代中,我们在依次计算完以上各个梯度后,会将它们存储起来,从而避免重复计算,例如,由于隐藏状态梯度 被计算和存储,之后的模型参数梯度 和 的计算可以直接读取
此外,反向传播中的梯度计算可能会依赖变量的当前值,它们正是通过正向传播计算出来的,举例来说,参数梯度 的计算需要依赖隐藏状态在时间步 的当前值
小结:
本节主要介绍了循环神经网络中通过时间反向传播来更新模型参数的推导过程,要求不在于能自己手动推导每一步,而在于理解循环神经网络的梯度为什么会出现衰减或者爆炸,而不是人云亦云或道听途说,后来引入的梯度裁剪、具有门控单元的循环神经网络都是基于这个原因。所以推导不要求,而重在理解问题本身,因为现在也不需要由研究人员手动去计算每一步了,都交给计算机或现有的模块来完成了。
- 通过时间反向传播是反向传播在循环神经网络中的具体应用;
- 当总的时间步数较大或者当前时间步较小时,循环神经网络的梯度较容易出现衰减或爆炸;