本文有一部分内容参考以下两篇文章:
一文弄懂神经网络中的反向传播法——BackPropagation
神经网络
最简单的全连接神经网络如下图所示(这张图极其重要,本文所有的推导都参照的这张图,如果有兴趣看推导,建议保存下来跟推导一起看):
它的前向传播计算过程非常简单,这里先讲一下:
前向传播
Y1=f(W(1)11X1+W(1)12X2+K1)Y1=f(W11(1)X1+W12(1)X2+K1)
Y2=f(W(1)21X1+W(1)22X2+K1)Y2=f(W21(1)X1+W22(1)X2+K1)
O1=f(W(2)11Y1+W(2)12Y2+K2)O1=f(W11(2)Y1+W12(2)Y2+K2)
O2=f(W(2)21Y1+W(2)22Y2+K2)O2=f(W21(2)Y1+W22(2)Y2+K2)
具体的,如果代入实际数值,取
X1=0.05X1=0.05 X2=0.10X2=0.10
K1=0.35K1=0.35 K2=0.60K2=0.60
W(1)11=0.15W11(1)=0.15 W(1)12=0.20W12(1)=0.20
W(1)21=0.25W21(1)=0.25 W(1)22=0.30W22(1)=0.30
W(2)11=0.40W11(2)=0.40 W(2)12=0.45W12(2)=0.45
W(2)21=0.50W21(2)=0.50 W(2)22=0.55W22(2)=0.55
激活函数为:11+e−z11+e−z
则有:z(1)1=0.15∗0.05+0.20∗0.10+0.35=0.3775z1(1)=0.15∗0.05+0.20∗0.10+0.35=0.3775
Y1=11+e−z(1)1=11+e−0.3775=0.5932699921Y1=11+e−z1(1)=11+e−0.3775=0.5932699921
z(1)2=0.25∗0.05+0.30∗0.10+0.35=0.3925z2(1)=0.25∗0.05+0.30∗0.10+0.35=0.3925
Y2=11+e−z(1)2=11+e−0.3925=0.5968843783Y2=11+e−z2(1)=11+e−0.3925=0.5968843783
z(2)1=0.40∗0.5932699921+0.45∗0.5968843783+0.60=1.1059059671z1(2)=0.40∗0.5932699921+0.45∗0.5968843783+0.60=1.1059059671
O1=11+e−z(2)2=11+e−1.1059059671=0.7513650696O1=11+e−z2(2)=11+e−1.1059059671=0.7513650696
z(2)2=0.50∗0.5932699921+0.55∗0.5968843783+0.60=1.2249214041z2(2)=0.50∗0.5932699921+0.55∗0.5968843783+0.60=1.2249214041
O2=11+e−z(2)2=f(1.2249214041)=11+e−1.2249214041=0.7729284653O2=11+e−z2(2)=f(1.2249214041)=11+e−1.2249214041=0.7729284653
经过上面的过程,我们就完成了一次神经网络从输入到输出的计算。虽然公式代入数值看起来比较要命,但实际上对于计算机来说并没有什么。
那它有什么用呢?单看上面的例子可以说是完全没用的,因为它的输出跟输入的关系还非常的模糊。我们需要做的是训练这个网络中的参数,使得输出和输入存在某种对应关系(比如输入1、1,输出1、0来实现一个类似于加法器这样的东西),当上面网络的参数训练好了,我们工程中就只需要将数据输入这个网络,然后看看输出结果就行。从这里也大致可以看到,神经网络在实际应用中计算量大归大(可能网络本身就很复杂),但其实也还可以接受,最要命的地方是在于训练(每训练一次都要做一次前向传播计算,一般训练的次数又是以万为单位的)!
以上面的网络为例,通常我们说的训练参数就是训练公式中跟W相关的那8个数。在具体展开讲之前先补充下上面用到的神经网络的两个知识点:
激活函数,也就是上面例子中的11+e−z11+e−z(事实上只要满足一定的规范,激活函数可以有无数种形态,不一定就用这个),其大体有两个作用:
1.将数据归一化,因为前一层网络的计算结果很有可能不在0~1之间,而数据的范围需要统一,因此用激活函数把数据范围给限定住。
2.打破网络的线性映射关系,如果网络只存在线性关系,则无论网络多深多复杂,最后都可以用单层网络替换,这样也就跟深度学习没什么关系了。另外更重要的一点是,如果只有线性,对于非线性的数据要分类是无能为力的。
偏置项,也就是本篇最开始的网络图中最底层的那个“+1”
对这个东西有什么用,有些解释如下:
Y=WX+b (1)
假设没有b,则公式退化成
Y=WX (2)
假设现在要把(1,1)、(2,2)这两个点分成不同的类,则公式(2)直接就跪了,而公式(1)可以做到。
但,本人不同意这个说法,因为这样的话(1,b)、(2,b)这两个点就分不出来了。也就是说按照这样的解释方法加入偏置项虽然能解决一部分问题,但会带入另外的问题,并没有什么卵用。
本人对偏置项作用的看法是,偏置项要结合激活函数来看,每一层网络虽然共享一个偏置项,然而因为前面计算的结果有所差异(如例子中W(1)11X1+W(1)12X2W11(1)X1+W12(1)X2与W(1)21X1+W(1)22X2W21(1)X1+W22(1)X2),而激活函数又非线性函数,因而可以将神经元较快的分化出来。
反向传播
承接上面,我们来讲最重要的参数训练问题,深度学习一般用反向传播法更新权重(甚至可以说反向传播是神经网络的灵魂)。它的作用其实很好理解,下面结合着上面举的例子解释一下。
上面我们的输入是:
X1=0.05X1=0.05 X2=0.10X2=0.10
对应的输出是:
O1=0.7513650696 O2=0.7729284653O1=0.7513650696 O2=0.7729284653
假设我们希望输入对应的输出为:
O1=0.01 O2=0.99O1=0.01 O2=0.99
我们就需要改变W的取值,而具体要改变多少,我们一般会用梯度下降的方法去评估。在讲梯度下降之前,先来看看评价误差大小的“损失函数”。
损失函数,也叫做“代价函数”,损失函数越小,就代表模型拟合的越好。最常用的损失函数是均方误差:
E总=∑ni=1(Ti−Oi)2n(其中Ti为期望网络输出的结果,Oi为实际网络输出的结果)E总=∑i=1n(Ti−Oi)2n(其中Ti为期望网络输出的结果,Oi为实际网络输出的结果)
代入上面例子的期望输出和实际输出数值则可以求得
E总=∑ni=1(Ti−Oi)2n=EO1+EO2=(0.01−0.7513650696)22+(0.99−0.7729284653)22=0.2983711088E总=∑i=1n(Ti−Oi)2n=EO1+EO2=(0.01−0.7513650696)22+(0.99−0.7729284653)22=0.2983711088
通过损失函数算出误差大小之后我们就可以大概知道网络训练的怎么样了,是不是已经大致能工作之类的。
OK,下面进入梯度下降法:
梯度下降法
要求单个的W对于总体误差起到多大的影响。在数学上,就是求总体误差对相应W的偏导数。以示例中隐含层到输出层的 W(2)11W11(2)为例,就是求∂E总∂W(2)11∂E总∂W11(2)。
要直接求基本是不可能的,我们可以先分析下W(2)11W11(2)到E总E总间到底经历了什么。
1. W(2)11W11(2)先与Y1Y1相乘
2. 经过激活函数
3. 经过误差计算公式,也就是损失函数
因此我们可以把∂E总∂W(2)11∂E总∂W11(2)拆开来(链式法则,高数学的不好的同学回去翻书),如下:
∂E总∂W(2)11=∂E总∂O1∗∂O1∂z(2)1∗∂z(2)1∂W(2)11∂E总∂W11(2)=∂E总∂O1∗∂O1∂z1(2)∗∂z1(2)∂W11(2)(z(2)1z1(2)为经过激活函数前的状态)
这样,只要能分别求出这三个部分,整体也就求出来了。
下面先列出被微分的这几项
E总=EO1+EO2=(T1−O1)22+(T2−O2)22E总=EO1+EO2=(T1−O1)22+(T2−O2)22
O1=11+e−z(2)1O1=11+e−z1(2)
z(2)1=W(2)11Y1+W(2)12Y2+K2z1(2)=W11(2)Y1+W12(2)Y2+K2
分别做偏微分得到
∂E总∂O1=∂[(T1−O1)22+(T2−O2)22]∂O1=−(T1−O1)=O1−T1∂E总∂O1=∂[(T1−O1)22+(T2−O2)22]∂O1=−(T1−O1)=O1−T1
∂O1∂z(2)1=∂11+e−z(2)1∂z(2)1=e−z(2)1(1+e−z(2)1)2=1+e−z(2)1−1(1+e−z(2)1)2=11+e−z(2)1(1−11+e−z(2)1)=O1(1−O1)∂O1∂z1(2)=∂11+e−z1(2)∂z1(2)=e−z1(2)(1+e−z1(2))2=1+e−z1(2)−1(1+e−z1(2))2=11+e−z1(2)(1−11+e−z1(2))=O1(1−O1)
∂z(2)1∂W(2)11=∂(W(2)11Y1+W(2)12Y2+K2)∂W(2)11=Y1∂z1(2)∂W11(2)=∂(W11(2)Y1+W12(2)Y2+K2)∂W11(2)=Y1
代入具体数值得到
∂E总∂O1=O1−T1=0.7513650696−0.01=0.7413650696∂E总∂O1=O1−T1=0.7513650696−0.01=0.7413650696
∂O1∂z(2)1=O1(1−O1)=0.7513650695(1−0.7513650695)=0.1868156018∂O1∂z1(2)=O1(1−O1)=0.7513650695(1−0.7513650695)=0.1868156018
∂z(2)1∂W(2)11=Y1=0.5932699921∂z1(2)∂W11(2)=Y1=0.5932699921
则∂E总∂W(2)11=∂E总∂O1∗∂O1∂z(2)1∗∂z(2)1∂W(2)11=(O1−T1)∗O1(1−O1)∗Y1=0.7413650696∗0.1868156018∗0.5932699921=0.0821670406∂E总∂W11(2)=∂E总∂O1∗∂O1∂z1(2)∗∂z1(2)∂W11(2)=(O1−T1)∗O1(1−O1)∗Y1=0.7413650696∗0.1868156018∗0.5932699921=0.0821670406
到此,我们求出了总体误差对相应隐含层的权重W的偏导数。他的含义是在当前位置上,如果权重W移动一小段距离,会引起总体误差的变化的大小。很容易可以想到,如果求出来的值比较大,证明该权重对误差的影响大,那么我们需要对它调整的步伐也就大。反之,则稍微调整一下就可以了。调整的公式如下:
W(2)new11=W(2)11−η∗∂E总∂W(2)11Wnew11(2)=W11(2)−η∗∂E总∂W11(2)
公式中的ηη 为学习速率,这哥们比较关键,如果取得太大有可能怎么训练都无法取得最优值,取得太小训练速度又非常的慢,且很容易就会陷入局部最优而出不来,关于这块的解释可以参考机器学习的书籍,如果有必要后面会专门出一篇文章来探讨这个问题,本文在示例中取η=0.5η=0.5。
那么,代入数值:
W(2)new11=W(2)11−η∗∂E总∂W(2)11=0.40−0.5∗0.0821670406=0.3589164797Wnew11(2)=W11(2)−η∗∂E总∂W11(2)=0.40−0.5∗0.0821670406=0.3589164797
有了上面的推导,更新隐含层剩下的三个权重可以说易如反掌:
W(2)new12=0.45−0.5∗(O1−T1)∗O1(1−O1)∗Y2=0.4086661861Wnew12(2)=0.45−0.5∗(O1−T1)∗O1(1−O1)∗Y2=0.4086661861
W(2)new21=0.50−0.5∗(O2−T2)∗O2(1−O2)∗Y1=0.5113012703Wnew21(2)=0.50−0.5∗(O2−T2)∗O2(1−O2)∗Y1=0.5113012703
W(2)new22=0.55−0.5∗(O2−T2)∗O2(1−O2)∗Y2=0.5613701211Wnew22(2)=0.55−0.5∗(O2−T2)∗O2(1−O2)∗Y2=0.5613701211
接下来还有输入层到隐含层的权重,基本原理是一样的,但因为所处位置比较前,所有改变这个位置的一个权重会影响两个输出的值,求偏导也要考虑两个输出的影响。
∂E总∂W(1)11=∂E总∂Y1∗∂Y1∂z(1)1∗∂z(1)1∂W(1)11∂E总∂W11(1)=∂E总∂Y1∗∂Y1∂z1(1)∗∂z1(1)∂W11(1)
可以看到,后面两项跟隐含层到输出层的偏导几乎一模一样,可以套用其结论,公式变为:
∂E总∂W(1)11=∂E总∂Y1∗Y1(1−Y1)∗X1∂E总∂W11(1)=∂E总∂Y1∗Y1(1−Y1)∗X1
现在主要就要求∂E总∂Y1∂E总∂Y1,回头看本文一开始的图片,可以看到E总E总和Y1Y1的距离是比较远的,无法直接求偏导,因而需要通过链式法则再展开一下。
∂E总∂Y1=∂(EO1+EO2)∂Y1=∂EO1∂Y1+∂EO2∂Y1∂E总∂Y1=∂(EO1+EO2)∂Y1=∂EO1∂Y1+∂EO2∂Y1
因为∂EO1∂Y1∂EO1∂Y1与∂EO2∂Y1∂EO2∂Y1形式相同,因而先看前者。
∂EO1∂Y1=∂EO1∂O1∗∂O1∂z(2)1∗∂z(2)1∂Y1∂EO1∂Y1=∂EO1∂O1∗∂O1∂z1(2)∗∂z1(2)∂Y1
前面两项之前求过,因此上式变成:
∂EO1∂Y1=∂EO1∂O1∗∂O1∂z(2)1∗∂z(2)1∂Y1=(O1−T1)∗O1(1−O1)∗∂z(2)1∂Y1∂EO1∂Y1=∂EO1∂O1∗∂O1∂z1(2)∗∂z1(2)∂Y1=(O1−T1)∗O1(1−O1)∗∂z1(2)∂Y1
又∂z(2)1∂Y1=∂(W(2)11Y1+W(2)12Y2+K2)∂Y1=W(2)11∂z1(2)∂Y1=∂(W11(2)Y1+W12(2)Y2+K2)∂Y1=W11(2)
故∂EO1∂z(1)1=(O1−T1)∗O1(1−O1)∗W(2)11∂EO1∂z1(1)=(O1−T1)∗O1(1−O1)∗W11(2)
同理∂EO2∂z(1)1=(O2−T2)∗O2(1−O2)∗W(2)21∂EO2∂z1(1)=(O2−T2)∗O2(1−O2)∗W21(2)
则∂E总∂W(1)11=((O1−T1)∗O1(1−O1)∗W(2)11+(O2−T2)∗O2(1−O2)∗W(2)21)∗Y1(1−Y1)∗X1∂E总∂W11(1)=((O1−T1)∗O1(1−O1)∗W11(2)+(O2−T2)∗O2(1−O2)∗W21(2))∗Y1(1−Y1)∗X1
代入数值可求得
∂E总∂W(1)11=0.000438568∂E总∂W11(1)=0.000438568
则参数更新为
W(1)new11=W(1)11−η∗∂E总∂W(1)11=0.149781Wnew11(1)=W11(1)−η∗∂E总∂W11(1)=0.149781
同理可求得:
W(1)new12=W(1)12−η∗∂E总∂W(1)12=0.199561Wnew12(1)=W12(1)−η∗∂E总∂W12(1)=0.199561
W(1)new21=W(1)21−η∗∂E总∂W(1)21=0.249751Wnew21(1)=W21(1)−η∗∂E总∂W21(1)=0.249751
W(1)new22=W(1)22−η∗∂E总∂W(1)22=0.299502Wnew22(1)=W22(1)−η∗∂E总∂W22(1)=0.299502
到此,理论部分就都讲完了,万岁!!!
在这里在此说明下,本文主要参考一文弄懂神经网络中的反向传播法——BackPropagation这篇文章。