什么是全连接神经网络?
全连接神经网络是指任意两个相邻层之间的神经元全部互相连接。如下图所示:

图 1
如何计算全连接神经网络的输出?
在进行计算前,我们先对一些变量进行说明,如下图所示:

图 2
首先是整个神经网络的输入,我们用 x1,x2,x3...xn 来表示神经网络的输入,在上图中输入是: x1,x2,x3 。为了方便计算我们还可以用向量表示:
X=⎣⎡x1x2x3⎦⎤
其次是神经网络的权重,我们用 wij 表示,其中 i 是源神经元节点编号, j 是目的神经元节点编号,wij 表示神经元 i 跟 神经元 j 连接的权重。在上图中,节点1根节点4之间的权重为 w14 。同样输入层和隐层之间的权重矩阵以及隐层和输出层之间的权重矩阵也可以用向量表示:
W1=⎣⎢⎢⎡w14w15w16w17w24w25w26w27w34w35w36w37⎦⎥⎥⎤W2=[w48w49w58w59w68w69w78w79]
需要注意的是权重矩阵不是随便排列的,这个在下面会提到。
之后是神经网络隐层的输出,我们用 a1,a2,...al 表示,在上图中,隐藏层的输出为:a4,a5,a6,a7 ,为了能更好的理解,我们直接用节点编号作为下标。用向量表示为:
a=⎣⎢⎢⎡a4a5a6a7⎦⎥⎥⎤
最后是神经网络的输出,我们用 y1,y2,...ym 来表示,在上图中输出是:y1,y2, 我们同样可以用向量表示:
Y=[y1y2]
既然我们已经将整个神经网络的输入、权重、中间变量、输出全部介绍完了,接下来,我们真正开始介绍如何从输入经过一系列计算得到输出。
首先看一张图:

图 3
这张图展示了经过神经元的数据如何进行计算并输出。
首先是神经元的输入:x1,x2,...xn ,然后是跟每一个输入所对应的权重:w1,w2,...wn ,神经元中的两个符号分别代表两种对输入数据的操作,首先是∑ 求和符号,它代表的是输入数据跟权重的乘积累和,即:∑i=1nxiwi ,我们用 net 表示,即 net=∑i=1nxiwi ;另一个符号 σ 代表的是一个**函数,前一步的输出作为**函数的输入,经过**函数的计算后得到输出 y 。
**函数不懂的同学可自行百度,这里不再赘述。只需要知道**函数是神经网络引入的非线性因素,目的是使神经网络可以解决非线性问题。
**函数有很多种,这里我们以sigmoid函数为例,即:
σ(x)=1+e−x1(1)
那么经过神经元的输出为:
y=σ(net)=σ(i=1∑nxiwi)=1+e−∑i=1nxiwi1(2)
这个公式别看最后计算挺复杂,其实只有两步运算。
- 神经元输入跟对应权重乘积再累加
- 将上一步结果经过**函数得到神经元输出
上面介绍的是单个神经元的输入输出计算,接下来我们结合具体的例子再来理解一下:

还是这张图,这里我们来计算一下隐藏层节点4的输出a4:
a4=σ(net)=σ(x1w14+x2w24+x3w34)(3)
同理我们可以计算出隐藏层所有节点的输出 a4,a5,a6,a7 ,之后我们再来计算一下输出层节点8的输出值 y1 :
y1=σ(a4w48+a5w58+a6w68+a7w78)(4)
同理可计算出 y2 :
y1=σ(a4w49+a5w59+a6w69+a7w79)(5)
以上就是整个神经元从输入到输出的计算过程。
上面的方法必须逐个计算每个神经元的输入输出,其实我们还可以用更简单的方式–矩阵计算。这里我们把前面介绍的矩阵表达直接拿过来:
X=⎣⎡x1x2x3⎦⎤W1=⎣⎢⎢⎡w14w15w16w17w24w25w26w27w34w35w36w37⎦⎥⎥⎤
这样一来,我们就可以更简单的计算隐藏层的输出值:
a=σ(W1X)=σ(⎣⎢⎢⎡w14w15w16w17w24w25w26w27w34w35w36w37⎦⎥⎥⎤⎣⎡x1x2x3⎦⎤)=σ(⎣⎡x1w14+x2w24+x3w34x1w15+x2w25+x3w35x1w16+x2w26+x3w36⎦⎤)=⎣⎡σ(x1w14+x2w24+x3w34)σ(x1w15+x2w25+x3w35)σ(x1w16+x2w26+x3w36)⎦⎤=⎣⎢⎢⎡a4a5a6a7⎦⎥⎥⎤(6)
瞧!该矩阵的第一行不正是我们前面求出的第4个神经元的输出值吗。
同理我们还可以根据矩阵计算出输出层的 Y 值:
Y=σ(W2a)=σ([w48w49w58w59w68w69w78w79]⎣⎢⎢⎡a4a5a6a7⎦⎥⎥⎤)=σ([a4w48+a5w58+a6w68+a7w78a4w49+a5w59+a6w69+a7w79])=[σ(a4w48+a5w58+a6w68+a7w78)σ(a4w49+a5w59+a6w69+a7w79)]=[y1y2](7)
其中 W2 是隐藏层到输出层的权重矩阵,a 是隐藏层输出值。结果跟我们之前的推导一模一样。
到此为止,全连接神经网络的前向计算已经全部推导完毕。
全连接神经网络的反向传播算法推导
我们将所有输出层节点的误差平方和作为目标函数:
Ed=21i=1∑m(yi−y^i)2(8)
其中 Ed 代表损失函数,m 代表输出层神经元个数, yi 代表第i个神经元的实际值, y^i 代表模型预测值。
接下来用梯度下降算法来优化目标函数:
wij←wij−α∂wij∂Ed(9)
这个是我们梯度更新的公式,可以更新任一权重。之后我们会介绍如何用矩阵更新一组权重。
假设 netj 是神经元节点 j 的加权输入:
netj=w1jx1j+w2jx2j+...+wnjxnj=i=1∑nwijxij(10)
其中 wij 是第 i 个节点到第 j 个节点的权重, xij 是第 i 个节点到第 j 个节点的输入。

图 4
还是前面这张图,希望能通过这张图看清楚 netj 在神经网络中的位置,在这里 netj 就相当于上图中的 ∑ 的位置。通过这张图还要理清楚函数的链式关系:误差 Ed 是 yi^ 的函数, y^ 是 net 的函数, net 是 wi 的函数;目的是为了下面的链式求导铺垫。
接下来求损失函数对 $w_{ij} $ 的偏导数:
∂wij∂Ed=∂netj∂Ed∂wij∂netj=∂netj∂Ed∂wij∂∑i=1nwijxij=∂netj∂Edxij(11)
为了求得其偏导数,需要分两种情况进行讨论:输出层和隐层
1.输出层权值训练
∂netj∂Ed=∂yj^∂Ed∂netj∂yj^=∂yj^∂21i=1∑m(yi−y^i)2∂netj∂σ(netj)=−(yj−yj^)yj^(1−yj^)(12)
这里的 σ **函数用的是sigmoid函数,故其导数为 σ(1−σ) ,上式第二行第二项就是这样的来的。
令 δj=−∂netj∂Ed ,即:
δj=(yj−yj^)yj^(1−yj^)(13)
最后将上述公式带入梯度下降公式可得:
wij←wij−α∂wij∂Ed=wij+αδjxij=wij+α(yj−yj^)yj^(1−yj^)xij(14)
这个就是更新输出层权值的公式;
2.隐藏层权值训练
这里我们先定义节点 j 的所有直接下游节点集合为 K , 从下图中我们可以明显看出,节点3的直接下游节点为{6,7,8};

图 5
(注:图 5只是为了便于理解隐藏层权值训练过程,所有的实际计算均以图 2主)
从上图可以看出,权值 wij 通过影响节点 j 的输出可以直接影响到节点 j 的所有直接下游节点,于是:
netj∂Ed=k∈K∑netk∂Ednetj∂netk=k∈K∑−δk∂aj∂netk∂netj∂aj=k∈K∑−δkwjkaj(1−aj)=−aj(1−aj)k∈K∑δkwjk(15)
再将 δj=−∂netj∂Ed 带入:
δj=aj(1−aj)k∈K∑δkwjk(16)
最后带入梯度下降公式:
wij←wij−α∂wij∂Ed=wij−α∂netj∂Ed∂wij∂netj=wij+αδjxij=wij+αaj(1−aj)xijk∈K∑δkwjk(17)
我们就得到了隐藏层的权值更新公式;
显然通过上面的方法需要一个个更新神经元的权值,非常麻烦;接下来我们介绍用矩阵的方式进行计算。

令:
x=⎣⎡x1x2x3⎦⎤a=⎣⎢⎢⎡a4a5a6a7⎦⎥⎥⎤y^=[y1^y2^]y=[y1y2]W1=⎣⎢⎢⎡w14w15w16w17w24w25w26w27w34w35w36w37⎦⎥⎥⎤W2=[w48w49w58w59w68w69w78w79]δ(2)=⎣⎢⎢⎢⎡δ1(2)δ2(2)δ3(2)δ4(2)⎦⎥⎥⎥⎤δ(3)=[δ1(3)δ2(3)]
将公式13和公式16用向量表示为:
δ=y^(1−y^)(y−y^)(18)
δ(l)=a(l)(1−a(l))WTδ(l+1)(19)
权重更新的向量化表示为:
W←W+αδxT(20)
偏置项更新的向量化表示为:
b←b+αδ(21)
接下来我们举例说明 W1,W2 的更新是怎样计算的:
先计算 δ(3):
δ(3)=y^(1−y^)(y−y^)=[y1^y2^](1−[y1^y2^])([y1y2]−[y1^y2^])=[y^1(1−y^1)(y1−y^1)y^2(1−y^2)(y2−y^2)]
然后更新 W2 :
W2←W2+αδxT=W2+αδ(3)aT=[w48w49w58w59w68w69w78w79]+α[y^1(1−y^1)(y1−y^1)y^2(1−y^2)(y2−y^2)][a4a5a6a7]=[w48w49w58w59w68w69w78w79]+α[y^1(1−y^1)(y1−y^1)a4y^2(1−y^2)(y2−y^2)a4y^1(1−y^1)(y1−y^1)a5y^2(1−y^2)(y2−y^2)a5y^1(1−y^1)(y1−y^1)a6y^2(1−y^2)(y2−y^2)a6y^1(1−y^1)(y1−y^1)a7y^2(1−y^2)(y2−y^2)a7]=[w48+αy^1(1−y^1)(y1−y^1)a4w49+αy^2(1−y^2)(y2−y^2)a4w58+αy^1(1−y^1)(y1−y^1)a5w49+αy^2(1−y^2)(y2−y^2)a5w68+αy^1(1−y^1)(y1−y^1)a6w49+αy^2(1−y^2)(y2−y^2)a6w78+αy^1(1−y^1)(y1−y^1)a7w49+αy^2(1−y^2)(y2−y^2)a7]
之后求 δ(2) :
δ(2)=a(2)(1−a(2))W2Tδ(3)=⎣⎢⎢⎡a4a5a6a7⎦⎥⎥⎤(1−⎣⎢⎢⎡a4a5a6a7⎦⎥⎥⎤)⎣⎢⎢⎡w48w58w68w78w49w59w69w79⎦⎥⎥⎤[y^1(1−y^1)(y1−y^1)y^2(1−y^2)(y2−y^2)]=⎣⎢⎢⎡a4(1−a4)a5(1−a5)a6(1−a6)a7(1−a7)⎦⎥⎥⎤⎣⎢⎢⎡w48y^1(1−y^1)(y1−y^1)+w49y^2(1−y^2)(y2−y^2)w58y^1(1−y^1)(y1−y^1)+w59y^2(1−y^2)(y2−y^2)w68y^1(1−y^1)(y1−y^1)+w69y^2(1−y^2)(y2−y^2)w78y^1(1−y^1)(y1−y^1)+w79y^2(1−y^2)(y2−y^2)⎦⎥⎥⎤=⎣⎢⎢⎡a4(1−a4)(w48y^1(1−y^1)(y1−y^1)+w49y^2(1−y^2)(y2−y^2))a5(1−a5)(w58y^1(1−y^1)(y1−y^1)+w59y^2(1−y^2)(y2−y^2))a6(1−a6)(w68y^1(1−y^1)(y1−y^1)+w69y^2(1−y^2)(y2−y^2))a7(1−a7)(w78y^1(1−y^1)(y1−y^1)+w79y^2(1−y^2)(y2−y^2))⎦⎥⎥⎤
最后更新 W1 :
W1...←W1+αδ(2)xT=⎣⎢⎢⎡w14w15w16w17w24w25w26w27w34w35w36w37⎦⎥⎥⎤+α⎣⎢⎢⎡a4(1−a4)(w48y^1(1−y^1)(y1−y^1)+w49y^2(1−y^2)(y2−y^2))a5(1−a5)(w58y^1(1−y^1)(y1−y^1)+w59y^2(1−y^2)(y2−y^2))a6(1−a6)(w68y^1(1−y^1)(y1−y^1)+w69y^2(1−y^2)(y2−y^2))a7(1−a7)(w78y^1(1−y^1)(y1−y^1)+w79y^2(1−y^2)(y2−y^2))⎦⎥⎥⎤[x1x2x3]
全部展开太过复杂,不再展开。
到这里我们就全连接神经网络前向传播和反向传播全部推导完毕。
参考:
【1】零基础入门深度学习(3) - 神经网络和反向传播算法