一文彻底搞懂BP算法:原理推导+数据演示+项目实战(上篇)
欢迎大家关注我们的网站和系列教程:http://www.tensorflownews.com/,学习更多的机器学习、深度学习的知识!
反向传播算法(Backpropagation Algorithm,简称BP算法)是深度学习的重要思想基础,对于初学者来说也是必须要掌握的基础知识!本文希望以一个清晰的脉络和详细的说明,来让读者彻底明白BP算法的原理和计算过程。
全文分为上下两篇,上篇主要介绍BP算法的原理(即公式的推导),介绍完原理之后,我们会将一些具体的数据带入一个简单的三层神经网络中,去完整的体验一遍BP算法的计算过程;下篇是一个项目实战,我们将带着读者一起亲手实现一个BP神经网络(不适用任何第三方的深度学习框架)来解决一个具体的问题。
读者在学习的过程中,有任何的疑问,欢迎加入我们的交流群(扫描文章最后的二维码即可加入),和大家一起讨论!
1. BP算法的推导
图1 一个简单的三层神经网络
图1所示是一个简单的三层(两个隐藏层,一个输出层)神经网络结构,假设我们使用这个神经网络来解决二分类问题,我们给这个网络一个输入样本 ,通过前向运算得到输出 。输出值 的值域为 ,例如 的值越接近0,代表该样本是“0”类的可能性越大,反之是“1”类的可能性大。
1.1前向传播的计算
为了便于理解后续的内容,我们需要先搞清楚前向传播的计算过程,以图1所示的内容为例:
输入的样本为: a→=(x1,x2)\overrightarrow{a}=(x_ {1} , x_ {2} )a=(x1,x2)
第一层网络的参数为:
W(1)=[w(x1,1),w(x2,1)w(x1,2),w(x2,2)w(x1,3),w(x2,3)],b(1)=[b1,b2,b3]W^{(1)}=\left[\begin{array}{l}w_{\left(x_{1}, 1\right)}, w_{\left(x_{2}, 1\right)} \\ w_{\left(x_{1}, 2\right)}, w_{\left(x_{2}, 2\right)} \\ w_{\left(x_{1}, 3\right)}, w_{\left(x_{2}, 3\right)}\end{array}\right], \quad b^{(1)}=\left[b_{1}, b_{2}, b_{3}\right]W(1)=⎣⎡w(x1,1),w(x2,1)w(x1,2),w(x2,2)w(x1,3),w(x2,3)⎦⎤,b(1)=[b1,b2,b3]
第二层网络的参数为:
W(2)=[w(1,4),w(2,4),w(3,4)w(1,5),w(2,5),w(3,5)],b(2)=[b4,b5]W^{(2)}=\left[\begin{array}{l}w_{(1,4)}, w_{(2,4)}, w_{(3,4)} \\ w_{(1,5)}, w_{(2,5)}, w_{(3,5)}\end{array}\right], \quad b^{(2)}=\left[b_{4}, b_{5}\right]W(2)=[w(1,4),w(2,4),w(3,4)w(1,5),w(2,5),w(3,5)],b(2)=[b4,b5]
第三层网络的参数为:
W3=[w(4,6),w(5,6)],b(3)=[b6]W^{3}=\left[w_{(4,6)}, w_{(5,6)}\right], \quad b^{(3)}=\left[b_{6}\right] W3=[w(4,6),w(5,6)],b(3)=[b6]
1.1.1 第一层隐藏层的计算
图2 计算第一层隐藏层
第一层有三个神经元:neu1neu_1neu1,neu2neu_2neu2,neu3neu_3neu3。该层的输入为:
Z(1)=W(1)∗(a⃗)T+(b(1))TZ^{(1)}=W^{(1)} *(\vec{a})^{T}+\left(b^{(1)}\right)^{T} Z(1)=W(1)∗(a)T+(b(1))T
以neu1neu_1neu1神经元为例,则其输入为:
z1=w(x1,1)∗x1+w(x2,1)∗x2+b1z_{1}=w_{\left(x_{1}, 1\right)} * x_{1}+w_{\left(x_{2}, 1\right)} * x_{2}+b_{1} z1=w(x1,1)∗x1+w(x2,1)∗x2+b1
同理有:
z2=w(x1,2)∗x1+w(x2,2)∗x2+b2z3=w(x1,3)∗x1+w(x2,3)∗x2+b3\begin{aligned} &z_{2}=w_{\left(x_{1}, 2\right)} * x_{1}+w_{\left(x_{2}, 2\right)} * x_{2}+b_{2} \\ &z_{3}=w_{\left(x_{1}, 3\right)} * x_{1}+w_{\left(x_{2}, 3\right)} * x_{2}+b_{3} \end{aligned} z2=w(x1,2)∗x1+w(x2,2)∗x2+b2z3=w(x1,3)∗x1+w(x2,3)∗x2+b3
假设我们选择函数 f(x)f(x)f(x) 作为该层的激活函数 ( 图 1 中的激活函数都际了一个下标,一般情况下,同一层的激活函数都是一样的,不同层可以选择不同的激活函数),那么该层的输出为: f1(z1),f2(z2)f_{1}(z_{1}), f_{2}\left(z_{2}\right)f1(z1),f2(z2) 和 f3(z3)f_{3}\left(z_{3}\right)f3(z3)
1.1.2 第二层隐藏层的计算
图3 计算第二层隐藏层
第二层隐藏层有两个神经元: neu4neu_{4}neu4 和 neu5neu_{5}neu5 。 该层的输入为:
z(2)=W(2)∗[z1,z2,z3]T+(b(2))Tz^{(2)}=W^{(2)} *\left[z_{1}, z_{2}, z_{3}\right]^{T}+\left(b^{(2)}\right)^{T} z(2)=W(2)∗[z1,z2,z3]T+(b(2))T
即第二层的输入是第一层的输出乘以第二层的权重, 再加上第二层的偏置。因此得到 neu4n e u_{4}neu4 和 neu5n e u_{5}neu5 的输入分别为:
z4=w(1,4)∗z1+w(2,4)∗z2+w(3,4)∗z3+b4z5=w(1,5)∗z1+w(2,5)∗z2+w(3,5)∗z3+b5\begin{aligned} &z_{4}=w_{(1,4)} * z_{1}+w_{(2,4)} * z_{2}+w_{(3,4)} * z_{3}+b_{4} \\ &z_{5}=w_{(1,5)} * z_{1}+w_{(2,5)} * z_{2}+w_{(3,5)} * z_{3}+b_{5} \end{aligned} z4=w(1,4)∗z1+w(2,4)∗z2+w(3,4)∗z3+b4z5=w(1,5)∗z1+w(2,5)∗z2+w(3,5)∗z3+b5
该层的输出分别为: f4(z4)f_{4}\left(z_{4}\right)f4(z4) 和 f5(z5)f_{5}(z_{5})f5(z5)。
1.1.3 输出层的计算
图4 计算输出层
输出层只有一个神经元:neu6neu_6neu6。该层的输入为:
z(3)=W(3)∗[z4,z5]T+(b(3))Tz^{(3)}=W^{(3)} *\left[z_{4}, z_{5}\right]^{T}+\left(b^{(3)}\right)^{T} z(3)=W(3)∗[z4,z5]T+(b(3))T
即:z6=w(4,6)∗z4+w(5,6)∗z5+b6z_{6}=w_{(4,6)} * z_{4}+w_{(5,6)} * z_{5}+b_{6}z6=w(4,6)∗z4+w(5,6)∗z5+b6
因为该网络要解决的是一个二分类问题,所以输出层的激活函数也可以使用一个 Sigmoid 型函数,神经网络最后的输出为: f6(z6)f_{6}\left(z_{6}\right)f6(z6) 。
1.2 反向传播的计算
在 1.1 节里,我们已经了解了数据沿着神经网络前向传播的过程,这一节我们来介绍更重要的反向传播的计算过程。假设我们使用随机梯度下降的方式来学习神经网络的参数,损失函数定义为 L(y,y^){L}({y}, \hat{{y}})L(y,y^),其中y是该样本的真实类标。使用梯度下降进行参数的学习,我们必须计算出损失函数关于神经网络中各层参数(权重 w{w}w 和偏置 bbb) 的偏导数。
假设我们要对第k层隐藏层的参数 W(k)W^{(k)}W(k) 和 b(k)b^{(k)}b(k) 求偏导数, 即求 ∂L(y,y^)∂W(k)\frac{\partial {L}({y}, \hat{y})}{\partial W^{(k)}}∂W(k)∂L(y,y^) 和 ∂L(y,y^)∂b(k)\frac{\partial {L}({y}, \hat{y})}{\partial b^{(k)}}∂b(k)∂L(y,y^) 。假设 Z(k)Z^{(k)}Z(k) 代表第 kkk 层神经元的输入,即 z(k)=W(k)∗n(k−1)+b(k)z^{(k)}=W^{(k)} * n^{(k-1)}+b^{(k)}z(k)=W(k)∗n(k−1)+b(k),其中 n(k−1)n^{(k-1)}n(k−1) 为前一层神经元的输出,则根据链式法则有:
∂L(y,y^)∂W(k)=∂L(y,y^)∂z(k)∗∂z(k)∂W(k)∂L(y,y^)∂b(k)=∂L(y,y^)∂z(k)∗∂z(k)∂b(k)\begin{aligned} &\frac{\partial {L}({y}, \hat{{y}})}{\partial W^{(k)}}=\frac{\partial {L}({y}, \hat{{y}})}{\partial z^{(k)}} * \frac{\partial z^{(k)}}{\partial W^{(k)}} \\ &\frac{\partial {L}({y}, \hat{{y}})}{\partial b^{(k)}}=\frac{\partial {L}({y}, \hat{{y}})}{\partial z^{(k)}} * \frac{\partial z^{(k)}}{\partial b^{(k)}} \end{aligned} ∂W(k)∂L(y,y^)=∂z(k)∂L(y,y^)∗∂W(k)∂z(k)∂b(k)∂L(y,y^)=∂z(k)∂L(y,y^)∗∂b(k)∂z(k)
因此,我们只需要计算偏导数 ∂L(y,y^)∂z(k)、∂z(k)∂W(k)\frac{\partial {L}({y}, \hat{y})}{\partial z^{(k)}} 、 \frac{\partial z^{(k)}}{\partial W^{(k)}}∂z(k)∂L(y,y^)、∂W(k)∂z(k) 和 ∂z(k)∂b(k)\frac{\partial z^{(k)}}{\partial b^{(k)}}∂b(k)∂z(k)。
1.2.1 计算偏导数∂z(k)∂W(k)\frac{\partial z^{(k)}}{\partial W^{(k)}}∂W(k)∂z(k)
前面说过,第kkk层神经元的输入为: z(k)=W(k)∗n(k−1)+b(k)z^{(k)}=W^{(k)} * n^{(k-1)}+b^{(k)}z(k)=W(k)∗n(k−1)+b(k),因此可以得到:
∂z(k)∂W(k)=[∂(W1:(k)∗n(k−1)+b(k))∂W(k)⋮∂(Wm:(k)∗n(k−1)+b(k))∂W(k)]⟹初等变换(nk−1)T\frac{\partial z^{(k)}}{\partial W^{(k)}}=\left[\begin{array}{c} \frac{\partial\left(W_{1:}^{(k)} * n^{(k-1)}+b^{(k)}\right)}{\partial W^{(k)}} \\ \vdots \\ \frac{\partial\left(W_{m:}^{(k)} * n^{(k-1)}+b^{(k)}\right)}{\partial W^{(k)}} \end{array}\right] \stackrel{初等变换}\Longrightarrow{{(n^{k-1})}^{T}} ∂W(k)∂z(k)=⎣⎢⎢⎢⎡∂W(k)∂(W1:(k)∗n(k−1)+b(k))⋮∂W(k)∂(Wm:(k)∗n(k−1)+b(k))⎦⎥⎥⎥⎤⟹初等变换(nk−1)T
上式中,Wm:(k)W_{m:}^{(k)}Wm:(k)代表第k层神经元的权重矩阵W(k)W^{(k)}W(k)的第m行,Wmn(k)W_{m n}{ }^{(k)}Wmn(k)代表第kkk层神经元的权重矩阵W(k)W^{(k)}W(k)的第m行中的第n列。
我们以1.1节中的简单神经网络为例,假设我们要计算第一层隐藏层的神经元关于权重矩阵的导数,则有:
∂z(1)∂W(1)=(x1,x2)T=(x1x2)\frac{\partial z^{(1)}}{\partial W^{(1)}}=\left(x_{1}, x_{2}\right)^{T}=\left(\begin{array}{l}{x_{1}}\\{x_{2}}\end{array}\right) ∂W(1)∂z(1)=(x1,x2)T=(x1x2)
1.2.2 计算偏导数 ∂z(k)∂b(k)\frac{\partial z^{(k)}}{\partial b^{(k)}}∂b(k)∂z(k)
因为偏置 bbb 是一个常数项,因此偏导数的计算也很简单:
∂z(k)∂b(k)=[∂(W1:(k)∗n(k−1)+b1)∂b1⋯∂(W1:(k)∗n(k−1)+b1)∂bm⋮⋯⋮∂(Wm:(k)∗n(k−1)+bm)∂b1⋯∂(Wm:(k)∗n(k−1)+bm)∂bm]\frac{\partial z^{(k)}}{\partial b^{(k)}}=\left[\begin{array}{ccc} \frac{\partial\left(W_{1:}{ }^{(k)} * n^{(k-1)}+b_{1}\right)}{\partial b_{1}} & \cdots & \frac{\partial\left(W_{1:}{ }^{(k)} * n^{(k-1)}+b_{1}\right)}{\partial b_{m}} \\ \vdots & \cdots & \vdots \\ \frac{\partial\left(W_{m:}^{(k)} * n^{(k-1)}+b_{m}\right)}{\partial b_{1}} & \cdots & \frac{\partial\left(W_{m:}{ }^{(k)} * n^{(k-1)}+b_{m}\right)}{\partial b_{m}} \end{array}\right] ∂b(k)∂z(k)=⎣⎢⎢⎢⎡∂b1∂(W1:(k)∗n(k−1)+b1)⋮∂b1∂(Wm:(k)∗n(k−1)+bm)⋯⋯⋯∂bm∂(W1:(k)∗n(k−1)+b1)⋮∂bm∂(Wm:(k)∗n(k−1)+bm)⎦⎥⎥⎥⎤
依然以第一层隐藏层的神经元为例,则有:
∂z(1)∂b(1)=[100010001]\frac{\partial z^{(1)}}{\partial b^{(1)}}=\left[\begin{array}{lll} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{array}\right] ∂b(1)∂z(1)=⎣⎡100010001⎦⎤
1.2.3 计算偏导数 ∂L(y,y^)∂z(k)\frac{\partial {L}({y}, \hat{y})}{\partial z^{(k)}}∂z(k)∂L(y,y^)
偏导数 ∂L(y,y^)∂z(k)\frac{\partial {L}(\mathbf{y}, \hat{y})}{\partial z^{(k)}}∂z(k)∂L(y,y^) 又称为误差项 (error term,也称为“灵敏度”),一般用 δ\deltaδ 表示,例如 δ(1)=∂L(y,y^)∂z(1)\boldsymbol{\delta}^{(1)}=\frac{\partial {L}({y}, \hat{y})}{\partial z^{(1)}}δ(1)=∂z(1)∂L(y,y^) 是第一层神经元的误差项,其值的大小代表了第一层神经元对于最终总误差的影响大小。 根据第一节的前向计算,我们知道第 k+1k+\mathbf{1}k+1 层的输入与第 kkk 层的输出之间的关系为:
z(k+1)=W(k+1)∗n(k)+bk+1z^{(k+1)}=W^{(k+1)} * n^{(k)}+b^{k+1} z(k+1)=W(k+1)∗n(k)+bk+1
又因为 n(k)=fk(z(k))n^{(k)}=\boldsymbol{f}_{\boldsymbol{k}}\left(\boldsymbol{z}^{(\boldsymbol{k})}\right)n(k)=fk(z(k)),根据链式法则,我们可以得到 δ(k)\boldsymbol{\delta}^{(\boldsymbol{k})}δ(k) 为:
δ(k)=∂L(y,y^)∂z(k)=∂n(k)∂z(k)∗∂z(k+1)∂n(k)∗∂L(y,y^)∂z(k+1)=∂n(k)∂z(k)∗∂z(k+1)∂n(k)∗δ(k+1)=fk′(z(k))∗((W(k+1))T∗δ(k+1))\begin{aligned} \delta^{(k)} &=\frac{\partial {L}({y}, \hat{{y}})}{\partial z^{(k)}} \\ &=\frac{\partial n^{(k)}}{\partial z^{(k)}} * \frac{\partial z^{(k+1)}}{\partial n^{(k)}} * \frac{\partial {L}({y}, \hat{{y}})}{\partial z^{(k+1)}}\\ &=\frac{\partial n^{(k)}}{\partial z^{(k)}} * \frac{\partial z^{(k+1)}}{\partial n^{(k)}} * \delta^{(k+1)} \\ &=f_{k}^{\prime}\left(z^{(k)}\right) *\left(\left(W^{(k+1)}\right)^{T} * \delta^{(k+1)}\right) \end{aligned} δ(k)=∂z(k)∂L(y,y^)=∂z(k)∂n(k)∗∂n(k)∂z(k+1)∗∂z(k+1)∂L(y,y^)=∂z(k)∂n(k)∗∂n(k)∂z(k+1)∗δ(k+1)=fk′(z(k))∗((W(k+1))T∗δ(k+1))
由上式我们可以看到,第 kkk 层神经元的误差项 δ(k)\boldsymbol{\delta}^{(\boldsymbol{k})}δ(k) 是由第 k+1k+1k+1 层的误差项乘以第 k+1{k}+{1}k+1 层的权重,再乘以第 k{k}k 层激活函数的导数(梯度)得到的。这就是误差的反向传播。
现在我们已经计算出了偏导数 ∂L(y,y^)∂z(k),∂z(k)∂W(k)\frac{\partial {L}(y, \hat{y})}{\partial z^{(k)}}, \frac{\partial z^{(k)}}{\partial W^{(k)}}∂z(k)∂L(y,y^),∂W(k)∂z(k) 和 ∂z(k)∂b(k)\frac{\partial z^{(k)}}{\partial b^{(k)}}∂b(k)∂z(k), 则 ∂L(y,y^)∂W(k)\frac{\partial {L}({y}, \hat{y})}{\partial W^{(k)}}∂W(k)∂L(y,y^) 和 ∂L(y,y^)∂b(k)\frac{\partial {L}(y, \hat{y})}{\partial b^{(k)}}∂b(k)∂L(y,y^) 可分别表示为:
∂L(y,y^)∂W(k)=∂L(y,y^)∂z(k)∗∂z(k)∂W(k)=δ(k)∗(n(k−1))T∂L(y,y^)∂b(k)=∂L(y,y^)∂z(k)∗∂z(k)∂b(k)=δ(k)\begin{aligned} &\frac{\partial {L}({y}, \hat{{y}})}{\partial W^{(k)}}=\frac{\partial {L}({y}, \hat{{y}})}{\partial z^{(k)}} * \frac{\partial z^{(k)}}{\partial W^{(k)}}=\delta^{(k)} *\left(n^{(k-1)}\right)^{T} \\ &\frac{\partial {L}({y}, \hat{{y}})}{\partial b^{(k)}}=\frac{\partial {L}({y}, \hat{{y}})}{\partial z^{(k)}} * \frac{\partial z^{(k)}}{\partial b^{(k)}}=\delta^{(k)} \end{aligned} ∂W(k)∂L(y,y^)=∂z(k)∂L(y,y^)∗∂W(k)∂z(k)=δ(k)∗(n(k−1))T∂b(k)∂L(y,y^)=∂z(k)∂L(y,y^)∗∂b(k)∂z(k)=δ(k)
单纯的公式推导看起来有些枯燥,下面我们将实际的数据带入图1所示的神经网络中,完整的计算一遍。
2. 图解BP算法
图5 图解BP算法
我们依然使用如图5所示的简单的神经网络,其中所有参数的初始值如下:
输入的样本为(假设其真实类标为“1”):
a→=(x1,x2)=(1,2)\overrightarrow{{a}}=\left(x_{1}, x_{2}\right)=(1,2) a=(x1,x2)=(1,2)
第一层网络的参数为:
W(1)=[w(x1,1),w(x2,1)w(x1,2),w(x2,2)w(x1,3),w(x2,3)]=[211332],b(1)=[b1,b2,b3]T=[1,2,3]TW^{(1)}=\left[\begin{array}{l} w_{\left(x_{1}, 1\right)}, w_{\left(x_{2}, 1\right)} \\ w_{\left(x_{1}, 2\right)}, w_{\left(x_{2}, 2\right)} \\ w_{\left(x_{1}, 3\right)}, w_{\left(x_{2}, 3\right)} \end{array}\right]=\left[\begin{array}{ll} 2 & 1 \\ 1 & 3 \\ 3 & 2 \end{array}\right], \quad b^{(1)}=\left[b_{1}, b_{2}, b_{3}\right]^{T}=[1,2,3]^{T} W(1)=⎣⎡w(x1,1),w(x2,1)w(x1,2),w(x2,2)w(x1,3),w(x2,3)⎦⎤=⎣⎡213132⎦⎤,b(1)=[b1,b2,b3]T=[1,2,3]T
第二层网络的参数为:
W(2)=[w(1,4),w(2,4),w(3,4)w(1,5),w(2,5),w(3,5)]=[112322],b(2)=[b4,b5]T=[2,1]TW^{(2)}=\left[\begin{array}{l} w_{(1,4)}, w_{(2,4)}, w_{(3,4)} \\ w_{(1,5)}, w_{(2,5)}, w_{(3,5)} \end{array}\right]=\left[\begin{array}{lll} 1 & 1 & 2 \\ 3 & 2 & 2 \end{array}\right], \quad b^{(2)}=\left[b_{4}, b_{5}\right]^{T}=[2,1]^{T} W(2)=[w(1,4),w(2,4),w(3,4)w(1,5),w(2,5),w(3,5)]=[131222],b(2)=[b4,b5]T=[2,1]T
第三层网络的参数为:
W3=[w(4,6),w(5,6)]=[1,3],b(3)=[b6]=[2]W^{3}=\left[w_{(4,6)}, w_{(5,6)}\right]=[1,3], \quad b^{(3)}=\left[b_{6}\right]=[2] W3=[w(4,6),w(5,6)]=[1,3],b(3)=[b6]=[2]
假设所有的激活函数均为 Logistic 函数: f(k)(x)=11+e−xf^{(k)}(x)=\frac{1}{1+e^{-x}}f(k)(x)=1+e−x1 。使用均方误差函数作为损失函数:
L(y,y^)=E(y−y^)2{L}({y}, \hat{{y}})={E}({y}-\hat{{y}})^{2} L(y,y^)=E(y−y^)2
为了方便求导,我们将损失函数简化为: L(y,y^)=12∑(y−y^)2。{L}({y}, \hat{{y}})=\frac{1}{2} \sum({y}-\hat{{y}})^{2} 。L(y,y^)=21∑(y−y^)2。
2.1 前向传播
我们首先初始化神经网络的参数,计算第一层神经元:
z1=w(x1,1)∗x1+w(x2,1)∗x2+b1=2∗1+1∗2+1=5\begin{aligned} z_{1} &=w_{\left(x_{1}, 1\right)} * x_{1}+w_{\left(x_{2}, 1\right)} * x_{2}+b_{1} \\ &=2 * 1+1 * 2+1 \\ &=5 \\ \end{aligned} z1=w(x1,1)∗x1+w(x2,1)∗x2+b1=2∗1+1∗2+1=5
f1(z1)=11+e−z1=0.993307149075715f_{1}\left(z_{1}\right)=\frac{1}{1+e^{-z_{1}}}=0.993307149075715 f1(z1)=1+e−z11=0.993307149075715
上图中我们计算出了第一层隐藏层的第一个神经元的输入 z1z_{1}z1 和输出 f1(z1)f_{1}\left(z_{1}\right)f1(z1),同理可以计算第二 个和第三个神经元的输入和输出:
z2=w(x1,2)∗x1+w(x2,2)∗x2+b2=1∗1+3∗2+2=9\begin{aligned} z_{2} &=w_{\left(x_{1}, 2\right)} * x_{1}+w_{\left(x_{2}, 2\right)} * x_{2}+b_{2} \\ &=1 * 1+3 * 2+2 \\ &=9 \end{aligned} z2=w(x1,2)∗x1+w(x2,2)∗x2+b2=1∗1+3∗2+2=9
f2(z2)=11+e−z2=0.999876605424014f_{2}\left(z_{2}\right)=\frac{1}{1+e^{-z_{2}}}=0.999876605424014 f2(z2)=1+e−z21=0.999876605424014
z3=w(x1,3)∗x1+w(x2,3)∗x2+b3=3∗1+2∗2+3=10\begin{aligned} z_{3} &=w_{\left(x_{1}, 3\right)} * x_{1}+w_{\left(x_{2}, 3\right)} * x_{2}+b_{3} \\ &=3 * 1+2 * 2+3=10 \end{aligned} z3=w(x1,3)∗x1+w(x2,3)∗x2+b3=3∗1+2∗2+3=10
f3(z3)=11+e−z3=0.999954602131298\begin{aligned} f_{3}\left(z_{3}\right)=& \frac{1}{1+e^{-z_{3}}}=0.999954602131298 \end{aligned} f3(z3)=1+e−z31=0.999954602131298
接下来是第二层隐藏层的计算,首先我们计算第二层的第一个神经元的输入 z4z_{4}z4 和输出 f4(z4)f_{4}\left(z_{4}\right)f4(z4) :
z4=w(1,4)∗f1(z1)+w(2,4)∗f2(z2)+w(3,4)∗f3(z3)+b4=1∗0.993307149075715+1∗0.999876605424014+2∗0.999954602131298+2=5.993092958762325\begin{aligned} z_{4}&=w_{(1,4)} * f_{1}\left(z_{1}\right)+w_{(2,4)} * f_{2}\left(z_{2}\right)+w_{(3,4)} * f_{3}\left(z_{3}\right)+b_{4} \\ &=1 * 0.993307149075715+1 * 0.999876605424014+2 * 0.999954602131298+2 \\ &=5.993092958762325 \end{aligned} z4=w(1,4)∗f1(z1)+w(2,4)∗f2(z2)+w(3,4)∗f3(z3)+b4=1∗0.993307149075715+1∗0.999876605424014+2∗0.999954602131298+2=5.993092958762325
f4(z4)=11+e−z4=0.997510281884102f_{4}\left(z_{4}\right)=\frac{1}{1+e^{-z_{4}}}=0.997510281884102 f4(z4)=1+e−z41=0.997510281884102
同样方法可以计算该层的第二个神经元的输入 z5z_{5}z5 和输出 f5(z5)f_{5}\left(z_{5}\right)f5(z5) :
z5=w(1,5)∗f1(z1)+w(2,5)∗f2(z2)+w(3,5)∗f3(z3)+b5=3∗0.993307149075715+3∗0.999876605424014+2∗0.999954602131298+1=8.979460467761783\begin{aligned} z_{5}&=w_{(1,5)} * f_{1}\left(z_{1}\right)+w_{(2,5)} * f_{2}\left(z_{2}\right)+w_{(3,5)} * f_{3}\left(z_{3}\right)+b_{5}\\ &=3 * 0.993307149075715+3 * 0.999876605424014+2 * 0.999954602131298+1 \\ &=8.979460467761783 \end{aligned} z5=w(1,5)∗f1(z1)+w(2,5)∗f2(z2)+w(3,5)∗f3(z3)+b5=3∗0.993307149075715+3∗0.999876605424014+2∗0.999954602131298+1=8.979460467761783
f5(z5)=11+e−z5=0.999874045072167f_{5}\left(z_{5}\right)=\frac{1}{1+e^{-z_{5}}}=0.999874045072167 f5(z5)=1+e−z51=0.999874045072167
最后计算输出层的输入 z6z_{6}z6 和输出 f6(z6)f_{6}\left(z_{6}\right)f6(z6) :
z4=w(1,4)∗f1(z1)+w(2,4)∗f2(z2)+w(3,4)∗f3(z3)+b4=1∗0.993307149075715+1∗0.999876605424014+2∗0.999954602131298+2=5.993092958762325\begin{aligned} z_{4}&=w_{(1,4)} * f_{1}\left(z_{1}\right)+w_{(2,4)} * f_{2}\left(z_{2}\right)+w_{(3,4)} * f_{3}\left(z_{3}\right)+b_{4} \\ &=1 * 0.993307149075715+1 * 0.999876605424014+2 * 0.999954602131298+2 \\ &=5.993092958762325 \end{aligned} z4=w(1,4)∗f1(z1)+w(2,4)∗f2(z2)+w(3,4)∗f3(z3)+b4=1∗0.993307149075715+1∗0.999876605424014+2∗0.999954602131298+2=5.993092958762325
f4(z4)=11+e−z4=0.997510281884102f_{4}\left(z_{4}\right)=\frac{1}{1+e^{-z_{4}}}=0.997510281884102 f4(z4)=1+e−z41=0.997510281884102
2.2 误差反向传播
首先计算输出层的误差项 δ3\delta_{3}δ3,我们的误差函数为 L(y,y^)=12∑(y−y^)2{L}({y}, \hat{{y}})=\frac{1}{2} \sum({y}-\hat{{y}})^{2}L(y,y^)=21∑(y−y^)2,由于该样本的类标为“1",而预测值为 0.9975202938230020.9975202938230020.997520293823002,因此误差为 0.0024797061769980.0024797061769980.002479706176998,输出层的误差项为:
δ3=∂L(y,y^)∂z(3)=∂L(y,y^)∂n(3)∗∂n(3)∂z(3)=[−0.002479706176998]∗f(3)′(z3)=[0.002473557234274]∗[−0.002479706176998]=[−0.000006133695153]\begin{aligned} \delta_{3}&=\frac{\partial {L}({y}, \hat{y})}{\partial z^{(3)}}=\frac{\partial {L}({y}, \hat{{y}})}{\partial n^{(3)}} * \frac{\partial n^{(3)}}{\partial z^{(3)}}=[-0.002479706176998] * f^{(3)\prime}\left(z^{3}\right) \\ &=[0.002473557234274] *[-0.002479706176998] \\ &=[-0.000006133695153] \end{aligned} δ3=∂z(3)∂L(y,y^)=∂n(3)∂L(y,y^)∗∂z(3)∂n(3)=[−0.002479706176998]∗f(3)′(z3)=[0.002473557234274]∗[−0.002479706176998]=[−0.000006133695153]
接着计算第二层隐藏层的误差项,根据误差项的计算公式有:
δ(2)=∂L(y,y^)∂z(2)=f(2)′(z(2))∗((W(3))T∗δ(3))=[f4′(z4)00f5′(z5)]∗([13]∗[−0.000006133695153])=[0.00248351941960100.000125939063189]∗[−0.000006133695153−0.000018401085459]=[−0.000000015233151−0.000000002317415]\begin{aligned} \delta^{(2)}&=\frac{\partial {L}({y}, \hat{y})}{\partial z^{(2)}}=f^{(2)\prime}\left(z^{(2)}\right) *\left(\left(W^{(3)}\right)^{T} * \delta^{(3)}\right) \\ &=\left[\begin{array}{cc} f_{4}^{\prime}\left(z_{4}\right) & 0 \\ 0 & f_{5}^{\prime}\left(z_{5}\right) \end{array}\right] *\left(\left[\begin{array}{l} 1 \\ 3 \end{array}\right] *[-0.000006133695153]\right) \\ &=\left[\begin{array}{c} 0.002483519419601 \\ 0 & 0.000125939063189 \end{array}\right] *\left[\begin{array}{l} -0.000006133695153 \\ -0.000018401085459 \end{array}\right] \\ &=\left[\begin{array}{c} -0.000000015233151 \\ -0.000000002317415 \end{array}\right] \end{aligned} δ(2)=∂z(2)∂L(y,y^)=f(2)′(z(2))∗((W(3))T∗δ(3))=[f4′(z4)00f5′(z5)]∗([13]∗[−0.000006133695153])=[0.00248351941960100.000125939063189]∗[−0.000006133695153−0.000018401085459]=[−0.000000015233151−0.000000002317415]
最后是计算第一层隐藏层的误差项:
δ(1)=∂L(y,y^)∂n(1)=f(1)′(n(1))∗((W(2))T∗δ(2))=[f1′(z1)000f2′(z2)000f3′(z3)]=[0.0066480566707900000.0001233793497650000.000045395807735]∗([112322]T∗[−0.000000015233151−0.000000002317415])=[−0.000000000147490−0.000000000002451−0.000000000001593]\begin{aligned} \delta^{(1)}&=\frac{\partial {L}({y}, \hat{{y}})}{\partial n^{(1)}}=f^{(1)^{\prime}}\left(n^{(1)}\right) *\left(\left(W^{(2)}\right)^{T} * \delta^{(2)}\right) \\ &=\left[\begin{array}{ccc} f_{1}^{\prime}\left(z_{1}\right) & 0 & 0 \\ 0 & f_{2}^{\prime}\left(z_{2}\right) & 0 \\ 0 & 0 & f_{3}^{\prime}\left(z_{3}\right) \end{array}\right] \\ &=\left[\begin{array}{ccc} 0.006648056670790 & 0 & 0 \\ 0 & 0.000123379349765 & 0 \\ 0 & 0 & 0.000045395807735 \end{array}\right] \\ &*\left(\left[\begin{array}{lll} 1 & 1 & 2 \\ 3 & 2 & 2 \end{array}\right]^{T} *\left[\begin{array}{l} -0.000000015233151 \\ -0.000000002317415 \end{array}\right]\right) \\ &=\left[\begin{array}{l} -0.000000000147490 \\ -0.000000000002451 \\ -0.000000000001593 \end{array}\right] \end{aligned} δ(1)=∂n(1)∂L(y,y^)=f(1)′(n(1))∗((W(2))T∗δ(2))=⎣⎡f1′(z1)000f2′(z2)000f3′(z3)⎦⎤=⎣⎡0.0066480566707900000.0001233793497650000.000045395807735⎦⎤∗([131222]T∗[−0.000000015233151−0.000000002317415])=⎣⎡−0.000000000147490−0.000000000002451−0.000000000001593⎦⎤
2.3 更新参数
上一小节中我们已经计算出了每一层的误差项,现在我们要利用每一层的误差项和梯度来更新每一层的参数,权重WWW和偏置bbb的更新公式如下:
W(k)=W(k)−α(δ(k)(n(k−1))T+W(k))b(k)=b(k)−αδ(k)\begin{gathered} W^{(k)}=W^{(k)}-\alpha\left(\delta^{(k)}\left(n^{(k-1)}\right)^{T}+W^{(k)}\right) \\ b^{(k)}=b^{(k)}-\alpha \delta^{(k)} \end{gathered} W(k)=W(k)−α(δ(k)(n(k−1))T+W(k))b(k)=b(k)−αδ(k)
W(1)=W(1)−0.1∗(δ(1)(n(0))T+W(1))=[211332]−0.1∗([−0.000000000147490−0.000000000002451−0.000000000001593]∗[x1x2]+[211332])=[211332]−0.1∗([−0.000000000147490−0.000000000002451−0.000000000001593]∗[12]+[211332])=[211332]−0.1∗[1.9999999998525100.9999999997050200.9999999999975492.9999999999950982.9999999999984071.999999999996814]=[1.8000000000147490.9000000000294980.9000000000002452.7000000000004902.7000000000001591.800000000000319]\begin{aligned} W^{(1)}&=W^{(1)}-0.1 *\left(\delta^{(1)}\left(n^{(0)}\right)^{T}+W^{(1)}\right) \\ &=\left[\begin{array}{ll} 2 & 1 \\ 1 & 3 \\ 3 & 2 \end{array}\right]-0.1 *\left(\left[\begin{array}{ll} -0.000000000147490 \\ -0.000000000002451 \\ -0.000000000001593 \end{array}\right] *\left[\begin{array}{ll} x_{1} & x_{2} \end{array}\right]+\left[\begin{array}{ll} 2 & 1 \\ 1 & 3 \\ 3 & 2 \end{array}\right]\right) \\ &=\left[\begin{array}{ll} 2 & 1 \\ 1 & 3 \\ 3 & 2 \end{array}\right]-0.1 *\left(\left[\begin{array}{ll} -0.000000000147490 \\ -0.000000000002451 \\ -0.000000000001593 \end{array}\right] *\left[\begin{array}{ll} 1 & 2 \end{array}\right]+\left[\begin{array}{ll} 2 & 1 \\ 1 & 3 \\ 3 & 2 \end{array}\right]\right) \\ &=\left[\begin{array}{ll} 2 & 1 \\ 1 & 3 \\ 3 & 2 \end{array}\right]-0.1 *\left[\begin{array}{ll} 1.999999999852510 & 0.999999999705020 \\ 0.999999999997549 & 2.999999999995098 \\ 2.999999999998407 & 1.999999999996814 \end{array}\right] \\ &=\left[\begin{array}{ll} 1.800000000014749 & 0.900000000029498 \\ 0.900000000000245 & 2.700000000000490 \\ 2.700000000000159 & 1.800000000000319 \end{array}\right] \end{aligned} W(1)=W(1)−0.1∗(δ(1)(n(0))T+W(1))=⎣⎡213132⎦⎤−0.1∗⎝⎛⎣⎡−0.000000000147490−0.000000000002451−0.000000000001593⎦⎤∗[x1x2]+⎣⎡213132⎦⎤⎠⎞=⎣⎡213132⎦⎤−0.1∗⎝⎛⎣⎡−0.000000000147490−0.000000000002451−0.000000000001593⎦⎤∗[12]+⎣⎡213132⎦⎤⎠⎞=⎣⎡213132⎦⎤−0.1∗⎣⎡1.9999999998525100.9999999999975492.9999999999984070.9999999997050202.9999999999950981.999999999996814⎦⎤=⎣⎡1.8000000000147490.9000000000002452.7000000000001590.9000000000294982.7000000000004901.800000000000319⎦⎤
b(1)=b(1)−αδ(1)=[1,2,3]T−0.1∗[−0.000000000147490−0.000000000002451−0.000000000001593]=[0.9999999999852511.9999999999997552.999999999999841]\begin{aligned} b^{(1)}&=b^{(1)}-\alpha \delta^{(1)}\\ &=[1,2,3]^{T}-0.1 *\left[\begin{array}{l}-0.000000000147490 \\ -0.000000000002451 \\ -0.000000000001593\end{array}\right]\\ &=\left[\begin{array}{l}0.999999999985251 \\ 1.999999999999755 \\ 2.999999999999841\end{array}\right]\\ \end{aligned} b(1)=b(1)−αδ(1)=[1,2,3]T−0.1∗⎣⎡−0.000000000147490−0.000000000002451−0.000000000001593⎦⎤=⎣⎡0.9999999999852511.9999999999997552.999999999999841⎦⎤
通常权重WWW的更新会加上一个正则化项来避免过拟合,这里为了简化计算,我们省去了正则化项。上式中的 是学习率,我们设其值为0.10.10.1。参数更新的计算相对简单,每一层的计算方式都相同,因此本文仅演示第一层隐藏层的参数更新:
3. 小结
至此,我们已经完整介绍了BP算法的原理,并使用具体的数值做了计算。在下篇中,我们将带着读者一起亲手实现一个BP神经网络(不适用任何第三方的深度学习框架),敬请期待!有任何疑问,欢迎加入我们一起交流!
本篇文章出自http://www.tensorflownews.com,对深度学习感兴趣,热爱Tensorflow的小伙伴,欢迎关注我们的网站!
一文彻底搞懂BP算法:原理推导+数据演示+项目实战(上篇)相关推荐
- layer output 激活函数_一文彻底搞懂BP算法:原理推导+数据演示+项目实战(下篇)...
在"一文彻底搞懂BP算法:原理推导+数据演示+项目实战(上篇)"中我们详细介绍了BP算法的原理和推导过程,并且用实际的数据进行了计算演练.在下篇中,我们将自己实现BP算法(不使用第 ...
- 一文彻底搞懂BP算法:原理推导+数据演示+项目实战(下篇)
在"一文彻底搞懂BP算法:原理推导+数据演示+项目实战(上篇)"中我们详细介绍了BP算法的原理和推导过程,并且用实际的数据进行了计算演练.在下篇中,我们将自己实现BP算法(不使用第 ...
- BP算法:原理推导数据演示项目实战1(转)
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/fendouaini/article/details/79789440 </div>< ...
- 一文搞懂RSA算法原理及简单实现
前言 RSA算法是最重要的算法之一,它是一种非对称加密,是目前最有影响力的加密方式之一.这篇文章我们通过实现一种简单的RSA加密来探究它的原理. 计算公钥和私钥 RSA中的公钥和私钥需要结合在一起工作 ...
- 一文彻底搞懂快速幂(原理、实现、矩阵快速幂)
前言 大家好,我是bigsai,之前有个小老弟问到一个剑指offer一道相关快速幂的题,这里梳理一下讲一下快速幂! 快速幂是什么? 顾名思义,快速幂就是快速算底数的n次幂.你可能疑问,求n次幂算n次叠 ...
- cas无法使用_一文彻底搞懂CAS实现原理
本文导读: 前言 如何保障线程安全 CAS原理剖析 CPU如何保证原子操作 解密CAS底层指令 小结 前言 日常编码过程中,基本不会直接用到 CAS 操作,都是通过一些JDK 封装好的并发工具类来使用 ...
- 一文彻底搞懂事务底层原理
事务底层原理(INNODB) 前言 redo log 为什么需要 redo log 一些问题 重做日志结构 重做日志文件结构 log group与循环写入 日志何时写入磁盘? 数据恢复:LSN标记 C ...
- 一文搞懂 Raft 算法
一文搞懂Raft算法 正文 raft是工程上使用较为广泛的强一致性.去中心化.高可用的分布式协议.在这里强调了是在工程上,因为在学术理论界,最耀眼的还是大名鼎鼎的Paxos.但Paxos是:少数真正理 ...
- Android 动态分区详解(一) 5 张图让你搞懂动态分区原理
文章目录 0. 导读 1. 动态分区详解的背景 1.1 背景 1.2 动态分区的本质 2. Linux device mapper 驱动 3. Android 动态分区布局 3.1 动态分区布局 3. ...
- php service原理,轻松搞懂WebService工作原理
用更简单的方式给大家谈谈WebService,让你更快更容易理解,希望对初学者有所帮助. WebService是基于网络的.分布式的模块化组件. 我们直接来看WebService的一个简易工作流程: ...
最新文章
- mysql利用CPU多核
- 查询页面代码运行时间
- python处理大型矩阵_在python中处理大型密集矩阵
- 经典C语言程序100例之五六
- mysql把latin1编码的中文转成gbk(或utf8)编码
- angular ng-zorro 用组件自身方的法来重置表单校验
- springboot中getOutputStream() has already been called for this response和java.io.FileNotFoundException
- python-while循环简单版-练习
- html 监听后端变化_SpringBoot2.0整合WebSocket,实现后端数据实时推送!
- 我38岁,从外企技术高管到失业在家,只因为做错了这件事
- 接口参数,get和post
- Windows 10开机Windows聚焦壁纸不更新解决方法
- GoldenDict音标乱码
- 计算机时间单位,时间计算机单位之间的换算
- ctf之7z文件爆破
- 香橙派python编程_香橙派4B Python3.7安装OpenCV
- 苏超 计算机系 南京大学,Ni-Ti基合金薄膜相变行为及其力学特性研究
- java小游戏大鱼吃小鱼入门(音乐添加+鱼头转向+背景移动+背景泡泡效果)
- 人生就像四季,繁华过后终归平淡,不可能一直繁华似锦,不可能一路花香四溢。...
- salt同步配置文件
热门文章
- android screencap,android – “adb screencap /sdcard/screenshot.raw”生成什么格式? (没有“-p”标志)...
- matlab语法——min函数
- jszip压缩文件上传到服务器,AngularJS - 使用JSZip压缩上传的pdf文件
- 给mBlock添加扩展模块
- 3Ds MAX 百度网盘免费下载
- Idea 破解版下载指南
- 《硬件接入》海康威视接入及CPU性能优化思路
- 开源项目之Windows读取Ext4分区的工具 Ext2Read
- windows本地破解用户口令
- 【郝斌C语言课程】学习笔记