一、梯度消失及爆炸
1.1 RNN中的梯度消失(推导)
如图,反向传播更新隐藏层的向量时,如果途中的梯度较小,链式法则将使得远处的梯度信号
根据RNN中的隐藏层计算公式:
h(t)=σ(Whh(t−1)+Wxx(t)+b1)
反向传播时计算相邻两个time-step的梯度:
∂h(t−1)∂h(t)=diag(σ′(Whh(t−1)+Wxx(t)+b1))Wh
计算计算不相邻两个time-step的梯度:
∂h(j)∂J(i)(θ)=∂h(i)∂J(i)(θ)j<t≤i∏∂h(t−1)∂h(t)=∂h(i)∂J(i)(θ)Wh(i−j)j<t≤i∏diag(σ′(Whh(t−1)+Wxx(t)+b1))
考虑矩阵的L2范数:
∥∥∥∥∂h(j)∂J(i)(θ)∥∥∥∥≤∥∥∥∥∂h(i)∂J(i)(θ)∥∥∥∥∥Wh∥(i−j)j<t≤i∏∥diag(σ′(Whh(t−1)+Wxx(t)+b1))∥
有论文证明了矩阵
Wh的特征值如果小于1,那么上面的梯度就会随着距离指数级减小。由于我们使用sigmod非线性激活函数,边界值就是1。(个人觉得存疑,因为sigmod并没有对
Wh使用)。
相反的,如果其特征值大于一,能被证明会发生梯度爆炸。
1.2 梯度消失会带来的问题
梯度消失会使后面距离较远的损失函数很难影响到前面的隐藏层的值,模型就无法有效的学习到前后距离较远的time-step的相互关联。因此,梯度可以看做前面的时间步对未来预测的影响。
对于较长的距离,例如从t到t+n,由于没有足够的误差信号传播来更新,预测阶段就不能获得正确的通过t预测t+n的数据的参数,这两者的预测数据就几乎没有关联。
一个容易出错的例子:
1.3 梯度爆炸带来的问题及解决办法
根据梯度更新的公式,如果梯度太大,一次更新步长太大,导致无法收敛,参数最终会溢出(inf),如果模型训练时loss异常增大,很可能是由于梯度爆炸导致(可以返回上一个检查点重新训练)。
下面这个图很直观的表现了梯度爆炸的可能原因,梯度陡崖的存在导致参数向它的反方向更新了很大一个步长。
可以通过梯度裁剪的方式来避免梯度爆炸。即设定一个梯度阈值,每次进行SGD更新前检查梯度,如果大于这个阈值,就对所有梯度进行等比例缩小。(相当于沿着同一个方向减小梯度,但是减小了步长)
二、更复杂的RNN
2.1 Long Short-Term Memory(LSTM)
2.1.1 LSTM的结构
梯度爆炸可以通过梯度裁剪来解决,而LSTM就是1997年提出的解决梯度消失的办法。其基本思想是通过在每个time-step增加一个记忆区来储存上下文的信息。
LSTM的基本结构:
- 每个time-step有一个隐藏状态
h(t)(hidden state)和一个cell状态
c(t)(cell state)
- 这两个都是长度为n的向量。
- 记忆状态储存长距离的依赖信息。
- LSTM对cell可以有三种操作:擦除、重写、读取。
LSTM中的门:
- 通过三个关联的门(gates)来控制上面三种操作的选择。
- 这三个门也分别是三个长度为n的向量。
- 在每一个time-step的gates有开(1)、闭(0)两种状态或者这之间的某个值
- 门的状态在每一个time-step受上下文信息影响动态调整
2.1.2 LSTM前向传播
对于输入序列
x(t):
- 每一个门是一个长为n的向量,都有一个对应权重矩阵。
(遗忘门−forget)f(t)(输入门−input)i(t)(输出门−output)o(t)=σ(Wfh(t−1)+Ufx(t)+bf)=σ(Wih(t−1)+Uix(t)+bi)=σ(Woh(t−1)+Uox(t)+bo)
-
其中三个门控制的效果为均是以cell记忆单元命名:
-
遗忘门:
c(t−1)到
c(t)的信息删除
-
输入门:
h(t−1)到
c(t)的信息输入
-
输出门:
c(t)到
h(t)的信息输出
- 通过这些门来控制cell,进而计算hidden (
a∘b在这里是指元素级element-wise相乘)
c~(t)c(t)h(t)=tanh(Wch(t−1)+Ucx(t)+bc)=f(t)∘c(t−1)+i(t)∘c~(t)=o(t)∘tanhc(t)
注意这里的tanh是双曲正切函数,值域为(-1, 1)现在在放出这个经典的图,注意左下角的图例,这次终于能看懂了:
2.1.3 LSTM为什么解决了梯度消失的问题
LSTM事实上并没有从根本上解决梯度消失的问题,但它通过记忆之前的信息,从而产生了长距离的依赖。
那么为什么普通RNN我们通过梯度消失断定其依赖距离存在问题,而LSTM就只通过前向传播断定其有效呢?老师的回答是LSTM的记忆机制可能提供一种梯度的传播捷径,而普通RNN的hidden是其唯一的传播途径。
2.1.4 LSTM的发展历程
- 2013-2015 LSTM称为最主要的工具之一
- 这之后transformer他、取代了LSTM的地位
2.1.5 Bidirectional RNNs
单向的RNN, 某个time-step可能只与它的左侧context产生关联,通过双向RNN拼接,解决这个问题。但要注意双向RNN不是语言建模(用左侧序列预测下一个)
例如:BERT(Bidirectional Encoder Representations from Transformer), 现在来看这个明明就很有意思了,transformer作为encoder, 并且是双向的两层。
2.1.6 muti-layer(stacked) RNNs
RNN已经在序列单个维度上进行深度抽象,通过增加网络层数,可以在另一个维度上进行高度抽象,从而学习到更为复杂的特征。
2.2 GRU(gated recurrent units)
- 2014年提出的LSTM的替代,结构更简单
- 每个time-step有一个输入
x(t)和一个hidden state
h(t)
- two gates:
- update gate:
u(t)=σ(Wuh(t−1)+Uux(t)+bu)
- reset gate:
r(t)=σ(Wrh(t−1)+Urx(t)+br)
- 门控隐藏层:
h~(t)=tanh(Wh(r(t)∘h(t−1))+Uhx(t)+bh)h(t)=(1−u(t))∘h(t−1)+u(t)∘h~(t)
2.3 GRU vs LSTM
- RNN有很多种,但这两种使用最为广泛
- 两者唯一的区别:GRU比LSTM运算更快
- 当数据充足时,建议使用LSTM(因为参数更多,但依然是玄学)
- 需要性能的话就GRU
三、梯度消失与爆炸广泛存在
- 梯度消失爆炸存在于所有神经网络中,尤其是深度神经网络,这是由于链式法则产生。
- 这导致底部的网络层更难以训练
- 网络设置直接相连的捷径,使梯度能够有效传播,例如ResNet
- DenseNet: 直接将底层与上面的每一层暴力相连:
- HighwayNet: 受LSTM启发,网络结构与resnet相似,但捷径部分是一个动态的门。
四、应用技巧
- 通常多层RNN表现更好, 例如Britz在2017的论文发现2-4层的RNN作为encoder, 4层的RNN作为decoder用于神经网络翻译效果最好。但是深度的网络需要使用skip-connections/dense-connections来训练更深的RNN.
- 基于Transformer的网络可能深达24层(BERT),其中就用到了很多skip-connections的技术。
- LSTM更强,但GRU更快
- 梯度裁剪
- RNN能用双向就用双向
- 多层RNN更强大,但可能需要用到skip/dense-connections的技巧。