Neural networks and deep learning
神经网络和深度学习
Michael Nielsen/Jun 2019
迈克尔 尼尔逊/更新至2019年6月
Chapters
章节
- 1 using neural nets to recognize handwtritten digits 用神经网识别手写数字
- 2 how the back propagation works 后向传播算法工作原理
- 3 improving the way neural networks learn 改进神经网络的学习方式
- 4 a visual proof that neoral nets can compute any function 神经网能计算任何函数的可视化依据
- 5 why are neural networks hard to train 神经网络为什么难以训练
- 6 deep leaning 深度学习
第二章 后向传播算法原理
上一章,我们知道了神经网络可以使用梯度下降算法来学习他们的权值(weight)和阈值(bias)。然而,在我们的解释中,还有一个空白:我们没有讨论如何计算成本函数(cost function)的梯度(gradient)。在本章中,我会介绍一个计算梯度的快速算法,也就是后向传播算法(backpropagation)。
后向传播算法最初是在上世纪70年代提出来的,但是直到David Rumelhart,Geoffrey Hinton和Ronald Williams发表了一篇著名的论文,后向传播算法才被人们重视起来。那篇著名的论文描述了几个神经网络,其中使用的后向传播算法要比在那之前的学习算法都要快,让之前被认为不可能被解决的问题得到了解决的可能。今天,后向传播算法已然成为神经网络中的主要角色。
这一章比本书中的其他各个章节都包含更多的数学。如果你对数学不是很狂热,你可能会想着跳过这一章,把后向传播算法当成细节忽略不计的黑盒子来使用。你可能要问了,为什么要花时间学习这些细节呢?
原因很自然就是理解。
后向传播算法的核心是一个表达式,成本函数C关于任何权值w(或者阈值b)的偏微分表达式
∂
C
∂
w
\frac{\partial C}{\partial w}
∂w∂C
这个表达式告诉我们,当我们改变权值和阈值的时候成本变化的快慢。
尽管这个表达式有一些复杂,但是它也有它的美丽之处,每一个元素都有自然的、启发性的解释。所,后向传播算法并不仅仅是一个学习的快速算法,实际上,它为我们揭示了改变权值和阈值是如何影响神经网络的整体表现的。因此,后向传播算法值得我们好好学习它的细节。
热身:一个计算神经网络输出的基于矩阵理论的快速方法
在讨论后向传播算法之前,让我们从一个基于矩阵理论的计算神经网络输出的快速算法热身。
让我们用一个清楚的方式认识网络中的权值的记号:
w
j
k
l
w_{jk}^l
wjkl
这个记号表示
(
l
−
1
)
t
h
(l-1)^{th}
(l−1)th层的
k
t
h
k^{th}
kth神经元到
l
t
h
l^{th}
lth层的
j
t
h
j^{th}
jth神经元的连接。所以,如下图所示,
w
24
3
w_{24}^3
w243代表了第二层的第四个神经元到第三层的第二个神经元的连接。
这种记号开始看起来是笨重的,需要花时间掌握。但是,稍加理解你就会发现这种记号是很简单和自然的。
TIPS:其实很好理解,右上角的数字代表连接箭头指向的那一层神经元的层数,自然,该链接是由上一层指向过来的,所以一个层数就表示了两个层;右下角的两个数字,前一个表示箭头指向的层的神经元序号,后一个表示上一层的神经元序号;总而言就是用三个数字表示了两层的两个神经元位置。
我们用相类似的记号来表示网络中的阈值(bias)和激活(activations),
b
j
l
b_j^l
bjl代表
l
t
h
l^{th}
lth层的
j
t
h
j^{th}
jth个神经元的阈值(bias)(也就是右上角始终代表层数,右下角始终代表神经元序号数),
a
j
l
a_j^l
ajl代表
l
t
h
l^{th}
lth层的
j
t
h
j^{th}
jth个激活函数,如下图所示:
有了这些记号,
l
t
h
l^{th}
lth层的
j
t
h
j^{th}
jth个激活函数
a
j
l
a_j^l
ajl和
(
l
−
1
)
t
h
(l-1)^{th}
(l−1)th层就用下面的等式连接起来:
(23)
a
j
l
=
δ
(
∑
k
w
j
k
l
a
k
l
−
1
+
b
j
l
)
,
a_j^l=δ\bigg( \sum_kw_{jk}^la_k^{l-1}+b_j^l \bigg),\tag{23}
ajl=δ(k∑wjklakl−1+bjl),(23)
上式的求和是对
(
l
−
1
)
t
h
(l-1)^{th}
(l−1)th层的所有神经元进行求和。为了用矩阵的形式对上面的表达式进行重写,我们为每一层定义一个权值矩阵
w
l
w^l
wl。这个权值矩阵的元素们就是和
l
t
h
l^{th}
lth层神经元相连接的权值,也就是说,矩阵中的
j
t
h
j^{th}
jth行、
k
t
h
k^{th}
kth列元素就是
w
j
k
l
w_{jk}^l
wjkl。相类似的,我们为每一层定义一个阈值(bias)向量
b
l
b^l
bl。你大概也能猜到这是如何工作的了,阈值向量中的元素就是
l
t
h
l^{th}
lth层中的每个神经元的阈值,同样的道理,我们还可以定义激活函数向量
a
l
a^l
al。
我们需要重写式(23)的最后一个要素就是把诸如δ这样的函数向量化。
我们使用显而易见的记号
δ
(
v
)
δ(v)
δ(v)来表示这类元素化的函数。也就是说,
δ
(
v
)
j
=
δ
(
v
j
)
δ(v)_j=δ(v_j)
δ(v)j=δ(vj)。举个栗子,如果我们假设
f
(
x
)
=
x
2
f(x)=x^2
f(x)=x2,那么函数f的向量化形式如下:
(24)
f
(
[
2
3
]
)
=
[
f
(
2
)
f
(
3
)
]
=
[
4
9
]
f\bigg(\left[ \begin{matrix} 2 \\ 3 \end{matrix} \right]\bigg)=\bigg[ \begin{matrix} f(2)\\ f(3) \end{matrix}\bigg]=\bigg[ \begin{matrix} 4 \\ 9 \end{matrix}\bigg] \tag{24}
f([23])=[f(2)f(3)]=[49](24)
也就是说,向量化的函数
f
f
f把向量中的每个元素都平方了。
记住这些记号,等式(23)可以用美丽的、紧凑的向量化方式重写如下:
a
l
=
δ
(
w
l
a
l
−
1
+
b
l
)
a^l=δ(w^la^{l-1}+b^l)
al=δ(wlal−1+bl)
这个表达式为我们提供了一个整体的方法来想明白网络中的一层是如何与前一层的激活函数联系起来的,正如上式所示。
这个整体的观点通常是比我们前面提到的一个接一个的神经元的形式更简单和简洁的,并且角标更少了!我们可以把它当做一种躲避角标的方式,但是并不影响它把事情表述清楚。这个表达式在实际使用中仍然是有用的,因为大多数的矩阵函数库提供了快速计算矩阵乘法、向量相加、向量化等等。实际上,上一章的代码在计算网络的各种行为上并没有提供清楚的表达。
当我们使用等式(25)来计算
a
l
a^l
al,我们计算中间量
z
l
≡
w
l
a
l
−
1
+
b
l
z^l\equiv w^la^{l-1}+b^l
zl≡wlal−1+bl。你会发现这个中间量在后面变的非常有用,我们称其为l层的神经元的加权输入(weighted input),后面我们将会大量使用加权输入
z
l
z^l
zl。等式(25)有时候根据加权输入来表示
a
l
=
δ
(
z
l
)
a^l=δ(z^l)
al=δ(zl)。
关于成本函数,我们需要知道的两个假设
后向传播算法的目的是计算网络中的成本函数的偏微分
∂
C
∂
w
\frac{\partial C}{\partial w}
∂w∂C和
∂
C
∂
b
\frac{\partial C}{\partial b}
∂b∂C。对于后向传播函数工作,我们需要关于成本函数的形式作出两个主要的假设。
在开始陈述这两个假设之前,我们事先认识一个示例成本函数很有必要。我们使用最后一章的二次项成本函数:
(26)
C
=
1
2
n
∑
x
∣
∣
y
(
x
)
−
a
L
(
x
)
∣
∣
2
C= \frac{1}{2n}\sum_x||y(x)-a^L(x)||^2\tag{26}
C=2n1x∑∣∣y(x)−aL(x)∣∣2(26)
其中:n是训练实例的总数量,求和操作是对每个训练实例x有效的;
y
=
y
(
x
)
y=y(x)
y=y(x)是对应的输出;L代表网络中的神经层数目;
a
L
=
a
L
(
x
)
a^L=a^L(x)
aL=aL(x)是当x为输入的时候网络输出的激活函数向量。
好了,我们需要关于我们的成本函数做出什么假设使得后向传播算法足以被应用?
我们需要的第一个假设是成本函数可以对每一个训练实例
x
x
x关于成本函数
C
x
C_x
Cx写成平均值的形式:
C
=
1
n
∑
x
C
x
C=\frac{1}{n}\sum_xC_x
C=n1∑xCx
这是二次项成本函数的形式,对于每一个训练实例
x
x
x的成本函数是
C
x
=
1
2
∣
∣
y
−
a
L
∣
∣
2
C_x=\frac{1}{2}||y-a^L||^2
Cx=21∣∣y−aL∣∣2,这个假设对于所有的其他成本函数都是成立的。
事实上,知道了这个假设,我们认为训练实例
x
x
x是固定的,加上角标
x
x
x,就用
C
x
C_x
Cx代替了
C
C
C。
第二个假设是成本函数可以被重写为神经网络的一个输出函数。
比方说,二次项函数满足上面的要求,因为一个单独的训练实例的二次成本可以写成:
(27)
C
=
1
2
∣
∣
y
−
a
L
∣
∣
2
=
1
2
∑
j
(
y
j
−
a
j
L
)
2
C=\frac{1}{2}||y-a^L||^2=\frac{1}{2}\sum_j(y_j-a_j^L)^2\tag{27}
C=21∣∣y−aL∣∣2=21j∑(yj−ajL)2(27)
因此上式就是输出激活函数的一个函数。当然,这个成本函数同样依赖于我们想要得到的输出
y
y
y,你可能会好奇我们为什么不把成本也当成一个函数
y
y
y。请记住,输入的训练实例
x
x
x是固定的,所以输出
y
y
y也是一个固定的参数,并且这不是我们可以通过改变权值和阈值改变的,也就是说,这不是神经网络能学习的。
Hadamard product 哈达玛乘积
s ⊙ t s\odot t s⊙t
后向传播算法是基于普通的线性代数运算的,比如说向量相加,矩阵和向量相乘,等等。但是有一个操作是不经常使用的。尤其是当
s
s
s和
t
t
t是
未完待续,持续翻译中,敬请期待^ _ ^