花书+吴恩达深度学习(三)反向传播算法 Back Propagation

目录

0. 前言

1. 从 Logistic Regression 中理解反向传播

2. 两层神经网络中单个样本的反向传播

3. 两层神经网络中多个样本的反向传播


如果这篇文章对你有一点小小的帮助,请给个关注,点个赞喔~我会非常开心的~

花书+吴恩达深度学习(一)前馈神经网络(多层感知机 MLP)

花书+吴恩达深度学习(二)非线性激活函数(ReLU, maxout, sigmoid, tanh)

花书+吴恩达深度学习(三)反向传播算法 Back Propagation

花书+吴恩达深度学习(四)多分类 softmax

0. 前言

在神经网络中,通过前向传播,将线性拟合和非线性激活的计算结果传递至最后一层 \hat{y} 。

然后通过反向传播,从最后一层进行梯度计算,每一层使用到了后面一层的计算结果对各自的参数进行修改,直到输入层。

本篇文章通过几个例子层层递进,理解反向传播算法。

1. 从 Logistic Regression 中理解反向传播

如下图所示,为单个样本通过 LR 单元:

花书+吴恩达深度学习(三)反向传播算法 Back Propagation_第1张图片

其中,样本有两个特征,前向传播通过线性单元和非线性激活函数 sigmoid ,得出结果,然后计算损失函数。

损失函数采用:

\mathfrak{L}(a,y)=y\log(a)+(1-y)\log(1-a)

反向传播中,首先对最后一层的输出计算梯度:

\frac{\mathrm{d} \mathfrak{L}}{\mathrm{d} a}= -\frac{y}{a}+\frac{1-y}{1-a}

其次,对倒数第二层的输出计算梯度:

\frac{\mathrm{d} \mathfrak{L}}{\mathrm{d} z}=\frac{\mathrm{d} \mathfrak{L}}{\mathrm{d} a}\frac{\mathrm{d} a}{\mathrm{d} z}=(-\frac{y}{a}+\frac{1-y}{1-a})\cdot a(1-a)=a-y

然后,求出了对 z 的梯度之后,可以计算对参数的梯度:

\begin{align*} & \frac{\partial \mathfrak{L}}{\partial w_j}=\frac{\mathrm{d} \mathfrak{L}}{\mathrm{d} z}\frac{\partial z}{\partial w_j}=(a-y)x_j \\ & \frac{\partial \mathfrak{L}}{\partial b}=\frac{\mathrm{d} \mathfrak{L}}{\mathrm{d} z}\frac{\partial z}{\partial b}=(a-y) \end{align*}

最后,就可以使用梯度下降的方法对参数进行修改。

在每一层计算梯度的过程中,都使用到了后面一层的计算结果,可以看成是梯度的计算从后面不断的往前面传递的反向传播

2. 两层神经网络中单个样本的反向传播

在 logistic regression 的例子中,可以看成是一个神经元的反向传播。

现在,我们构建一个两层多个神经元的神经网络:

花书+吴恩达深度学习(三)反向传播算法 Back Propagation_第2张图片

我们对其进行向量化,单个样本表示为 X ,维度 (2,1) 。

第一层网络中,参数权重表示为 W^{[1]} ,维度 (3,2) ,每一行表示每一个神经元,每一列表示对应上层输入的每个特征。

参数截距表示为 B^{[1]} ,维度 (3,1) ,每一行表示每一个神经元,输出 Z^{[1]}\ A^{[1]} ,维度 (3,1) ,每一行表示每一个神经元的输出。

第二层网络中,参数权重表示为 W^{[2]} ,维度 (1,3) ,参数截距表示为 B^{[2]} ,维度 (1,1) ,输出 Z^{[2]}\ A^{[2]} ,维度 (1,1) ,最终输出。

输出层的激活函数仍然采用合适的 sigmoid 函数。

前向传播表示为:

\begin{align*} & Z^{[1]}=W^{[1]}X+B^{[1]} \\ & A^{[1]}=g^{[1]}(Z^{[1]}) \\ & Z^{[2]}=W^{[2]}A^{[1]}+B^{[2]} \\ & A^{[2]}=g^{[2]}(Z^{[2]}) \\ \end{align*}

反向传播中,所有对应变量梯度的维度,与对应变量的维度是相同的。

首先,对第二层网络的 Z^{[2]} 求梯度:

\mathrm{d} Z^{[2]}=\frac{\partial \mathfrak{L}}{\partial Z^{[2]}}=\frac{\partial \mathfrak{L}}{\partial A^{[2]}}\frac{\partial A^{[2]}}{\partial Z^{[2]}}=A^{[2]}-y

解释:因 A^{[2]} 的维度 (1,1) ,单个样本,所以与上一个例子最后一层的梯度求解相同。

然后,求出了 Z^{[2]} 后,可对参数进行梯度求解:

\mathrm{d} W^{[2]}=\frac{\partial \mathfrak{L}}{\partial W^{[2]}}=\frac{\partial \mathfrak{L}}{\partial Z^{[2]}}\frac{\partial Z^{[2]}}{\partial W^{[2]}}=\mathrm{d} Z^{[2]}\cdot (A^{[1]})^T

\mathrm{d} B^{[2]}=\frac{\partial \mathfrak{L}}{\partial B^{[2]}}=\frac{\partial \mathfrak{L}}{\partial Z^{[2]}}\frac{\partial Z^{[2]}}{\partial B^{[2]}}=\mathrm{d} Z^{[2]}

解释:上述链式求导的第二项中,可分解为对函数 Z^{[2]}=W^{[2]}_1A^{[1]}_1+W^{[2]}_2A^{[1]}_2+W^{[2]}_3A^{[1]}_3+B^{[2]} 求导,则分别为 A^{[1]}_1\ A^{[1]}_2\ A^{[1]}_3 ,用向量表示,则为 (A^{[1]})^T 。

接着,对第一层网络求解梯度:

\mathrm{d} Z^{[1]}=\frac{\partial \mathfrak{L}}{\partial Z^{[1]}}=\frac{\partial \mathfrak{L}}{\partial Z^{[2]}}\frac{\partial Z^{[2]}}{\partial A^{[1]}}\frac{\partial A^{[1]}}{\partial Z^{[1]}}=(W^{[2]})^T\cdot \mathrm{d} Z^{[2]}\ *\ {g^{[1]}(Z^{[1]})}'

解释:上述链式求导的第二项中,可分解为对函数 Z^{[2]}=W^{[2]}_1A^{[1]}_1+W^{[2]}_2A^{[1]}_2+W^{[2]}_3A^{[1]}_3+B^{[2]} 求导,则分别为 W^{[2]}_1\ W^{[2]}_2\ W^{[2]}_3 ,用向量表示,则为 (W^{[2]})^T 。* 表示元素对应相乘(点乘)。可验算,dZ^{[1]} 与 Z^{[1]} 维度相同。

然后,就可以对参数进行梯度求解:

\mathrm{d} W^{[1]}=\frac{\partial \mathfrak{L}}{\partial W^{[1]}}=\frac{\partial \mathfrak{L}}{\partial Z^{[1]}}\frac{\partial Z^{[1]}}{\partial W^{[1]}}=\mathrm{d} Z^{[1]}\cdot X^T

\mathrm{d} B^{[1]}=\frac{\partial \mathfrak{L}}{\partial B^{[1]}}=\frac{\partial \mathfrak{L}}{\partial Z^{[1]}}\frac{\partial Z^{[1]}}{\partial B^{[1]}}=\mathrm{d} Z^{[1]}

最后,就可使用梯度下降法,对网络中的每个神经元进行更新。

3. 两层神经网络中多个样本的反向传播

在上述例子中,仅使用了一个样本,少数的神经元,进行计算。

现在,我们构建一个两层更多个神经元,对多个样本进行计算的神经网络:

花书+吴恩达深度学习(三)反向传播算法 Back Propagation_第3张图片

单个样本表示为 X ,维度 (n_0,m) 。

第一层网络中,参数权重表示为 W^{[1]} ,维度 (n_1,n_0) ,每一行表示每一个神经元,每一列表示对应上层输入的每个特征。

参数截距表示为 B^{[1]} ,维度 (n_1,1) ,每一行表示每一个神经元,输出 Z^{[1]}\ A^{[1]} ,维度 (n_1,m) ,每一行表示每一个神经元的输出。

第二层网络中,参数权重表示为 W^{[2]} ,维度 (1,n_1) ,参数截距表示为 B^{[2]} ,维度 (1,1) ,输出 Z^{[2]}\ A^{[2]} ,维度 (1,m) ,最终输出。

输出层的激活函数仍然采用合适的 sigmoid 函数。

反向传播与上述例子相似,只是在求解参数梯度处有变化。

首先,对第二层网络的 Z^{[2]} 求梯度:

\mathrm{d} Z^{[2]}=\frac{\partial \mathfrak{L}}{\partial Z^{[2]}}=\frac{\partial \mathfrak{L}}{\partial A^{[2]}}\frac{\partial A^{[2]}}{\partial Z^{[2]}}=A^{[2]}-Y

解释:与上述例子不同之处在于,这里表示的是一个 (1,m) 的行向量,对应每一个样本。

然后,求出了 Z^{[2]} 后,可对参数进行梯度求解:

\mathrm{d} W^{[2]}=\frac{\partial \mathfrak{L}}{\partial W^{[2]}}=\frac{\partial \mathfrak{L}}{\partial Z^{[2]}}\frac{\partial Z^{[2]}}{\partial W^{[2]}}=\frac{1}{m}\cdot \mathrm{d} Z^{[2]}\cdot (A^{[1]})^T

\mathrm{d} B^{[2]}=\frac{\partial \mathfrak{L}}{\partial B^{[2]}}=\frac{\partial \mathfrak{L}}{\partial Z^{[2]}}\frac{\partial Z^{[2]}}{\partial B^{[2]}}=\frac{1}{m}\cdot \textup{np.sum}(\mathrm{d} Z^{[2]},axis=1)

解释:\mathrm{d} Z^{[2]} 的维度为 (1,m) ,(A^{[1]})^T 的维度为 (m,n_1) ,\mathrm{d} Z^{[2]}(A^{[1]})^T 的维度为 (1,n_1) ,从矩阵乘法的角度,可理解为将 \mathrm{d} Z^{[2]} 的每个样本组成的行向量乘以 (A^{[1]})^T 中的每个样本的某一个特征组成的列向量,得到 \mathrm{d} Z^{[2]}(A^{[1]})^T 的一个值,因对每个样本都做了一次计算然后求和,所以需要取平均。在 \mathrm{d} B^{[2]} 中,因为 Z^{[2]}=W^{[2]}A^{[1]}+B^{[2]} ,而 W^{[2]}A^{[1]} 的维度为 (1,m) ,B^{[2]} 的维度为 (1,1) ,执行了一次广播操作(自动复制了 m 份,使得维度表示为 (1,m) ),所以需要对每一行求和再取平均( axis=1 在 python 总表示按照行求和)。

接着,对第一层网络求解梯度:

\mathrm{d} Z^{[1]}=\frac{\partial \mathfrak{L}}{\partial Z^{[1]}}=\frac{\partial \mathfrak{L}}{\partial Z^{[2]}}\frac{\partial Z^{[2]}}{\partial A^{[1]}}\frac{\partial A^{[1]}}{\partial Z^{[1]}}=(W^{[2]})^T\cdot \mathrm{d} Z^{[2]}\ *\ {g^{[1]}(Z^{[1]})}'

然后,就可以对参数进行梯度求解:

\mathrm{d} W^{[1]}=\frac{\partial \mathfrak{L}}{\partial W^{[1]}}=\frac{\partial \mathfrak{L}}{\partial Z^{[1]}}\frac{\partial Z^{[1]}}{\partial W^{[1]}}=\frac{1}{m}\cdot\mathrm{d} Z^{[1]}\cdot X^T

\mathrm{d} B^{[1]}=\frac{\partial \mathfrak{L}}{\partial B^{[1]}}=\frac{\partial \mathfrak{L}}{\partial Z^{[1]}}\frac{\partial Z^{[1]}}{\partial B^{[1]}}=\frac{1}{m}\cdot \textup{np.sum}(\mathrm{d} Z^{[1]},axis=1)

最后,就可使用梯度下降法,对网络中的每个神经元进行更新。


如果这篇文章对你有一点小小的帮助,请给个关注,点个赞喔~我会非常开心的~

 

 

 

你可能感兴趣的:(深度学习)