联系我们
- 地 址:北京市海淀区北四环西路9号 ,主 营:人脸识别,活体检测,身份证识别,银行卡识别,名片识别,车牌识别,OCR识别等及智能识别技术。
- 电 话:13146317170 廖经理
- 传 真:
- 邮 箱:398017534@qq.com
深度学习神经网络:多层网络和C++实现
深度学习神经网络:多层网络和C++实现
一、引言
在前一篇关于神经网络的文章中,给出了神经网络中单个神经元的构造和作用原理,并且用梯度降落的办法推导了单个SIMGOID单元的权值更新规律。在文章的最后给了一个例子,我们以一个4维的单位向量作为特征,映射到一维的[0,1]的空间中,我们采用了一个感知器单元,实验结果发现经过15000次(实践应该在5000次左右曾经收敛了)的锻炼后,关于给出的特征向量,感知器单元总是可以得到很接近我们预期的结果了。但是在实践应用过程中,单个神经元不能拟合太复杂的映射关系,我们需求构建更复杂的网络来迫近那些更复杂的目的函数,本文的最后,我们会用多层网络处置前一篇文章中的例子,经过300-500次的锻炼,就能够很好的收敛。
本篇文章为神经网络这个主题的第二篇文章,主要引见多层网络的构造及用反向传播算法对权值停止更新,最后我们会一步一步用C++对整个构造停止完成。
二、多层网络构造
多层网络,望文生义就是由多个层构造组成的网络系统,它的每一层都是由若干个神经元结点构成,该层的恣意一个结点都与上一层的每一个结点相联,由它们来提供输入,经过计算产生该结点的输出并作为下一层结点的输入。
值得留意的是任何多层的网络构造必需有一输入层、一个输出层。下面的图构造是更形象的表示:
我们从图像中来再次阐明多层网络的构造:上图是一个3层的网络构造,它由一个输入层、一个输出层和一个躲藏层构成,当然躲藏层的层数能够更多。图像躲藏层的结点ii与输入层的每一个结点相连,也就是说它接纳了一组向量input=[x1,x2,x3,⋯,xn]input=[x1,x2,x3,⋯,xn]作为输入,同时与它相连的n条线代表了n个输入的权值。特别要留意的是图像躲藏层结点与输出结点还有一个红色的连线,它们代表了偏置,即w0w0。
那么分离上篇文章的内容,我们晓得图像的i结点,它将输入与对应的权值停止线性加权求和,然后经过sigmoid函数sigmoid函数计算,把得到的结果作为该个结点的输出。
neti=w0+x1w1+x2w2+x3w3+xnwn=∑i=0N=nxiwi.(其中x0=1)neti=w0+x1w1+x2w2+x3w3+xnwn=∑i=0N=nxiwi.(其中x0=1)
oi=11+e−netioi=11+e−neti
整个多层网络就是由一组输入开端,然后按每条连结线的权重,停止不断的向前计算。这里我们进一步对上面这个网络构造停止量化,以便后面完成:首先它是一个三层的网络构造,第一层是输入层,它自身没有接纳输入,也没有连线进来;第二层有3个结点,并且有3*(4+1)根连结线,留意每个结点有一个偏置线;最后一层是输出层,它有4个结点,并且有4*(3+1)根连结线。所以说整个网络构造为[layer1,layer2,layer3][layer1,layer2,layer3],而每一层都是这样的构造:layer=[nodes,weights]layer=[nodes,weights]。
三、反向传播算法
我们曾经在上篇文章中讨论了单个结点用梯度降落的办法,能够去更新权值向量。而关于多层网络构造,我们也能够用相似的办法也推导整个网络的权值更新规律,我们把这种办法叫作反向传播算法,由于它是从输出层开端向前逐层更新权值的。
那么我们先从输出层思索,还是先思索整个输出误差是几?不同与单个感知器单元(一个输出),多层网络构造具有多个输出,那么它的误差计算公式能够用LSM规律表示如下:
E(w)=12∑d∈D∑k∈outputs(tkd−okd)2E(w)=12∑d∈D∑k∈outputs(tkd−okd)2
其中,outputsoutputs是网络输出单元的汇合,DD还是代表一切锻炼样本空间,tkdtkd和okdokd是与锻炼样例dd和第kk个输出单元相关的预期值与输出值。
我们的目的是搜索一个宏大的假定空间,这个假定空间由网络构造中一切可能的权值构成。假如用几何的定义来考虑,那么这个宏大的搜索空间构成了一个误差曲面,我们需求找到这个曲面上的最小值点。显然,梯度降落是我们的一个办法,我们经过计算曲面任何点的梯度方向,然后沿着反方向去改动权值,就会使误差变小。
回想我们一篇文章讲到的随机梯度降落规律,我们将它应用在多层网络的反向传播算法中。我们每次只处置一个样本实例,然后更新各个权值,经过大量的样本实例逐步的调整权值。那么关于每一次的锻炼样例dd来说,它的输出误差为:
Ed(w)=12∑k∈outputs(tkd−okd)2Ed(w)=12∑k∈outputs(tkd−okd)2
关于输出层的结点上的连线权值,很明显它们能够直接影响到最终的误差,而躲藏层结点上的连结线权值只能间接的影响最后的结果,所以我们分两种状况来推导反向传播算法。
状况1:关于输出单元的权值锻炼规律:
我们晓得每个结点前的一切连结线只能经过影响net(net的定义在上面的公式中)的结果来影响误差E,所以有:
∂Ed∂wi=∂Ed∂net∂net∂wi=∂Ed∂netxi∂Ed∂wi=∂Ed∂net∂net∂wi=∂Ed∂netxi
所以我们只用推导出∂Ed∂net∂Ed∂net即可。
∂Ed∂net=∂Ed∂o∂o∂net=−(t−o)o(1−o)∂Ed∂net=∂Ed∂o∂o∂net=−(t−o)o(1−o)
将上面的两个公式兼并,我们就得到了更新权值的规律,如下:
wi←wi+ΔwΔw=−η∂Ed∂wixi=η(t−o)o(1−o)xiwi←wi+ΔwΔw=−η∂Ed∂wixi=η(t−o)o(1−o)xi
我们把其中的(t−o)o(1−o)(t−o)o(1−o)看成与该个结点相关的误差项,并用符号δδ表示。
状况2:躲藏单元的权值锻炼规律
躲藏层中的恣意结点上的连结线权值都是经过影响以它的输出作为输入的下一层(downstream)的结点而最终影响误差的,所以躲藏层的推导如下:
∂Ed∂neti=∑k∈ds(i)∂Ed∂netk∂netkneti=∑k∈ds(i)−δk∂netkneti=−oi(1−oi)∑k∈ds(i)δkwki∂Ed∂neti=∑k∈ds(i)∂Ed∂netk∂netkneti=∑k∈ds(i)−δk∂netkneti=−oi(1−oi)∑k∈ds(i)δkwki
所以躲藏层单元权值更新规律为:
wi←wi+ΔwiΔwi=−ηδixiδi=o(1−o)∑k∈ds(i)δkwkiwi←wi+ΔwiΔwi=−ηδixiδi=o(1−o)∑k∈ds(i)δkwki
OK,上面内容就是反向传播算法,上面公式中有些中间推导步骤省略了,无非是一些链式规律求导的内容。不过就算没弄分明整个推导过程也没有关系,只需按下面的算法来更新你的一切权值即可。
1,关于锻炼样例training_examples中的每个<x⃗ ,t⃗ ><x→,t→>,把输入沿网络传播,计算出网络中每个单元uu的输出ouou;
2,关于网络中的每个输出单元kk,计算它的误差项δkδk
δk←ok(1−ok)(tk−ok)δk←ok(1−ok)(tk−ok)
3,关于网络中的每个躲藏的单元hh,计算它的误差项δhδh
δh←oh(1−oh)∑k∈outputswkhδkδh←oh(1−oh)∑k∈outputswkhδk
4,更新每个网络权值wjiwji
wji←wji+Δwji,其中,Δwji=ηδjxjiwji←wji+Δwji,其中,Δwji=ηδjxji
四、深化讨论
收敛性与部分最小值
正如前面所说的反向传播算法完成了一种对可能的网络权值空间的梯度降落搜索,它不时迭代从而减小锻炼样例目的值与网络输出之间的误差。但由于多层网络,误差曲面可能含有多个不同的部分极小值,我们的梯度降落能够收敛在这些极小值中。因而,关于多层网络,反向传播算法仅能保证收敛到误差E的某个部分极小值,不一定收敛到全局最小误差。
虽然缺乏对收敛到全局最小误差的保证,反向传播算法在理论中仍是十分有效的函数迫近算法。对很多实践中的应用,人们发现部分最小值的问题没有想像的那么严重。由于部分极小值常常是关于某个权值而言,些时其他权值一定也是极小值。事实上网络的权越多,误差曲面维数越多,也就越可能为梯度降落提供更多的“逃逸道路”让梯度降落分开相对该单个权值的部分极小值。
另外一个观念是,我们开端给权值初始化的值都十分小,接近于0,在这样小权值的状况下,sigoid函数能够近似的看为线性的,所以在权值变化的初期是不存在部分极小值问题的,而到了后期整个网络到了高度非线性的时分,可能这里的极小值点曾经很接近全局最小值了。
多层网络的处置才能
很多人都会在这里发出疑问,什么类型的函数能够运用多层网络来表示呢?或者说什么样的分类问题能够用多层网络来表示呢?答案是:恣意函数。恣意函数能够被一个有三层单元的网络以恣意精度迫近(Cybenko 1988)。但是值得留意的是,我们运用的梯度降落算法并没有搜索整个权值空间,所以我们很可能会漏掉那个最适宜的权值汇合。
归结偏置
什么是归结偏置?举个例子,假设我们有两个样本x1=[1,0,0,0]x1=[1,0,0,0]和x2=[0.8,0,0,0]x2=[0.8,0,0,0]并且我们以为它们属于同一类别,即假如把它们作为神经网络的输入,我们希望它们得到同样的输出。锻炼样本中只要这两个实例,但是假如我们需求得到x3=[0.9,0,0,0]x3=[0.9,0,0,0]的输出时,它的结果会和x1x1,x2x2的输出一样。神经网络的这种才能,我们称它为归结偏置的才能,实践网络是在数据点之间平滑插值。
过度拟合
由于我们搜集到的样本中有些样本可能由于我们分类错误等缘由,形成了一个错误的样本用例,实践上神经网络对这种带有噪点的样本的顺应性很强。但是在上面我们引见的原理中,我们并没有规则权值迭代更新的终止条件,常常我们是设置了一个迭代次数来控制,也就有可能形成,在锻炼的后期那些权值是过度拟合那些噪点样本。这个问题没有统一的处理计划,如今比拟常用的办法就是经过穿插考证,即在锻炼的同时,用一组校验校本停止测试,找出分类率回降的一个点,从而终于锻炼过程。
五、ANN的完成
我们首先来定义几个类,用它们来分别表示神经网络构造中一些根本组件:整个网络(NeuralNetwork)、单层网络(NNlayer)、神经元结点(NNneural)、衔接线(NNconnection)。
首先整个网络包含了一些参数,如层数、每层的结点数、迭代次数、每次实例的输出等,同时一个网络构造应该有的功用:设置参数、初始化网络、网络向前传播、反向传播、样本输入、锻炼等。
1 class NNlayer;
2 class NNneural;
3 class NNconnection;
4
5 class NeuralNetwork
6 {
7 private:
8 unsigned nLayer; // 网络层数
9 vector nodes; // 每层的结点数
10 vector actualOutput; // 每次迭代的输出结果
11 double etaLearningRate; // 权值学习率
12 unsigned iterNum; // 迭代次数
13 public:
14 vector<NNlayer*> m_layers; // 整个网络层
15 void create(unsigned num_layers,unsigned * ar_nodes); // 创立网络
16 void initializeNetwork(); // 初始化网络,包括设置权值等
17 void forwardCalculate(vector& invect,vector& outvect); // 向前计算
18 void backPropagate(vector& tVect,vector& oVect); //反向传播
19
20 void train(vector<vector>& inputVect,vector<vector>& outputVect); //锻炼
21 void classifer(vector& inVect,vector& outVect); // 分类
22 };
然后设计单层网络构造,我们需求一个指针成员来阐明层与层之间的衔接关系,同时每层网络是由大量的神经元结点构成,同时我们将权值向量作为了每一层的成员,为什么没有将权值与每个结点上的衔接线捆在一同呢?那是由于到后面引见到卷积神经网络的时分,你会发现很多结点能够共有一个权值。
1 class NNlayer
2 {
3 public:
4 NNlayer(){ preLayer = NULL; }
5 NNlayer *preLayer;
6 vector m_neurals;
7 vector m_weights;
8 void addNeurals(unsigned num, unsigned preNumNeurals);
9 void backPropagate(vector& dErrWrtDxn, vector& dErrWrtDxnm, double eta);
10 };
然后就是每个结点类和结点上的衔接线,每个结点包含了一个输出和若干个衔接线。这里衔接线里保管是两个索引值,它标明条衔接线的权重在整个权重向量中的索引与它衔接的前面一层结点的索引。
1 class NNneural
2 {
3 public:
4 double output;
5 vector m_connection;
6
7 };
8 class NNconnection
9 {
10 public:
11 unsigned weightIdx;
12 unsigned neuralIdx;
13 };
上面是根本的数据构造,而我们整个算法的中心就在于向前计算与反向传播来更新阈值,也就是函数forwardCalculate()和backPropagate()。
向前传播函数其实比拟简单,留意第一层是输入层,它不承受来自其他层的输入,我们只需将它一切结点的输出设置为锻炼样本的特征即可。而反向传播函数,将最后一层与躲藏层辨别开来,由于它们更新权值的规律不同,并且这个工作由每一层的backPropagate()函数来完成。
下面是整个代码中比拟重要的几个函数,需求完好代码的能够联络我。
initializeNetwork
addNeurals
forwardCalculate
backPropagate
这里我们想起上篇文章中的一个例子,这里我们用多层的网络来再次去拟合那个目的函数,我们用了3层的网络构造,躲藏层设置了20层,而这里我们没有将结果设置为1维,而是用一个4维向量组成也就是与输入向量分歧。下面是经过500迭代后产生的结果,并组我们最后以一组[0.01,0.99,0.001,-0.05]这样的输入来测试,我们预期的结果是[0,1,0,0],而程序得到的结果是[0.027,0.999,0.011,-0.046]。
六、完毕语
到这里,神经网络的根本构造和最常见的锻炼规律曾经引见完了,但是神经网络的开展曾经有几十年的历史了,期间呈现了各种的变种,让神经网络开展为了不同的品种,但它的根本思绪都是不变的,正如下一篇文章行将引见的卷积神经网络。
上一条:视频字幕OCR辨认技术
下一条:深度学习框架之争