回顾符号定义,前向传播的过程#
| 参数符号 | 含义 |
|---|
| U | 输入到隐藏层的权重矩阵 |
| W | 隐藏层到隐藏层的权重矩阵(循环权重) |
| V | 隐藏层到输出层的权重矩阵 |
| b | 隐藏层的偏置向量 |
| c | 输出层的偏置向量 |
| 中间量 | 含义 |
|---|
| a(t) | 第 t 时刻隐藏层的净输入(激活前) |
| h(t) | 第 t 时刻隐藏层的输出(激活后) |
| o(t) | 第 t 时刻的输出层净输入 |
| y^(t) | 第 t 时刻的预测输出(经softmax后) |
| y(t) | 第 t 时刻的真实标签 |
| L(t) | 第 t 时刻的损失值 |
前向传播公式:
路径:x(t)→a(t)→h(t)→o(t)→y^(t)
a(t)=b+Wh(t−1)+Ux(t)
h(t)=tanh(a(t))
o(t)=c+Vh(t)
y^(t)=softmax(o(t))
BPTT (Backpropagation Through Time)过程#
路径:L(t)→o(t)→h(t)(→a(t))→h(t−1)→...→h(1)
1. 对总损失求各时刻损失的梯度#
∂L(t)∂L=1用∇∗表示对 * 求梯度,在别的文献中也叫 δ∗
2. 对输出层的净输入求梯度#
损失函数对输出层净输入的梯度 ∇o(t)L≜y^(t)−y(t)
∇o(t)L=∂o(t)∂L=∂L(t)∂L⋅∂o(t)∂L(t)=y^(t)−y(t)3. 对隐藏层的输出求梯度#
单个时间步内的损失函数对隐藏层输出的梯度 ∇h(t)L(t)≜VT∇o(t)L ,是下面的方框项
整体损失函数对隐藏层输出的梯度 δ(t)≜∂h(t)∂L :
δ(t)=∂h(t)∂L=∂h(t)∂L(t)+∂h(t)∂L(t+1)+∂h(t)∂L(t+2)+…=∂h(t)∂L(t)+∂h(t)∂h(t+1)∂h(t+1)∂L(t+1)+∂h(t+1)∂h(t+2)∂h(t)∂h(t+1)∂h(t+2)∂L(t+2)+…=∂h(t)∂L(t)+k=1∑τ−t∂h(t)∂L(t+k)∂h(t)∂L(t+k)=∂h(t)∂h(t+1)⋅∂h(t+1)∂h(t+2)⋯∂h(t+k)∂L(t+k)=(j=1∏k∂h(t+j−1)∂h(t+j))∂h(t+k)∂L(t+k)
-
对于方框里面的部分,L(t) 只依赖于 h(t),所以可以直接求导;
-
对于后续时刻的 L(t+1),L(t+2),…,它们依赖于 h(t) 是通过 h(t+1),h(t+2),… 传递,所以需要用链式法则展开,但是展开依旧是一坨乘积,没法算
-
距离越远,乘积越长,容易出现梯度消失或梯度爆炸问题,导致训练困难。
注意递推关系,把 t 换成 t+1:
δ(t+1)=∂h(t+1)∂L=∂h(t+1)∂L(t+1)+∂h(t+1)∂L(t+2)+∂h(t+1)∂L(t+3)+…=∂h(t+1)∂L(t+1)+∂h(t+1)∂h(t+2)∂h(t+2)∂L(t+2)+∂h(t+2)∂h(t+3)∂h(t+1)∂h(t+2)∂h(t+3)∂L(t+3)+…这个两边同时乘以 ∂h(t)∂h(t+1),就可以得到 δ(t) 非方框 中的部分!
重大发现:δ(t) 可以递推计算:
δ(t)=∂h(t)∂L=∂h(t)∂L(t)+(∂h(t)∂h(t+1))Tδ(t+1)=(∂h(t)∂o(t))T∂o(t)∂L(t)+(∂h(t)∂h(t+1))T∂h(t+1)∂L=VT∇o(t)L+WTdiag(1−(h(t+1))2)∇h(t+1)L其中 ∂h(t)∂h(t+1) 是通过链式法则展开得到的:
h(t+1)a(t+1)⇒∂h(t)∂h(t+1)=tanh(a(t+1))=b+Wh(t)+Ux(t+1)=∂a(t+1)∂h(t+1)⋅∂h(t)∂a(t+1)=WTdiag(1−(h(t+1))2)对参数求梯度#
注意每个参数在所有时刻共享,所以要对所有时刻求和。
∇UL∇WL∇VL∇bL∇cL=t∑diag(1−(h(t))2)∇h(t)L(t)⋅(x(t))T=t∑diag(1−(h(t))2)⋅∇h(t)L(t)⋅(h(t−1))T=t∑∇o(t)L⋅(h(t))T=t∑diag(1−(h(t))2)⋅∇h(t)L=t∑∇o(t)L
长期依赖#
当间隔时间步很长时,δ(t) 中的乘积项 ∏j=1k∂h(t+j−1)∂h(t+j) 会导致梯度消失或梯度爆炸问题,训练困难。
在消失的情况下,t 时刻的梯度对 t+k 时刻以及之前的损失几乎没有影响,导致模型无法学习长期依赖关系。
梯度消失与梯度爆炸的解决方案#
1. 截断梯度#
实际应用中,两种方式性能表现类似
- 方式1:在参数更新之前,逐元素地截断Mini-batch
产生的参数梯度
- 方式2:在参数更新之前,整体约束参数梯度大小
(不改变梯度方向)
2. 时间维度的跳跃连接#
直接构造从 t 时刻单元到 t+d 时刻单元的连接
3. 渗漏单元#
对于隐藏层之间的连接:
从开始的 h(t)=tanh(b+Wh(t−1)+Ux(t)) 改结构成:
h(t)=αh(t−1)+(1−α)g(x(t),h(t−1))
- g 可以是任意的非线性函数,比如 g(x(t),h(t−1))=tanh(b+Wh(t−1)+Ux(t)),也可以是其他的函数。
- α 是一个小于 1 的常数,表示“渗漏”比例。它可以让梯度在时间维度上有一个“泄漏”,从而缓解梯度消失问题。
- α≈1 容易饱和。
- α≈0 退化为普通RNN。