卷积神经网络Step by Step(三)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wblgers1234/article/details/72795163

卷积神经网络Step by Step(三)
系列的第一篇博客(一)对卷积神经网络的几个重要概念进行总结,现在就从代码的角度对”卷积”,”池化”,”反向传播”进行详细的分析。

代码是基于“UFLDL Tutorial”的excercise代码中的cnn部分实现的,系列博客的最后我会把代码的Github地址分享出来。

“池化”
回顾卷积神经网络Step by Step(一)中对“池化”的介绍,为了将卷积层得到的大量特征减少,以避免训练中产生过拟合,我们一般采用“平均值池化”和“最大值池化”。

先给出函数cnnPool.m的完整代码:

function pooledFeatures = cnnPool(poolDim, convolvedFeatures)    

% 初始化定义,从输入的卷积特征中取出图像数,特征提取个数,卷积维数
numImages = size(convolvedFeatures, 4);
numFilters = size(convolvedFeatures, 3);
convolvedDim = size(convolvedFeatures, 1);

pooledFeatures = zeros(convolvedDim / poolDim, ...
        convolvedDim / poolDim, numFilters, numImages);

% 对于每一副训练图像的每一个特征提取滤波器,进行平均值池化
for imageNum = 1:numImages
  for filterNum = 1:numFilters
      % 取出二维卷积特征
      tempFeature = convolvedFeatures(:,:,filterNum,imageNum);
      % 用全1的矩阵作为卷积滤波器
      filter_rot = ones(poolDim,poolDim);
      % 二维卷积进行滑动平均值计算
      tempPooledFeature = conv2(tempFeature,filter_rot,'valid')/(size(filter_rot,1)*size(filter_rot,2));
      % 下采样,筛选特征
      pooledFeatures(:,:,filterNum,imageNum) = tempPooledFeature(1:poolDim:size(tempPooledFeature,1),1:poolDim:size(tempPooledFeature,2));
  end

end

end

函数中巧妙地利用二维卷积函数conv2完成平均值池化,是怎样实现的呢?其实很简单,还记得之前在介绍池化时的演示图吗?如下所示,池化处理是在原始的卷积特征上进行不重叠的下采样,平均值池化就是将每个不重叠的二维区域的特征值累加然后取平均得到一个输出值,作为整块池化区域的特征代表;最大值池化就是将每个不重叠的二维区域的特征值中取出一个最大值,作为整块池化区域的特征代表。
这里写图片描述
那么将一块二维特征区域和一个全“1”的卷积核进行二维卷积conv2,在滑动的过程中可以得到每个区域(大小和卷积核的维数相当)的特征值累加,再除以池化区域的大小( poolDim×poolDim )即可得到平均值。

tempPooledFeature = conv2(tempFeature,filter_rot,'valid')/(size(filter_rot,1)*size(filter_rot,2));

举个例子来说明,利用conv2来实现二维矩阵分池化区域求和的过程:

x=111111111,filter=[1111]

conv2(x,filter,valid)=[2002]

这个二维卷积过程是按元素平移,即池化区域之间是有重叠的,所以需要进行下采样完成最后的操作,这部分代码很简单不再赘述。

pooledFeatures(:,:,filterNum,imageNum) = tempPooledFeature(1:poolDim:size(tempPooledFeature,1),1:poolDim:size(tempPooledFeature,2));

池化处理的介绍和代码解析就先到这里,下一篇将对卷积神经网络的前向传播和方向传播的代码进行解析。

猜你喜欢

转载自blog.csdn.net/wblgers1234/article/details/72795163