Professional Documents
Culture Documents
Lecture 03
Lecture 03
Lecture 03
3. 神经网络学习:手工计算梯度
3.1. 简介
作业 2 是关于确保你真正理解神经网络的数学。
……那我们就让软件来做吧!
我们今天将快速完成所有工作,但这一周的大量工作要是阅读!
对于某些人来说,这将是艰难的一周!
如果需要,请务必寻求帮助:
办公时间访问;
阅读教学大纲中给出的教程材料。
星期四将主要是语言学!有些人也觉得它很难。
3.1.1. 命名实体识别(NER)
NER 任务:在文本中查找和分类名称(时间-DATA、地点-LOC、人物-PER、组织-ORG),例如:
NER 可能的用途:
(1) 跟踪文档中对特定实体的提及;
(2) 对于问答系统,其答案通常是命名实体。
后续任务通常是命名实体链接/规范化到知识库中。
3.1.3. NER:中心词作为地点的二元分类
假设我们要对中心词是否为一个地点进行二元分类。与 word2vec 类似,我们将遍历语料库中的所有
地点。但这一次,它将受到监督,只有一些地点能够得到高分。例如,在它们的中心有一个实际的 NER
Location 是“真实的”地点(例如 Paris)会获得高分(概率)。
例 3.1:如果中心词是某个地点,那么如何获得中心词的概率?
我们用四层神经网络模型进行有监督的训练,见图 3.1。模型的第四层是分类预测,可以获得中心词
的概率为 ( )。
图 3.1:NER 二元分类的四层神经网络模型
即,对于每个参数:
在深度学习中,我们也会更新数据表示(例如,词向量)!
那么,我们如何计算∇θ ( )呢?
3.1.4. 本章计划
我们将介绍两种方法:
(1) 手工矩阵演算(40 分钟);
(2) 反向传播算法(35 分钟)。
3.2. 手工矩阵演算
本节的主要目的是手工计算梯度,通过矩阵演算,得到完全矢量化的梯度。
首先,要认识到“如果你使用矩阵,多变量微积分就像单变量微积分”这个观念的重要性。矩阵计算比
非矢量化梯度更快、更有用,但是做一个非矢量化的梯度可以有利于直觉(回忆第一章)。
然后,您要多学习讲义和矩阵演算笔记,其中有详细的介绍资料。您还可以复习 Math 51,它有一本
新的在线教科书:http://web.stanford.edu/class/math51/textbook.html;或者,如果您做了 Engr108,那
么您可能会更幸运。
3.2.1. 梯度
在向量微积分中,标量场的梯度是一个向量场。标量场中某一点上的梯度指向标量场增长最快的方向,
梯度的长度是这个最大的变化率。
在单变量的实值函数的情况,梯度只是导数;或者,对于一个线性函数,梯度就是线的斜率。
3.2 手工矩阵演算 49
例 3.2:如果给定一个具有 1 个输出和 1 个输入的函数:
( )= 3
那么它的梯度(斜率)就是它的导数:
2
=3
您一定要好好思考一下这个问题:“如果我们稍微改变输入,那么输出会改变多少?”答案是:
在 x = 1 时,它的变化大约是 3 倍:1.013 = 1.03;
在 x = 4 时,它的变化大约是 48 倍:4.013 = 64.48。
=[ , , ⋯, ] (3.2)
1 2
3.2.2. 雅可比矩阵
严格地说,梯度是雅可比(Jacobian)矩阵的一个特例。因此,可以从梯度推广到雅可比矩阵。
在向量微积分中,雅可比矩阵是一阶偏导数以一定方式排列成的矩阵,其行列式称为雅可比行列式。
雅可比矩阵的重要性在于它体现了一个可微方程与给出点的最优线性逼近。因此,雅可比矩阵类似于多元
函数的导数。
如果给定具有 m 个输出和 n 个输入的函数:
( ) = [ 1 ( 1 , 2 , ⋯, ), ⋯, ( 1, 2 , ⋯, ] (3.3)
那么它的雅可比矩阵就是一个 m x n 的偏导数矩阵:
1 1
⋯
1
= ⋮ ⋱ ⋮ , 或 ( ) = (3.4)
⋯
1
3.2.3. 链式法则
链式法则是微积分中的求导法则,用以求一个复合函数的导数。所谓的复合函数,是指以一个函数作
为另一个函数的自变量。
链式法则用文字描述:由两个函数凑起来的复合函数,其导数等于里边函数代入外边函数的值之导数,
乘以里边函数的导数。
链式法则用数学描述:若 f(x)=3x,g(x)=x+3,则 g(f(x))就是一个复合函数,并且 g′(f(x))=3;若 h(x)=f(g(x)),
则 h'(x)=f'(g(x))g'(x)。
对于单变量函数的组合,链式法则是导数相乘:
z = 3y
y = x2
= =(3)(2x)=6x
对于多个变量函数的组合,链式法则是雅可比矩阵相乘:
h=f(z)
z=Wx+b
ℎ ℎ
= =⋯
50 3 神经网络学习:手工计算梯度
例 3.3:逐元激活函数雅可比矩阵。
问题:
已知
ℎ = ( ), ℎ, ∈ (3.5)
ℎ
如何求 ?
解答:
假设函数有 n 个输出和 n 个输入,即 n×n 的雅可比矩阵:
ℎ = ( ) (3.6)
则有:
ℎ ℎ
( ) = = ( ) (雅可比矩阵的定义) (3.7)
'
( ), =
= (正则一元导数) (3.8)
0, ℎ
'
( 1) ⋯
ℎ
= ⋮ ⋱ ⋮ = ( ' ( )) (3.9)
⋯ '( )
例 3.4:其他雅可比矩阵。
( + )= (3.10)
( + ) =I (单位矩阵) (3.11)
( ℎ) = ℎ (3.12)
注意:这是正确的雅可比矩阵。稍后我们将讨论“形状约定”。
在课外计算这些练习!把您的答案与课堂笔记核对一下。
3.2.3.1. 计算 /
回到我们的神经网络(见例 3.1),让我们来求解 。
图 3.2:三层神经网络模型
将方程ℎ = ( + )分解成简单的两个部分ℎ = ( ) 和 = + ,最终形成如下方程组:
= ℎ (3.13)
ℎ= ( ) (3.14)
= + (3.15)
注意:请您仔细定义变量并跟踪它们的维度!
3.2 手工矩阵演算 51
∂s
我们只要两个过程就可以求出 (见图 3.3):
∂b
= ∘ '( ) (3.17)
图 3.3:两个过程求出 = ∘ '( )
3.2.3.2. 计算 /
假设我们现在要计算 ,再次使用链式法则,则可得:
ℎ
=
ℎ
(3.18)
ℎ
= = (3.20)
ℎ
ℎ
= = ∘ '( ) (3.21)
ℎ
所以,δ可以表示本地误差信号。
3.2.3.3. 关于矩阵的导数:输出形状
52 3 神经网络学习:手工计算梯度
因为不方便再做 = − ( )计算,所以,我们离开纯数学,并使用“形状约定”:导数的
⋯
11 1
= ⋮ ⋱ ⋮ (3.22)
⋯
1
= = (3.23)
3.2.3.4. 在反向传播中推导本地输入梯度
对于如下方程:
= ( ∙ + )= =1
= (3.25)
3.2.3.5. 为什么是转置矩阵?
为什么方程 3.23 右边是转置矩阵相乘 ?
黑客(Hacky)答案:这是为了在矩阵运算时保持矩阵维度的匹配!
我们看到梯度中所有项的维度都匹配(即,当前项中的列数等于下一项中的行数),见图 3.5:
δ1 δ1 1 ⋯ δ1
= = ⋮ 1 ⋯ = ⋮ ⋱ ⋮
δn δn 1 ⋯ δn
[n × 1] [1 × m] [n × m]
图 3.5:矩阵运算时保持矩阵维度的匹配
以上经验可以当作检查您的工作的有用技巧!这在讲义的注释中有完整解释。
从图 3.5 可以看出,每个输入乘以每个输出就得到外积。
3.3 反向传播算法 53
3.2.3.6. 导数应该是什么形状?
但是“形状约定”说:我们的梯度应该是一个列向量,因为 b 是列向量……
这就使得雅可比形式(这使链式法则变得容易)和形状约定(这使 SGD 变得容易)之间存在不一致。
我们希望作业中的答案遵循形状约定,但是雅可比形式对于计算答案很有用。
因此,我们有两种选择(二选一):
(1) 尽量使用雅可比形式,最后遵循形状约定进行整形。
就像我们上面刚刚做的,但最后转置 使导数成为列向量,得到结果 。
(2) 始终遵循形状约定。
查看维度以确定何时转置和/或重新排序各项;
到达隐藏层的误差信号 与该隐藏层具有相同的维度。
3.3. 反向传播算法
我们几乎已经向您展示了反向传播,它采用导数并使用(广义、多元或矩阵)链式法则。
还展示了其他技巧:我们在计算较低层的导数时重用为较高层计算的导数以最小化计算。
3.3.1. 计算图
一般的软件都要求将神经网络方程表示为计算图。计算图包含节点和边:
(1) 源节点:接收输入。
(2) 内部节点:提供操作。
(3) 边:传递操作结果。
正向和反向的传播过程,见图 3.6:
(a)正向传播(右向箭头所示)
(b)反向传播(左向箭头所示)
图 3.6:正向传播和反向传播的计算图
从图 3.6(a)可见,正向传播过程是从最左边的输入 x(input)开始,按照右向箭头传递输入信息;
从图 3.6(b)可见,反向传播过程是从最右边的导数 = 1 开始,按照左向箭头传递导数信息。
3.3.2. 反向传播:单个节点的表示
在反向传播链上,每个节点接收“上游梯度”,它的目标是传递正确的“下游梯度”。
而且,每个节点都有“本地梯度”,即输出相对于输入的梯度,见图 3.7(a)。
54 3 神经网络学习:手工计算梯度
链式法则:
ℎ
=
ℎ
下游梯度=上游梯度 X 本地梯度
(a)单个节点的三个梯度 (b)三个梯度的链式法则
图 3.7:反向传播中单个节点的三个梯度
对上述三个梯度应用链式法则(见图 3.7(b)),则有:
ℎ
=
ℎ
下游梯度=上游梯度 X 本地梯度
3.3.3. 反向传播:单个节点多输入
推而广之,当单个节点具有多个输入时,链式法则的表示方法如图 3.8:
图 3.8:单节点多输入的链式法则表示
3.3.4. 一个例子
例 3.5:已知方程
f(x,y,z)=(x+y)max(y, z)
x=1, y=2, z=0
请用计算图展示其正向传播和反向传播过程。
解答:
1. 正向传播过程
1.1 方程分解
把方程 f(x,y,z)=(x+y)max(y, z)分解成如下方程组:
a=x+y, b=max(y,z), f=ab, 见图 3.9(a);
1.2 计算图
按照分解后的方程组,画出计算图,见图 3.9(b);
1.3 计算结果
输入初始值 x=1, y=2, z=0,并且计算每个节点的输出,得到正向传播结果,见图 3.9(c)。
3.3 反向传播算法 55
= 1, =1
求“max”节点的本地梯度:
= 1( > ) = 1,
= 1( > ) = 0
求“*”节点的本地梯度:
= = 2, = =3
(b) 求边的下游梯度
根据链式法则,
按照反向传播的过程,
分别求每条边的下游梯度
(c) 计算结果
令 =1,从最右边开始往左,
分别计算每条边的下游梯度,
最终得到:
=2
= + =2*1+3*1=5
=0
图 3.10:反向传播过程和结果
56 3 神经网络学习:手工计算梯度
2. 反向传播过程
2.1 求节点的本地梯度
分别计算“+”节点、“max”节点、“*”节点的本地梯度,见图 3.10(a);
2.2 求边的下游梯度
根据链式法则,按照反向传播的反向,分别计算每条边的下游梯度,见图 3.10(b);
2.3 计算结果
令 =1,从最右边开始往左,按照前面整理的公式,分别计算每条边的下游梯度,见图 3.10(c)。
=2*1+3*1=5
3.对三个中间节点的直觉理解(见图 3.10(c))。
3.1 “+”节点:“分配”上游梯度。例如,把上游梯度 2 分配给两个分支的下游梯度(均为 2);
3.2 “max”节点:“路由”上游梯度。例如,把上游梯度 3 路由到最大值分支的下游梯度(为 3),
而另一条分支的下游梯度为 0,即另外一条路不通。
3.3 “*”节点:“变换”上游梯度。例如,把上游梯度 1 变换到两个下游梯度(分别为 2 和 3)。
3.3.5. 效率:一次计算所有梯度
上面讲的反向传播过程,主要是为了从理论上便于正确理解其工作原理,但是实际上是不正确的。
这种不正确的反向传播方式,表现为:
然后,重复计算!
很显然,这种串行的、重复的计算,效率极其低下,所以说是不正确的方法!
(a)计算 的第一条反向传播路径
(b)计算 的第二条反向传播路径
图 3.11:不正确的两条反向传播路径
3.3 反向传播算法 57
那么,什么是正确的方法呢?
在实际应用中,正确方法是:一次性计算所有梯度(类似我们手动计算梯度时使用的δ,见方程 3.21)。
3.3.5.1. 一般计算图中的反向传播
1. 正向传播过程
1.1 按拓扑排序的顺序访问节点,在给定父节点(predecessors,例如 x)的情况下,计算当前节点(例
如,y)的值,见图 3.12 中的实线;
2. 反向传播过程
=
=1
其中:{y1...yn}是 x 的子节点。
图 3.12:一般计算图中的正向传播(实线)反向传播(虚线)
如果按照以上正确的计算步骤,那么正向传播和反向传播的复杂度相同,即 big O()水平。
通常,我们的网络是有规则的层结构,因此我们可以使用矩阵和雅可比矩阵……
3.3.5.2. 自动微分
我们可以从正向传播的符号表达式中自动推断出梯度的计算,见图 3.13(a)。
每种节点类型都需要知道如何计算其输出,以及在给定输出梯度的条件下,如何计算其输入的梯度,
见图 3.13(b)。
(a)正向传播 (b)反向传播
图 3.13:自动微分示意图
现代深度学习(DL)框架(Tensorflow、PyTorch 等)为您进行反向传播,但大体上还是留下一个编
辑网络层和节点的编写器,以便手动计算本地导数。
3.3.5.3. 正向/反向传播的实现
一般地,实现正向/反向传播的代码,见图 3.14:
58 3 神经网络学习:手工计算梯度
图 3.14:实现正向/反向传播的代码
特别地,实现正向/反向传播有专用的 API,见图 3.15:
图 3.15:实现正向/反向传播的 API
3.3.6. 手工检查数字梯度
( +ℎ)− ( −ℎ)
如果对于 ' ( ) = ,其中有一个极小的 h≈1e-4,那么很容易正确地实现,但只能得到近似
2ℎ
值,且速度非常慢,因为必须为模型的每个参数重新计算 f。
有利于检查您的实施情况的一些方法:
过去,我们手工编写一切,从头到尾每一步都这样做,这是关键的测试。
现在,这种需要少了很多,您可以只用手工检查网络图的各个层,测试它们是否正确实现。
3.4 总结 59
3.4. 总结
我们掌握了神经网络的核心技术!
前向传递:计算操作的结果并保存中间值。
反向传播:沿计算图递归地(因此有效地)应用链式法则,即:下游梯度=上游梯度 x 本地梯度。
我们为什么要了解有关梯度的所有这些细节?
因为,虽然现代深度学习框架为您计算梯度(本周五参加 PyTorch 介绍),即编译器或系统为您自动
实现正向/反向传播,但是反向传播并不总是完美的;所以,这门课可以使您了解底层工作原理,这对调试
和改进模型至关重要。
参见 Karpathy 文章(在教学大纲中):
https://medium.com/@karpathy/yes-you-should-understand-backprop-e2f06eab496b
后续课程中的示例:梯度爆炸和消失。