标签:【神经网络与深度学习】git
实际上前面已经发布过一次,可是此次从新复习了一下,决定再发博一次。github
说明:之后的总结,还应该以个人认识进行总结,这样比较符合我认知的习惯,而不是单纯的将别的地方的知识复制过来,这样并起不到好的总结效果。相反,若是可以将本身的体会写下来,当有所遗忘时还能顺着当时总结的认识思路,从新“辨识”起来,因此,要总结,而不要搬运知识。web
起初并不理解卷积神经的卷积与结构是什么,后来经过了一个比较好的例子才对卷积神经网络有了初步的认识,这里对这一阶段的认识进行总结。算法
首先,一提到卷积,首先想到的是在信号与系统、数字信号处理中所讲的,作一下翻转平移而后再作点积求和,由于这是第一次引入卷积。后来到了数字图像处理的课程中学习了卷积核,实现的是其实是空域滤波,好比边缘检测技术中经常使用的sobel算子、梯度算子、laplace算子等。网络
而后是分析卷积神经网络的结构。能够经过下图所示的一个例子进行分析:svg
卷积神经网络是一个多层神经网络,图示中包括输入层、卷积层(C1)、子采样层(S2)、卷积层(C3)、子采样层(S4)、卷积层(C5)和输出层。
其工做流程是:输入层有
上面三点内容说明了卷积层所进行的工做,经过8个不一样的
下面有卷积层C1到子采样层S2实现的是子抽样和局部平均,将C1层获得的8个
经过卷积得到特征以后,若是直接训练分类器,计算量特别大,并且如此大维度的特征向量对分类器来说,容易出现过拟合现象。好比对于一个
解决的方法就是降采样,经过某一个区域的特征平均值或最大值等这些概要统计特征来对不一样位置上的特征进行聚合统计。具备将低维度和改善结果(不容易过拟合)的做用。这种聚合的操做叫作池化,也称为平均池化或最大池化等。以下图所示:
红色区域内的平均值做为该区域的统计特性,实现降采样过程,也就是池化过程。atom
所以,再通过一次卷积层C3和子采样层S4,便获得了较小的特征描述20个
稍微细心一点就能发现,由S2层到C3层,从8个特征映射层到20个特征映射层,并非整数倍的关系,这说明C3层的每一个特征映射并非将多少个卷积核分别做用在S2层的特征映射上,即须要注意C3中每个特征map是链接到S2中的全部8个,或者几个特征map上的,表示本层的特征map是上一层提取到的特征map的不一样组合,即所谓相似边缘构成形状或者目标的部分等特色。但为何不让S2中的全部特征map全连结到C3层的特征图上呢?缘由有2:一是不彻底链接机制将链接的数量保持在合理的范围内;二是破坏网络的对称性,因为不一样的特征图有不一样的输入,迫使之抽取不一样的特征(互补)。这里盗用一张图说明一下组合状况:
好比C3层有16个,S2层有6个,如何map的链接呢,能够参看下图的组合形式:
spa
C3层的0号map由S2层的0-2号map映射而来,以此类推。以C3层的0号特征图获取过程为例,将0号卷积核分别在S2层的前三个map上进行卷积,并求和,以后加入偏移量,经过sigmoid函数进行激发,就能够获得C3层的0号特征图了。
卷积以后紧跟着子抽样的思想是受到动物视觉系统的“简单的”细胞后面跟着“复杂的”细胞的想法的启发而产生的。具体意义在上面已经分析过。
最后要将的就是CNN的学习,上面讲的例子的CNN网络结构能够简化为以下:
其中input层到C1,S4到C5,C5到output是全连结,C1到S二、C3到S4 是一一对应的链接,而S2到C3为了消除对称性,去掉了部分链接,可让特征映射具备多样性。须要注意的是C5层卷积核的尺寸要与S4层输出相同,保证输出为1维向量。
卷积层的典型结构以下:
卷积层的前馈输出经过以下的公式进行计算:
ConvolutionLayer::fprop(input,output) { //取得卷积核的个数 int n=kernel.GetDim(0); for (int i=0;i<n;i++) { //第i个卷积核对应输入层第a个特征映射,输出层的第b个特征映射 //这个卷积核能够形象的看做是从输入层第a个特征映射到输出层的第b个特征映射的一个连接 int a=table[i][0], b=table[i][10]; //用第i个卷积核和输入层第a个特征映射作卷积 convolution = Conv(input[a],kernel[i]); //把卷积结果求和 sum[b] +=convolution; } for (i=0;i<(int)bias.size();i++) { //加上偏移量 sum[i] += bias[i]; } //调用Sigmoid函数 output = Sigmoid(sum); }
其中,input是 n1×n2×n3 的矩阵,n1是输入层特征映射的个数,n2是输入层特征映射的宽度,n3是输入层特征映射的高度。output, sum, convolution,bias是n1×(n2-kw+1)×(n3-kh+1)的矩阵,kw,kh是卷积核的宽度高度(图中是5×5)。kernel是卷积核矩阵。table是链接表,即若是第a输入和第b个输出之间有链接,table里就会有[a,b]这一项,并且每一个链接都对应一个卷积核。
卷积层的反馈运算的核心代码以下:
ConvolutionLayer::bprop(input,output,in_dx,out_dx) { //梯度经过DSigmoid反传 sum_dx = DSigmoid(out_dx); //计算bias的梯度 for (i=0;i<bias.size();i++) { bias_dx[i] = sum_dx[i]; } //取得卷积核的个数 int n=kernel.GetDim(0); for (int i=0;i<n;i++) { int a=table[i][0],b=table[i][11]; //用第i个卷积核和第b个输出层反向卷积(即输出层的一点乘卷积模板返回给输入层),并把结果累加到第a个输入层 input_dx[a] += DConv(sum_dx[b],kernel[i]); //用一样的方法计算卷积模板的梯度 kernel_dx[i] += DConv(sum_dx[b],input[a]); } }
其中in_dx,out_dx 的结构和 input,output 相同,表明的是相应点的梯度。
子采样层的学习
自采样层的典型结构以下:
SubSamplingLayer::fprop(input,output) { int n1= input.GetDim(0); int n2= input.GetDim(1); int n3= input.GetDim(2); for (int i=0;i<n1;i++) { for (int j=0;j<n2;j++) { for (int k=0;k<n3;k++) { //coeff 是可训练的权重,sw 、sh 是采样窗口的尺寸。 sub[i][j/sw][k/sh] += input[i][j][k]*coeff[i]; } } } for (i=0;i<n1;i++) { //加上偏移量 sum[i] = sub[i] + bias[i]; } output = Sigmoid(sum); }
子采样层的反馈运算的核心代码以下:
SubSamplingLayer::bprop(input,output,in_dx,out_dx) { //梯度经过DSigmoid反传 sum_dx = DSigmoid(out_dx); //计算bias和coeff的梯度 for (i=0;i<n1;i++) { coeff_dx[i] = 0; bias_dx[i] = 0; for (j=0;j<n2/sw;j++) for (k=0;k<n3/sh;k++) { coeff_dx[i] += sub[j][k]*sum_dx[i][j][k]; bias_dx[i] += sum_dx[i][j][k]); } } for (i=0;i<n1;i++) { for (j=0;j<n2;j++) for (k=0;k<n3;k++) { in_dx[i][j][k] = coeff[i]*sum_dx[i][j/sw][k/sh]; } } }
全连结层实际上就相似BP网络了,具体能够参考BP算法。
关于CNN的完整代码能够参考https://github.com/ibillxia/DeepLearnToolbox/tree/master/CNN中的Matlab代码
主要参考资料:
http://ibillxia.github.io/blog/2013/04/06/Convolutional-Neural-Networks/
http://blog.csdn.net/nan355655600/article/details/17690029
http://www.36dsj.com/archives/24006
2016-9-27 22:40 张朋艺 pyZhangBIT2010@126.com