Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDocCN
Dive-into-DL-PyTorch
提交
4a087ef2
D
Dive-into-DL-PyTorch
项目概览
OpenDocCN
/
Dive-into-DL-PyTorch
通知
9
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Dive-into-DL-PyTorch
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4a087ef2
编写于
4月 18, 2019
作者:
S
ShusenTang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add 6.6
上级
389ba79f
变更
3
展开全部
隐藏空白更改
内联
并排
Showing
3 changed file
with
360 addition
and
2 deletion
+360
-2
README.md
README.md
+3
-2
docs/chapter06_RNN/6.6_bptt.md
docs/chapter06_RNN/6.6_bptt.md
+107
-0
img/chapter06/6.6_rnn-bptt.svg
img/chapter06/6.6_rnn-bptt.svg
+250
-0
未找到文件。
README.md
浏览文件 @
4a087ef2
...
...
@@ -58,8 +58,9 @@ Dive into Deep Learning with PyTorch code.
[
6.1 语言模型
](
https://github.com/ShusenTang/Dive-into-DL-PyTorch/blob/master/docs/chapter06_RNN/6.1_lang-model.md
)
[
6.2 循环神经网络
](
https://github.com/ShusenTang/Dive-into-DL-PyTorch/blob/master/docs/chapter06_RNN/6.2_rnn.md
)
[
6.3 语言模型数据集(周杰伦专辑歌词)
](
https://github.com/ShusenTang/Dive-into-DL-PyTorch/blob/master/docs/chapter06_RNN/6.3_lang-model-dataset.md
)
[
6.4 循环神经网络的从零开始实现
](
https://github.com/ShusenTang/Dive-into-DL-PyTorch/blob/master/docs/chapter06_RNN/6.4_rnn-scratch.md
)
[
6.4 循环神经网络的从零开始实现
](
https://github.com/ShusenTang/Dive-into-DL-PyTorch/blob/master/docs/chapter06_RNN/6.4_rnn-scratch.md
)
[
6.5 循环神经网络的简洁实现
](
https://github.com/ShusenTang/Dive-into-DL-PyTorch/blob/master/docs/chapter06_RNN/6.5_rnn-pytorch.md
)
[
6.6 通过时间反向传播
](
https://github.com/ShusenTang/Dive-into-DL-PyTorch/blob/master/docs/chapter06_RNN/6.6_bptt.md
)
...
...
docs/chapter06_RNN/6.6_bptt.md
0 → 100644
浏览文件 @
4a087ef2
# 6.6 通过时间反向传播
在前面两节中,如果不裁剪梯度,模型将无法正常训练。为了深刻理解这一现象,本节将介绍循环神经网络中梯度的计算和存储方法,即通过时间反向传播(back-propagation through time)。
我们在3.14节(正向传播、反向传播和计算图)中介绍了神经网络中梯度计算与存储的一般思路,并强调正向传播和反向传播相互依赖。正向传播在循环神经网络中比较直观,而通过时间反向传播其实是反向传播在循环神经网络中的具体应用。我们需要将循环神经网络按时间步展开,从而得到模型变量和参数之间的依赖关系,并依据链式法则应用反向传播计算并存储梯度。
## 6.6.1 定义模型
简单起见,我们考虑一个无偏差项的循环神经网络,且激活函数为恒等映射($
\p
hi(x)=x$)。设时间步 $t$ 的输入为单样本 $
\b
oldsymbol{x}_t
\i
n
\m
athbb{R}^d$,标签为 $y_t$,那么隐藏状态 $
\b
oldsymbol{h}_t
\i
n
\m
athbb{R}^h$的计算表达式为
$$
\b
oldsymbol{h}_t =
\b
oldsymbol{W}_{hx}
\b
oldsymbol{x}_t +
\b
oldsymbol{W}_{hh}
\b
oldsymbol{h}_{t-1},
$$
其中$
\b
oldsymbol{W}_{hx}
\i
n
\m
athbb{R}^{h
\t
imes d}$和$
\b
oldsymbol{W}_{hh}
\i
n
\m
athbb{R}^{h
\t
imes h}$是隐藏层权重参数。设输出层权重参数$
\b
oldsymbol{W}_{qh}
\i
n
\m
athbb{R}^{q
\t
imes h}$,时间步$t$的输出层变量$
\b
oldsymbol{o}_t
\i
n
\m
athbb{R}^q$计算为
$$
\b
oldsymbol{o}_t =
\b
oldsymbol{W}_{qh}
\b
oldsymbol{h}_{t}.
$$
设时间步$t$的损失为$
\e
ll(
\b
oldsymbol{o}_t, y_t)$。时间步数为$T$的损失函数$L$定义为
$$
L =
\f
rac{1}{T}
\s
um_{t=1}^T
\e
ll (
\b
oldsymbol{o}_t, y_t).
$$
我们将$L$称为有关给定时间步的数据样本的目标函数,并在本节后续讨论中简称为目标函数。
## 6.6.2 模型计算图
为了可视化循环神经网络中模型变量和参数在计算中的依赖关系,我们可以绘制模型计算图,如图6.3所示。例如,时间步3的隐藏状态$
\b
oldsymbol{h}_3$的计算依赖模型参数$
\b
oldsymbol{W}_{hx}$、$
\b
oldsymbol{W}_{hh}$、上一时间步隐藏状态$
\b
oldsymbol{h}_2$以及当前时间步输入$
\b
oldsymbol{x}_3$。
<div
align=
center
>
<img
width=
"500"
src=
"../../img/chapter06/6.6_rnn-bptt.svg"
/>
</div>
<div
align=
center
>
图6.3 时间步数为3的循环神经网络模型计算中的依赖关系。方框代表变量(无阴影)或参数(有阴影),圆圈代表运算符
</div>
## 6.6.3 方法
刚刚提到,图6.3中的模型的参数是 $
\b
oldsymbol{W}_{hx}$, $
\b
oldsymbol{W}_{hh}$ 和 $
\b
oldsymbol{W}_{qh}$。与3.14节(正向传播、反向传播和计算图)中的类似,训练模型通常需要模型参数的梯度$
\p
artial L/
\p
artial
\b
oldsymbol{W}_{hx}$、$
\p
artial L/
\p
artial
\b
oldsymbol{W}_{hh}$和$
\p
artial L/
\p
artial
\b
oldsymbol{W}_{qh}$。
根据图6.3中的依赖关系,我们可以按照其中箭头所指的反方向依次计算并存储梯度。为了表述方便,我们依然采用3.14节中表达链式法则的运算符prod。
首先,目标函数有关各时间步输出层变量的梯度$
\p
artial L/
\p
artial
\b
oldsymbol{o}_t
\i
n
\m
athbb{R}^q$很容易计算:
$$
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{o}_t} =
\f
rac{
\p
artial
\e
ll (
\b
oldsymbol{o}_t, y_t)}{T
\c
dot
\p
artial
\b
oldsymbol{o}_t}.$$
下面,我们可以计算目标函数有关模型参数$
\b
oldsymbol{W}_{qh}$的梯度$
\p
artial L/
\p
artial
\b
oldsymbol{W}_{qh}
\i
n
\m
athbb{R}^{q
\t
imes h}$。根据图6.3,$L$通过$
\b
oldsymbol{o}_1,
\l
dots,
\b
oldsymbol{o}_T$依赖$
\b
oldsymbol{W}_{qh}$。依据链式法则,
$$
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{W}_{qh}}
=
\s
um_{t=1}^T
\t
ext{prod}
\l
eft(
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{o}_t},
\f
rac{
\p
artial
\b
oldsymbol{o}_t}{
\p
artial
\b
oldsymbol{W}_{qh}}
\r
ight)
=
\s
um_{t=1}^T
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{o}_t}
\b
oldsymbol{h}_t^
\t
op.
$$
其次,我们注意到隐藏状态之间也存在依赖关系。
在图6.3中,$L$只通过$
\b
oldsymbol{o}_T$依赖最终时间步$T$的隐藏状态$
\b
oldsymbol{h}_T$。因此,我们先计算目标函数有关最终时间步隐藏状态的梯度$
\p
artial L/
\p
artial
\b
oldsymbol{h}_T
\i
n
\m
athbb{R}^h$。依据链式法则,我们得到
$$
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{h}_T} =
\t
ext{prod}
\l
eft(
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{o}_T},
\f
rac{
\p
artial
\b
oldsymbol{o}_T}{
\p
artial
\b
oldsymbol{h}_T}
\r
ight) =
\b
oldsymbol{W}_{qh}^
\t
op
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{o}_T}.
$$
接下来对于时间步$t < T$, 在图6.3中,$L$通过$
\b
oldsymbol{h}_{t+1}$和$
\b
oldsymbol{o}_t$依赖$
\b
oldsymbol{h}_t$。依据链式法则,
目标函数有关时间步$t < T$的隐藏状态的梯度$
\p
artial L/
\p
artial
\b
oldsymbol{h}_t
\i
n
\m
athbb{R}^h$需要按照时间步从大到小依次计算:
$$
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{h}_t}
=
\t
ext{prod} (
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{h}_{t+1}},
\f
rac{
\p
artial
\b
oldsymbol{h}_{t+1}}{
\p
artial
\b
oldsymbol{h}_t}) +
\t
ext{prod} (
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{o}_t},
\f
rac{
\p
artial
\b
oldsymbol{o}_t}{
\p
artial
\b
oldsymbol{h}_t} ) =
\b
oldsymbol{W}_{hh}^
\t
op
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{h}_{t+1}} +
\b
oldsymbol{W}_{qh}^
\t
op
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{o}_t}
$$
将上面的递归公式展开,对任意时间步$1
\l
eq t
\l
eq T$,我们可以得到目标函数有关隐藏状态梯度的通项公式
$$
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{h}_t}
=
\s
um_{i=t}^T {
\l
eft(
\b
oldsymbol{W}_{hh}^
\t
op
\r
ight)}^{T-i}
\b
oldsymbol{W}_{qh}^
\t
op
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{o}_{T+t-i}}.
$$
由上式中的指数项可见,当时间步数 $T$ 较大或者时间步 $t$ 较小时,目标函数有关隐藏状态的梯度较容易出现衰减和爆炸。这也会影响其他包含$
\p
artial L /
\p
artial
\b
oldsymbol{h}_t$项的梯度,例如隐藏层中模型参数的梯度$
\p
artial L /
\p
artial
\b
oldsymbol{W}_{hx}
\i
n
\m
athbb{R}^{h
\t
imes d}$和$
\p
artial L /
\p
artial
\b
oldsymbol{W}_{hh}
\i
n
\m
athbb{R}^{h
\t
imes h}$。
在图6.3中,$L$通过$
\b
oldsymbol{h}_1,
\l
dots,
\b
oldsymbol{h}_T$依赖这些模型参数。
依据链式法则,我们有
$$
\b
egin{aligned}
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{W}_{hx}}
&=
\s
um_{t=1}^T
\t
ext{prod}
\l
eft(
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{h}_t},
\f
rac{
\p
artial
\b
oldsymbol{h}_t}{
\p
artial
\b
oldsymbol{W}_{hx}}
\r
ight)
=
\s
um_{t=1}^T
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{h}_t}
\b
oldsymbol{x}_t^
\t
op,
\\
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{W}_{hh}}
&=
\s
um_{t=1}^T
\t
ext{prod}
\l
eft(
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{h}_t},
\f
rac{
\p
artial
\b
oldsymbol{h}_t}{
\p
artial
\b
oldsymbol{W}_{hh}}
\r
ight)
=
\s
um_{t=1}^T
\f
rac{
\p
artial L}{
\p
artial
\b
oldsymbol{h}_t}
\b
oldsymbol{h}_{t-1}^
\t
op.
\e
nd{aligned}
$$
我们已在3.14节里解释过,每次迭代中,我们在依次计算完以上各个梯度后,会将它们存储起来,从而避免重复计算。例如,由于隐藏状态梯度$
\p
artial L/
\p
artial
\b
oldsymbol{h}_t$被计算和存储,之后的模型参数梯度$
\p
artial L/
\p
artial
\b
oldsymbol{W}_{hx}$和$
\p
artial L/
\p
artial
\b
oldsymbol{W}_{hh}$的计算可以直接读取$
\p
artial L/
\p
artial
\b
oldsymbol{h}_t$的值,而无须重复计算它们。此外,反向传播中的梯度计算可能会依赖变量的当前值。它们正是通过正向传播计算出来的。
举例来说,参数梯度$
\p
artial L/
\p
artial
\b
oldsymbol{W}_{hh}$的计算需要依赖隐藏状态在时间步$t = 0,
\l
dots, T-1$的当前值$
\b
oldsymbol{h}_t$($
\b
oldsymbol{h}_0$是初始化得到的)。这些值是通过从输入层到输出层的正向传播计算并存储得到的。
## 小结
*
通过时间反向传播是反向传播在循环神经网络中的具体应用。
*
当总的时间步数较大或者当前时间步较小时,循环神经网络的梯度较容易出现衰减或爆炸。
------------
> 注:本节与原书基本相同,[原书传送门](https://zh.d2l.ai/chapter_recurrent-neural-networks/bptt.html)
\ No newline at end of file
img/chapter06/6.6_rnn-bptt.svg
0 → 100644
浏览文件 @
4a087ef2
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录