1 正向传播
1.1 浅层神经网络
为简单起见,先给出如下所示的简单神经网络:
该网络只有一个隐藏层,隐藏层里有四个单元,并且只输入一个样本,该样本表示成一个三维向量,分别为为\(x_1\),\(x_2\)和\(x_3\)。网络的输出为一个标量,用\(\hat{y}\)表示。考虑该神经网络解决的问题是一个二分类的问题,把网络的输出解释为正样本的概率。比方说输入的是一张图片(当然图片不可能只用三维向量就可以表示,这里只是举个例子),该神经网络去判断图片里面是否有猫,则\(\hat{y}\)代表该图片中有猫的概率。另外,为衡量这个神经网络的分类表现,需要设置一个损失函数,针对二分类问题,最常用的损失函数是\(log-loss\)函数,该函数如下所示:
\[L(y,\hat{y}) = -y \times log(\hat{y}) - (1-y) \times log(1-\hat{y}) \tag{1}\]
上式只考虑一个样本的情况,其中\(y\)为真实值,\(\hat{y}\)为输出的概率。
1.1.1 单样本的前向传播
我们把单个输入样本用向量表示为:
\[\boldsymbol{x} =
\left[
\begin{matrix}
x_1 \ x_2 \ x_3
\end{matrix}
\right] \tag{2}
\]
那么对于隐藏层中的第一个单元,如果不考虑激活函数,则其输出可以表示为:
\[ z^{[1]}_1 = \boldsymbol{w}^{[1]^T}_1\boldsymbol{x} + b^{[1]}_1 \tag{3}\]
上式中,字母右上角的方括号中的数字代表这是神经网络的第几层,如果把输入层看作是第0层的话,那么这里的隐藏层就是第一层,字母的下标代表该层的第几个单元。\(\boldsymbol{w}^{[1]}_1\)是权重向量,即给输入向量的每个元素一个权重,这些权重组合起来就形成了\(\boldsymbol{w}^{[1]}_1\)向量,把向量和其权重作点乘,再加上一个偏置标量\(b^{[1]}_1\),就得到了该神经元的输出\(z^{[1]}_1\)。
同理可得隐藏层剩余三个单元的输出为:
\[ z^{[1]}_2 = \boldsymbol{w}^{[1]^T}_2\boldsymbol{x} + b^{[1]}_2 \tag{4}\]
\[ z^{[1]}_3 = \boldsymbol{w}^{[1]^T}_3\boldsymbol{x} + b^{[1]}_3 \tag{5}\]
\[ z^{[1]}_4 = \boldsymbol{w}^{[1]^T}_4\boldsymbol{x} + b^{[1]}_4 \tag{6}\]
但是对于每一个神经单元,其输出必须有一个非线性激活函数,否则神经网络的输出就是输入向量的线性运算得到的结果,这样会大大限制神经网络的能力。激活函数的种类有很多种,一般来说选用激活函数要视具体的应用情况而定,这里选用最常用的\(sigmoid\)激活函数。注:在1.2节之前,所有神经层都只用\(sigmoid\)激活函数。该函数的表达式如下:
\[ {\sigma}(z) = \frac{1}{1+e^{-z}} \tag{7}\]
sigmoid函数的导数和原函数的关系如下,这在具体进行计算的时候经常会用到:
\[ {\sigma}^{‘}(z) = {\sigma}(z)(1-\sigma(z)) \tag{8}\]
所以上面神经单元的计算结果需要再输入到sigmoid函数进行计算:
\[ a^{[1]}_1 = {\sigma}(z^{[1]}_1) \tag{9}\]
\[ a^{[1]}_2 = {\sigma}(z^{[1]}_2) \tag{10}\]
\[ a^{[1]}_3 = {\sigma}(z^{[1]}_3) \tag{11}\]
\[ a^{[1]}_4 = {\sigma}(z^{[1]}_4) \tag{12}\]
上面的四个式子中,上下角标的意义不变,用字母\(a\)来表示激活函数的输出结果是因为单词activation(激活)的首字母为a。
至此已经完成了从输入向量到隐藏层的输出计算,现在再计算最后一步,即从隐藏层到最终的输出。
和上述的计算过程一样,只不过这次是把隐藏层的输出作为输出层的输入,先把\(a^{[1]}_1\)到\(a^{[1]}_4\)组成一个向量:
\[\boldsymbol{a^{[1]}} =
\left[
\begin{matrix}
a^{[1]}_1 \ a^{[1]}_2 \ a^{[1]}_3 \ a^{[1]}_4
\end{matrix}
\right] \tag{13}
\]
再把该向量和对应的权重向量作点乘,最后加上一个偏置标量:
\[ z^{[2]}_1 = \boldsymbol{w}^{[2]^T}_1\boldsymbol{a^{[1]}} + b^{[2]}_1 \tag{14}\]
输出层是隐藏层的下一层,所以方括号的标注变成了2;由于输出只有一个神经单元,所以上式可省略下标:
\[ z^{[2]} = \boldsymbol{w}^{[2]^T}\boldsymbol{a^{[1]}} + b^{[2]} \tag{15}\]
同样地,把上面的结果输入到\(sigmoid\)函数里面,得到最终的输出结果:
\[ \hat{y} = a^{[2]} = {\sigma}(z^{[2]}) \tag{16}\]
单样本在神经网络的前向传播计算到这里基本已经结束了,但是上面的计算过程显得不是那么紧凑,比如在计算隐藏层的第一到第四个神经单元输出结果的时候,我们是按顺序一个一个计算的,这样的计算如果在具有非常多的神经单元的情况下,会导致最终的计算速度很慢,不高效。所以我们应当把上述的计算过程向量化,不仅使得公式更加简洁明了,而且会大大加快运算速度(很多软件包针对向量计算做了优化)。向量化的过程叙述如下:
首先考虑隐藏层中的权重向量,这些向量可以按行整合成一个矩阵:
\[\boldsymbol{W^{[1]}} =
\left[
\begin{matrix}
...\boldsymbol{w}^{[1]^T}_1 ...\ ...\boldsymbol{w}^{[1]^T}_2 ...\ ...\boldsymbol{w}^{[1]^T}_3 ...\ ...\boldsymbol{w}^{[1]^T}_4 ...
\end{matrix}
\right] \tag{17}
\]
同样地,标量\(b^{[1]}_1\)到\(b^{[1]}_4\), \(z^{[1]}_1\)到\(z^{[1]}_4\)以及\(a^{[1]}_1\)到\(a^{[1]}_4\)可以分别组成一个列向量:
\[\boldsymbol{b^{[1]}} =
\left[
\begin{matrix}
b^{[1]}_1\ b^{[1]}_2 \ b^{[1]}_3 \ b^{[1]}_4
\end{matrix}
\right] \tag{18}
\]
\[\boldsymbol{z^{[1]}} =
\left[
\begin{matrix}
z^{[1]}_1\ z^{[1]}_2 \ z^{[1]}_3 \ z^{[1]}_4
\end{matrix}
\right] \tag{19}
\]
\[\boldsymbol{a^{[1]}} =
\left[
\begin{matrix}
a^{[1]}_1\ a^{[1]}_2 \ a^{[1]}_3 \ a^{[1]}_4
\end{matrix}
\right] \tag{20}
\]
这样,式(3)-式(6)可以用向量形式表达为:
\[\boldsymbol{z^{[1]}} = \boldsymbol{W^{[1]}}\boldsymbol{x} + \boldsymbol{b^{[1]}} \tag{21}\]
其中\(\boldsymbol{W^{[1]}}\)是一个\(4\times3\)的矩阵,\(\boldsymbol{x}\)向量为\(3\times1\),二者相乘得到的维数为\(4\times1\),刚好和\(\boldsymbol{b^{[1]}}\)、\(\boldsymbol{z^{[1]}}\)的维数相同。
然后计算\(\boldsymbol{a^{[1]}}\):
\[\boldsymbol{a^{[1]}} = {\sigma}(\boldsymbol{z^{[1]}}) \tag{22}\]
\({\sigma}(\boldsymbol{z^{[1]}})\)的计算方式是,对向量\(\boldsymbol{z^{[1]}}\)中的每一个元素,依次输入到\(sigmoid\)函数中计算,最后将结果整合成一个向量。
同样可以把输出层的计算过程用向量表示:
\[\boldsymbol{z^{[2]}} = \boldsymbol{W^{[2]}}\boldsymbol{\boldsymbol{a^{[1]}}} + \boldsymbol{b^{[2]}} \tag{23}\]
\[\boldsymbol{a^{[2]}} = {\sigma}(\boldsymbol{z^{[2]}}) \tag{24}\]
其中\(\boldsymbol{W^{[2]}}\)是一个\(1\times4\)的矩阵,\(\boldsymbol{a^{[1]}}\)向量为\(4\times1\),二者相乘得到的维数为\(1\times1\),\(\boldsymbol{b^{[2]}}\)也是一个标量,所以最后的结果肯定是一个标量,也就是\(\boldsymbol{a^{[2]}}\)了,这里将\(\boldsymbol{a^{[2]}}\)和\(\boldsymbol{b^{[2]}}\)加粗是为了和向量表示相统一,实际上它并不是一个向量,除非输出的数值不止一个。
从上面的计算过程也可以总结出,权重矩阵\(\boldsymbol{W^{[l]}}\)的维数是\(n^{[l]}\times n^{[l-1]}\),偏置向量\(\boldsymbol{b^{[l]}}\)的维数是\(n^{[l]}\times 1\),其中\(l\)代表某一层,\(l-1\)则为上一层,\(n^{[l]}\)代表该层的神经单元数。
综上所述,式(21)-式(24)用向量化的方式完成了单样本输入神经网络的计算,总共就四个表达式,看起来十分简洁。
1.1.2 多样本的前向传播
在上面的例子中,我们使用的是单样本的前向传播过程,实际应用中是不可能只有一个样本的,会有很多个样本,那么针对多样本的前向传播过程又是怎么样的呢?其实过程是和单样本的过程是一样的,只不过是把输入的单个向量\(\boldsymbol{x}\)变成了矩阵\(\boldsymbol{X}\),该矩阵是把输入的每一个样本向量按列排序得到的,下面考虑m个样本,式(25)中右上角的圆括号中的数字代表样本编号:
\[
\boldsymbol{X} =
\left[
\begin{matrix}
\vdots & \vdots & & \vdots \\boldsymbol{x^{(1)}} & \boldsymbol{x^{(2)}} & \cdots & \boldsymbol{x^{(m)}} \\vdots & \vdots & & \vdots
\end{matrix}
\right] \tag{25}
\]
那么式(21)-式(24)拓展到m个样本,就可以改写为:
\[\boldsymbol{Z^{[1]}} = \boldsymbol{W^{[1]}}\boldsymbol{X} + \boldsymbol{B^{[1]}} \tag{26}\]
\[\boldsymbol{A^{[1]}} = {\sigma}(\boldsymbol{Z^{[1]}}) \tag{27}\]
\[\boldsymbol{Z^{[2]}} = \boldsymbol{W^{[2]}}\boldsymbol{\boldsymbol{A^{[1]}}} + \boldsymbol{B^{[2]}} \tag{28}\]
\[\boldsymbol{A^{[2]}} = {\sigma}(\boldsymbol{Z^{[2]}}) \tag{29}\]
式(26)-式(29)相对于式(21)-式(24)唯一的变化就是把z、a和b由向量表示转变为矩阵表示,具体的来看,比方说\(\boldsymbol{Z^{[1]}}\)、\(\boldsymbol{B^{[1]}}\)和\(\boldsymbol{A^{[1]}}\)可类似于\(\boldsymbol{X}\)展开为:
\[
\boldsymbol{Z^{[1]}} =
\left[
\begin{matrix}
\vdots & \vdots & & \vdots \\boldsymbol{z^{(1)^{[1]}}} & \boldsymbol{z^{(2)^{[1]}}} & \cdots & \boldsymbol{z^{(m)^{[1]}}} \\vdots & \vdots & & \vdots
\end{matrix}
\right] \tag{30}
\]
\[
\boldsymbol{B^{[1]}} =
\left[
\begin{matrix}
\vdots & \vdots & & \vdots \\boldsymbol{b^{(1)^{[1]}}} & \boldsymbol{b^{(2)^{[1]}}} & \cdots & \boldsymbol{b^{(2)^{[1]}}} \\vdots & \vdots & & \vdots
\end{matrix}
\right] \tag{31}
\]
\[
\boldsymbol{A^{[1]}} =
\left[
\begin{matrix}
\vdots & \vdots & & \vdots \\boldsymbol{a^{(1)^{[1]}}} & \boldsymbol{a^{(2)^{[1]}}} & \cdots & \boldsymbol{a^{(2)^{[1]}}} \\vdots & \vdots & & \vdots
\end{matrix}
\right] \tag{32}
\]
如果觉得矩阵表示较为抽象,就可以应用这种展开方式方便理解。另外要注意,对于上面的矩阵\(\boldsymbol{B^{[1]}}\),其中的各个列向量\(\boldsymbol{b^{(1)^{[1]}}}\)和\(\boldsymbol{b^{(2)^{[1]}}}\)等等,其实是完全一样的,就是同一个列向量重复地排了\(m\)列,正如权重矩阵\(\boldsymbol{W^{[l]}}\)不会随着样本的个数变化一样,偏置向量也是不会随着样本的不同而不同的。总而言之,对于同一个神经层,权重矩阵和偏置向量对于所有样本相同。从中可见式(26)-式(29)的维数也是正确的,例如式(26)中,\(\boldsymbol{W^{[1]}}\)维数是\(4\times3\),\(\boldsymbol{X}\)的维数是\(3\times m\),二者相乘的维数是\(4\times m\),而\(\boldsymbol{B^{[1]}}\)以及\(\boldsymbol{Z^{[1]}}\)的维数均是\(4\times m\),所以式(26)在维度上完全正确,余下的几个式子的维数分析同理。最后输出的是m个样本的计算结果:\(\boldsymbol{A^{[2]}}\),它是把每个样本单独输出的结果按列排列得到,这和之前所有样本均按列排列的方式是一致的。至此也完成了m个样本在浅层神经网络的正向传播过程。
1.2 深层神经网络
利用浅层神经网络的分析结果,我们很容易把正向传播过程推广到深层神经网络上,即不再像本文开始提出的那种只有一个隐藏层并且只有4个隐藏神经单元的神经网络,可以有很多个隐藏层,每个隐藏层也可以有很多个神经单元,也不再限定输入的是一个三维向量,输入的可以为任意维向量,当然,每个样本的向量维度必须一致,否则神经网络没法工作,同时网络的输出也可不限定为一个数值,可以输出一个向量以适应多分类的任务,即一个样本会有多个标签,输出向量表示该样本属于这些标签的概率值。最后作为一般概括,也不指定具体的激活函数,即激活函数在这里用\(g^{[l]}(x)\)表示。这样,我们可以把整个正向传输过程浓缩成:
\[\boldsymbol{Z^{[l]}} = \boldsymbol{W^{[l]}}\boldsymbol{A^{[l-1]}} + \boldsymbol{b^{[l]}} \tag{33}\]
\[\boldsymbol{A^{[l]}} = g^{[l]}(\boldsymbol{Z^{[l]}}) \tag{34}\]
上式中某一层用\(l\)表示,它的上一层用\(l-1\)来表示,这里规定输入层\(l=0\),第一个隐藏层\(l=1\),后面以此类推,即有\(1 \leq l \leq N\),\(N\)为输出层编号。所以上面两个式子的计算过程就是输入上一层计算的\(\boldsymbol{A^{[l-1]}}\),再输出本层的\(\boldsymbol{A^{[l]}}\),一直持续计算到输出层,最后得到计算的最终结果。需要注意的一点是对于第一个隐藏层,它的输入就是样本矩阵,也就是\(\boldsymbol{A^{[0]}} = \boldsymbol{X}\)。注意到式(33)我们没有用大写的\(\boldsymbol{B^{[l]}}\)来代表偏置矩阵,而是用了小写的向量记法,代表的是一个列向量,这是为了后续反向传播推导的方便,但是我们心里应该明白,这里一个矩阵和一个向量相加,相加的方法是矩阵的每一列分别和该列向量相加,这样就和原大写的矩阵相加结果相同,因为前面已经指出,矩阵\(\boldsymbol{B^{[l]}}\)就是单个列向量扩展\(m\)列得到的。
最后再来总结式(33)-式(34)中每个元素的维数,根据浅层神经网络的推导,我们也很容易把结论扩展到深层神经网络里面。以\(n^{[l]}\)表示该层的神经单元的个数(输入层\(n^{[0]}\)等于输入样本矩阵的行数,即单个样本向量的元素个数),m表示样本个数,则结论如下:
\[ \boldsymbol{W^{[l]}} \in \mathbb{R}^{n^{[l]} \times n^{[l-1]}} \tag{35}\]
\[ \boldsymbol{b^{[l]}} \in \mathbb{R}^{n^{[l]} \times 1} \tag{36}\]
\[ \boldsymbol{Z^{[l]}} \in \mathbb{R}^{n^{[l]} \times m} \tag{37}\]
\[ \boldsymbol{A^{[l]}} \in \mathbb{R}^{n^{[l]} \times m} \tag{38}\]
2 反向传播
现在来考虑反向传播的过程,该过程是一个不断迭代的过程,目的是寻找使得损失函数最小的参数,即每一个神经层的权重矩阵和偏置向量的数值。首先考虑单个样本在深层神经网络的反向传播的情况。
2.1 单样本的反向传播
计算反向传播的过程,我们首先要定义一个损失函数,为了不失一般性,这里用\(L(\boldsymbol{y}, \boldsymbol{\hat y})\)表示损失函数,其中\(\boldsymbol{y}\)为样本的真实标签,\(\boldsymbol{\hat y}\)为样本在神经网络中的计算结果。损失函数应当越小越好,越小就代表我们计算出的结果和样本的真实标签越接近。为和前面的章节相连贯,接下来我们考虑的是作为分类任务用的神经网络,即每一层包括输出层都会有一个激活函数,注意如果是回归任务,输出层是不需要激活函数的,因为激活函数会把输出结果限定在一个范围内,这对回归任务并不适用。我们记作\(g(x)^{[l]}\),\(l\)代表某一层。
针对单个样本,可记作:
\[\boldsymbol{a^{[0]}} = \boldsymbol{x} =
\left[
\begin{matrix}
x_1 \ x_2 \ \vdots \ x_{n^{[0]}}
\end{matrix}
\right] \tag{39}
\]
\(n^{[l]}\)表示\(l\)层的神经单元的个数,输入层的\(l\)记作0。那么后面的计算就可利用下面两个式子反复进行,其中\(1\leq l \leq N\),N为输出层编号。一直进行到输出层得出结果:
\[\boldsymbol{z^{[l]}} = \boldsymbol{W^{[l]}}\boldsymbol{a^{[l-1]}} + \boldsymbol{b^{[l]}} \tag{40}\]
\[\boldsymbol{a^{[l]}} = g^{[l]}(\boldsymbol{z^{[l]}}) \tag{41}\]
假设神经网络一共有N层,我们则把最后的输出结果记作\(\boldsymbol{a^{[N]}}\),也就是\(\boldsymbol{\hat{y}}\)。利用损失函数最终得到损失值,我们的任务就是最小化这个数值,如何最小化?那么就必须调节参数\(\boldsymbol{W^{[l]}}\)和\(\boldsymbol{b^{[l]}}\),这时候就需要用到反向传播算法了,即正向传播计算的是神经网络的输出值,而反向传播则计算修改后的网络参数,不断地进行正向反向传播,每一个正反来回都对这两个参数进行更新,再计算神经网络在参数更新后的损失值,和原来的损失值作比较,变小了就继续进行参数更新,反之则考虑是否停止参数更新,结束神经网络的计算。参数更新的过程如下所示,其中\(1\leq l\leq N\):
\[\boldsymbol{W^{[l]}} = \boldsymbol{W^{[l]}} - \alpha \times d\boldsymbol{W^{[l]}} \tag{42}\]
\[\boldsymbol{b^{[l]}} = \boldsymbol{b^{[l]}} - \alpha \times d\boldsymbol{b^{[l]}} \tag{43}\]
式中,\(d\boldsymbol{W^{[l]}}\)和\(d\boldsymbol{b^{[l]}}\)分别代表损失函数对这二者的求偏导的结果,即:
\[d{\boldsymbol{W^{[l]}}} = \frac{\partial L}{\partial{\boldsymbol{W^{[l]}}}} \tag{44}\]
\[d{\boldsymbol{b^{[l]}}} = \frac{\partial L}{\partial{\boldsymbol{b^{[l]}}}} \tag{45}\]
而\(\alpha\)代表参数更新的步长,称作学习率。问题的关键就在于怎么求出\(d\boldsymbol{W^{[l]}}\)和\(d\boldsymbol{b^{[l]}}\),这时候就需要考虑导数的链式法则了。反向传播的起点在最后一步,即损失函数这一步,从输出层开始再一层一层地往回计算,所以先考虑损失函数\(L(\boldsymbol{a^{[N]}} \boldsymbol{\hat y})\)和输出层参数,即先计算出\(d\boldsymbol{W^{[N]}}\)和\(d\boldsymbol{b^{[N]}}\),先考虑前者,根据链式法则,很容易得出下式:
\[\begin{align*}
d{\boldsymbol{W^{[N]}}} &= \frac{\partial L}{\partial{\boldsymbol{W^{[N]}}}} \ &= \frac{\partial L}{\partial{\boldsymbol{a^{[N]}}}} \frac{\partial{\boldsymbol{a^{[N]}}}}{\partial{\boldsymbol{W^{[N]}}}} \ &= \frac{\partial L}{\partial{\boldsymbol{a^{[N]}}}} \frac{\partial{\boldsymbol{a^{[N]}}}}{\partial{\boldsymbol{z^{[N]}}}} \frac{\partial{\boldsymbol{z^{[N]}}}}{\partial{\boldsymbol{W^{[N]}}}}
\end{align*} \tag{46}
\]
可见计算\(d{\boldsymbol{W^{[N]}}}\)共需三步,即分别计算\(\frac{\partial L}{\partial{\boldsymbol{a^{[N]}}}}\),\(\frac{\partial{\boldsymbol{a^{[N]}}}}{\partial{\boldsymbol{z^{[N]}}}}\)和\(\frac{\partial{\boldsymbol{z^{[N]}}}}{\partial{\boldsymbol{W^{[N]}}}}\),然后相乘即可。
首先\(\boldsymbol{a^{[N]}}\)求偏导得到:
\[d{\boldsymbol{a^{[N]}}} = \frac{\partial L}{\partial{\boldsymbol{a^{[N]}}}} \tag{47}\]
式(47)的具体计算结果依赖于具体的损失函数L,由于我们作一般化考虑,所以到此为止,不再继续计算下去。然后根据式(41)又有:
\[\frac{\partial{\boldsymbol{a^{[N]}}}}{\partial{\boldsymbol{z^{[N]}}}} = {g^{[N]}}^{\prime}(\boldsymbol{z^{[N]}}) \tag{48}\]
再根据式(40),得到:
\[\frac{\partial{\boldsymbol{z^{[N]}}}}{\partial{\boldsymbol{W^{[N]}}}} = \boldsymbol{a^{[N-1]}} \tag{49}\]
综合式(47)-式(48),可以得到:
\[
\begin{align*}
d{\boldsymbol{z^{[N]}}} &= \frac{\partial L}{\partial{\boldsymbol{a^{[N]}}}}\frac{\partial{\boldsymbol{a^{[N]}}}} {\partial{\boldsymbol{z^{[N]}}}} \ &= d{\boldsymbol{a^{[N]}}}{g^{[N]}}^{\prime}(\boldsymbol{z^{[N]}})
\end{align*}
\tag{50}
\]
但是要注意的是,式(50)并不正确,因为维度不匹配。各元素维度为:
\[d{\boldsymbol{z^{[N]}}} \in \mathbb{R}^{n[N]\times 1} \tag{51}\]
\[d{\boldsymbol{a^{[N]}}} \in \mathbb{R}^{n[N]\times 1} \tag{52}\]
\[{g^{[N]}}^{\prime}(\boldsymbol{z^{[N]}}) \in \mathbb{R}^{n[N]\times 1} \tag{53}\]
所以改写式(50)使其满足正确的维度:
\[
\begin{align*}
d{\boldsymbol{z^{[N]}}} &= \frac{\partial L}{\partial{\boldsymbol{a^{[N]}}}}\frac{\partial{\boldsymbol{a^{[N]}}}} {\partial{\boldsymbol{z^{[N]}}}} \ &= d{\boldsymbol{a^{[N]}}}\circ{g^{[N]}}^{\prime}(\boldsymbol{z^{[N]}})
\end{align*}
\tag{54}
\]
式(54)中的空心圆点代表这两个向量对应元素进行相乘。再把式(54)和式(49)联立,可得:
\[
d{\boldsymbol{W^{[N]}}} = d{\boldsymbol{z^{[N]}}}\boldsymbol{a^{[N-1]}}
\tag{55}
\]
同样地,式(55)也不满足正确的维度。各元素的维度为:
\[d{\boldsymbol{z^{[N]}}} \in \mathbb{R}^{n[N]\times 1} \tag{56}\]
\[\boldsymbol{a^{[N-1]}} \in \mathbb{R}^{n[N]\times 1} \tag{57}\]
\[d{\boldsymbol{W^{[N]}}} \in \mathbb{R}^{n[N]\times n[N-1]} \tag{58}\]
改写式(55)使其满足正确的维度:
\[
d{\boldsymbol{W^{[N]}}} = d{\boldsymbol{z^{[N]}}}\boldsymbol{{a^{[N-1]}}^T}
\tag{59}
\]
至此已经完成了\(d{\boldsymbol{W^{[N]}}}\)的计算,那么还剩下\(d{\boldsymbol{b^{[N]}}}\)还没有计算,计算它就简单多了,因为根据式(40),\(d{\boldsymbol{b^{[N]}}}\)就等于\(d{\boldsymbol{z^{[N]}}}\),所以有:
\[
\begin{align*}
d{\boldsymbol{b^{[N]}}} &= d{\boldsymbol{z^{[N]}}} \ &= d{\boldsymbol{a^{[N]}}}\circ{g^{[N]}}^{\prime}(\boldsymbol{z^{[N]}})
\end{align*}
\tag{60}
\]
\(d{\boldsymbol{W^{[N]}}}\)和\(d{\boldsymbol{b^{[N]}}}\)都计算出来之后,就可以利用式(42)-式(43)更新参数了:
\[\boldsymbol{W^{[N]}} = \boldsymbol{W^{[N]}} - \alpha \times d\boldsymbol{W^{[N]}} \tag{61}\]
\[\boldsymbol{b^{[N]}} = \boldsymbol{b^{[N]}} - \alpha \times d\boldsymbol{b^{[N]}} \tag{62}\]
下面再来考虑\(d{\boldsymbol{W^{[N-1]}}}\)和\(d{\boldsymbol{b^{[N-1]}}}\)的计算,即输出层的上一层,也就是最后一个隐藏层的参数。事实上,根据式(59)-式(60),就可以进行计算了,不过是把N换成N-1而已,但是这里有个问题是\(d{\boldsymbol{a^{[N-1]}}}\)没法得出,所以关键就是把它的表达式给求出来。根据式(40)-式(41),再应用链式法则,不难得到:
\[
\begin{align*}
d{\boldsymbol{a^{[N-1]}}} &= \frac{\partial L}{\partial{\boldsymbol{a^{[N-1]}}}} \ &= \frac{\partial L}{\partial{\boldsymbol{a^{[N]}}}} \frac{\partial{\boldsymbol{a^{[N]}}}}{\partial{\boldsymbol{z^{[N]}}}} \frac{\partial{\boldsymbol{z^{[N]}}}}{\partial{\boldsymbol{a^{[N-1]}}}}
\end{align*}
\tag{63}
\]
式(63)可整理如下:
\[
\begin{align*}
d{\boldsymbol{a^{[N-1]}}} &= \frac{\partial L}{\partial{\boldsymbol{a^{[N]}}}} \frac{\partial{\boldsymbol{a^{[N]}}}}{\partial{\boldsymbol{z^{[N]}}}} \frac{\partial{\boldsymbol{z^{[N]}}}}{\partial{\boldsymbol{a^{[N-1]}}}} \ &= d{\boldsymbol{z^{[N]}}}{\boldsymbol{W^{[N]}}}
\end{align*}
\tag{64}
\]
式(64)的维度也是有问题的,整理如下,使得元素维度匹配:
\[
\begin{align*}
d{\boldsymbol{a^{[N-1]}}} &= \frac{\partial L}{\partial{\boldsymbol{a^{[N]}}}} \frac{\partial{\boldsymbol{a^{[N]}}}}{\partial{\boldsymbol{z^{[N]}}}} \frac{\partial{\boldsymbol{z^{[N]}}}}{\partial{\boldsymbol{a^{[N-1]}}}} \ &= {\boldsymbol{W^{[N]}}}^Td{\boldsymbol{z^{[N]}}}
\end{align*}
\tag{65}
\]
目前为止,基本完成了单个样本的反向传播过程,主要过程、公式整理如下:
对于输出层有:
\[d{\boldsymbol{a^{[N]}}} = \frac{\partial L}{\partial{\boldsymbol{a^{[N]}}}} \tag{66}\]
\[
\begin{align*}
d{\boldsymbol{z^{[N]}}} &= \frac{\partial L}{\partial{\boldsymbol{a^{[N]}}}}\frac{\partial{\boldsymbol{a^{[N]}}}} {\partial{\boldsymbol{z^{[N]}}}} \ &= d{\boldsymbol{a^{[N]}}}\circ{g^{[N]}}^{\prime}(\boldsymbol{z^{[N]}})
\end{align*}
\tag{67}
\]
\[
d{\boldsymbol{W^{[N]}}} = d{\boldsymbol{z^{[N]}}}\boldsymbol{{a^{[N-1]}}^T}
\tag{68}
\]
\[
\begin{align*}
d{\boldsymbol{b^{[N]}}} &= d{\boldsymbol{z^{[N]}}} \ &= d{\boldsymbol{a^{[N]}}}\circ{g^{[N]}}^{\prime}(\boldsymbol{z^{[N]}})
\end{align*}
\tag{69}
\]
其中\(d{\boldsymbol{a^{[N]}}}\)是可以直接利用损失函数进行求导计算得出,而对于其他神经层则需要利用链式法则来求出。设\(h\)为为任意隐藏层,即\(1\leq h \leq N-1\),则有:
\[
\begin{align*}
d{\boldsymbol{a^{[h]}}} &= \frac{\partial L}{\partial{\boldsymbol{a^{[h+1]}}}} \frac{\partial{\boldsymbol{a^{[h+1]}}}}{\partial{\boldsymbol{z^{[h+1]}}}} \frac{\partial{\boldsymbol{z^{[h+1]}}}}{\partial{\boldsymbol{a^{[h]}}}} \ &= {\boldsymbol{W^{[h+1]}}}^Td{\boldsymbol{z^{[h+1]}}}
\end{align*}
\tag{70}
\]
\[
\begin{align*}
d{\boldsymbol{z^{[h]}}} &= \frac{\partial L}{\partial{\boldsymbol{a^{[h]}}}}\frac{\partial{\boldsymbol{a^{[h]}}}} {\partial{\boldsymbol{z^{[h]}}}} \ &= d{\boldsymbol{a^{[h]}}}\circ{g^{[h]}}^{\prime}(\boldsymbol{z^{[h]}})
\end{align*}
\tag{71}
\]
\[
d{\boldsymbol{W^{[h]}}} = d{\boldsymbol{z^{[h]}}}\boldsymbol{{a^{[h-1]}}^T}
\tag{72}
\]
\[
\begin{align*}
d{\boldsymbol{b^{[h]}}} &= d{\boldsymbol{z^{[h]}}} \ &= d{\boldsymbol{a^{[h]}}}\circ{g^{[h]}}^{\prime}(\boldsymbol{z^{[h]}})
\end{align*}
\tag{73}
\]
最后的参数更新只需按照下面式子来进行即可,其中\(1 \leq l \leq N\):
\[\boldsymbol{W^{[l]}} = \boldsymbol{W^{[l]}} - \alpha \times d\boldsymbol{W^{[l]}} \tag{74}\]
\[\boldsymbol{b^{[l]}} = \boldsymbol{b^{[l]}} - \alpha \times d\boldsymbol{b^{[l]}} \tag{75}\]
2.2 多样本的反向传播
考虑\(m\)个样本,各种符号表示以及解释参考式(25)-式(32)。损失函数则定义为所有样本损失值的平均值,即有如下定义:
\[
J(\boldsymbol{W}, \boldsymbol{b}) = \frac{1}{m}\Sigma^{m}_{i=1}L(\boldsymbol{y^{(i)}}, \boldsymbol{\hat y^{(i)}})
\tag{76}
\]
总的损失函数值是所有样本的损失值的平均,那么权值参数\(\boldsymbol{W^{[l]}}\)和偏置参数\(\boldsymbol{b^{[l]}}\)也应当是考虑了所有的样本计算后的平均。同样地,先考虑输出层的参数,利用式(66)-式(69)可得:
\[d{\boldsymbol{A^{[N]}}} = \frac{\partial J}{\partial{\boldsymbol{A^{[N]}}}} \tag{77}\]
\[
\begin{align*}
d{\boldsymbol{Z^{[N]}}} &= \frac{\partial J}{\partial{\boldsymbol{A^{[N]}}}}\frac{\partial{\boldsymbol{A^{[N]}}}} {\partial{\boldsymbol{z^{[N]}}}} \ &= d{\boldsymbol{A^{[N]}}}\circ{g^{[N]}}^{\prime}(\boldsymbol{Z^{[N]}})
\end{align*}
\tag{78}
\]
\[
d{\boldsymbol{W^{[N]}}} = \frac{1}{m}d{\boldsymbol{Z^{[N]}}}\boldsymbol{{A^{[N-1]}}^T}
\tag{79}
\]
\[
\begin{align*}
d{\boldsymbol{b^{[N]}}} &= \frac{1}{m}sum(d{\boldsymbol{Z^{[N]}}},axis=1) \ &= \frac{1}{m}sum(d{\boldsymbol{A^{[N]}}}\circ{g^{[N]}}^{\prime}(\boldsymbol{Z^{[N]}}), axis=1)
\end{align*}
\tag{80}
\]
注意的是式(80),列向量\(d{\boldsymbol{b^{[N]}}}\)是通过\(d{\boldsymbol{Z^{[N]}}}\)矩阵取每一行的平均值得到的,在直觉上也不难理解,矩阵\(d{\boldsymbol{Z^{[N]}}}\)是每个样本的\(d{\boldsymbol{z^{[N]}}}\)按列排列得到的,而\(d{\boldsymbol{b^{[N]}}}\)需要对每个样本的\(d{\boldsymbol{b^{[N]}}}\)求平均而得到,式(80)的做法正符合这一要求。至于式(78)只要将矩阵相乘的结果除以样本个数,这种做法可以将两个矩阵拆开来看,可以发现\(d{\boldsymbol{W^{[N]}}}\)确实也是综合考虑了所有样本的\(d{\boldsymbol{W^{[N]}}}\),然后求平均得到,具体请自行操作体会。
对于所有隐藏层,对式(70)-式(73)进行同样的改动,即可获得相应结果。设\(h\)为为任意隐藏层,即\(1\leq h \leq N-1\),则有:
\[
\begin{align*}
d{\boldsymbol{A^{[h]}}} &= \frac{\partial J}{\partial{\boldsymbol{A^{[h+1]}}}} \frac{\partial{\boldsymbol{A^{[h+1]}}}}{\partial{\boldsymbol{Z^{[h+1]}}}} \frac{\partial{\boldsymbol{Z^{[h+1]}}}}{\partial{\boldsymbol{A^{[h]}}}} \ &= {\boldsymbol{W^{[h+1]}}}^Td{\boldsymbol{Z^{[h+1]}}}
\end{align*}
\tag{81}
\]
\[
\begin{align*}
d{\boldsymbol{Z^{[h]}}} &= \frac{\partial J}{\partial{\boldsymbol{A^{[h]}}}}\frac{\partial{\boldsymbol{A^{[h]}}}} {\partial{\boldsymbol{Z^{[h]}}}} \ &= d{\boldsymbol{A^{[h]}}}\circ{g^{[h]}}^{\prime}(\boldsymbol{Z^{[h]}})
\end{align*}
\tag{82}
\]
\[
d{\boldsymbol{W^{[h]}}} = \frac{1}{m}d{\boldsymbol{Z^{[h]}}}\boldsymbol{{A^{[h-1]}}^T}
\tag{83}
\]
\[
\begin{align*}
d{\boldsymbol{b^{[h]}}} &= \frac{1}{m}sum(d{\boldsymbol{Z^{[h]}}}, axis=1) \ &= \frac{1}{m}sum(d{\boldsymbol{A^{[h]}}}\circ{g^{[h]}}^{\prime}(\boldsymbol{Z^{[h]}}), axis=1)
\end{align*}
\tag{84}
\]
最后,更新参数的方法同式(74)-式(75),现在,神经网络的正反向传播算法基本推导完毕。
原文地址:https://www.cnblogs.com/excellent-ship/p/9085672.html