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

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

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

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

“卷积”层

卷积层的核心实现由函数cnnConvolve.m完成,输入参数中filterDim是指特征提取模块的维数(即 filterDimfilterDim ),numFilters是指特征提取模块的个数。

先给出cnnConvolve.m的完整代码:

function convolvedFeatures = cnnConvolve(filterDim, numFilters, images, W, b)

numImages = size(images, 3);
imageDim = size(images, 1);
convDim = imageDim - filterDim + 1;

convolvedFeatures = zeros(convDim, convDim, numFilters, numImages);

% 用每一个特征提取权重(即二维滤波系数)对每幅图片进行处理卷积处理
for imageNum = 1:numImages
  for filterNum = 1:numFilters
    % 卷积操作后提取得到的特征矩阵
    convolvedImage = zeros(convDim, convDim);

    % 从权重矩阵中提取每一个二维的特征提取权重(filterDim * filterDim)
    filter = W(:,:,filterNum);
    % 对特征提取权重矩阵进行上下左右翻转
    filter_rot = rot90(squeeze(filter),2);

    % 提取图像
    im = squeeze(images(:, :, imageNum));

    % 二维卷积进行特征提取并加上bias偏差
    convolvedImage = conv2(im,filter_rot,'valid')+b(filterNum);

    % 用sigmod函数来得到激活值
    convolvedImage = sigmoid(convolvedImage);

    convolvedFeatures(:, :, filterNum, imageNum) = convolvedImage;
  end
end

在实现中我们着重关注卷积操作:

 % 二维卷积进行特征提取并加上bias偏差
    convolvedImage = conv2(im,filter_rot,'valid')+b(filterNum);

以下面的一个例子进行conv2的剖析:

x=111111111,filter=[1324]

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

由于我们需要在卷积完成后得到有效数据,即在matlab的conv2函数调用中加了”valid”标志,所以不需要对两个矩阵进行补零操作。

怎么理解这个所谓的二维卷积的过程?相信大家都对一维卷积很熟悉,类似的,二维卷积最开始也有一个翻转的过程,只不过是对矩阵进行上下并且左右反转。在matlab里面的实现是函数 rot90(filter,2)

rot90(filter,2)=[4231]

接下来呢,我们拿着这个 22 的矩阵依次和矩阵 x 里的每个 22 的矩阵块进行对应相乘并累加,这也是和一维卷积里面的滑动类似。
out(1,1)=sum([1111].[4231])=2

out(1,2)=sum([1111].[4231])=2

out(2,1)=sum([1111].[4231])=4

out(2,2)=sum([1111].[4231])=2

从上面的分析可以看出,二维卷积实际上实现的还是一个对应相乘并求和累加的过程:
out(i,j)=wi,j(1×n)xi,j(1×n)

其中 n=filterDimfilterDim ,可以理解为把二维矩阵拉伸为一个列向量再做处理。

现在我们就明白了以”卷积”来命名卷积神经网络的原因,在做二维信号(以图像为例)的特征提取时,其基本思想还是和一维的一致,即用权重向量 w 对信号向量 x 进行提取,然后再用激活函数(例如sigmoid)进行特征激活,从而得到最终的输出。但是呢,我们可以用二维卷积这个数学操作加速激活函数之前的特征提取过程,很多数学计算工具,包括matlab, python的numpy都有内置的优化好的用于二维卷积的函数,这样就对我们的开发提供了很多便利。

从代码中的一个小细节可以很好的解释,在调用conv2之间我们对特征提取的向量进行180度的翻转,之前提到过在convolution的过程也要对输入的filter进行翻转,这样一来一回,相互抵消,最终还是原来输入的特征提取向量。这就从侧面说明,卷积层其实并不是要用做卷积,而是用卷积来实现特征提取,核心作用还是分块的特征提取!

filter_rot = rot90(squeeze(filter),2);

再往下看代码,最后就是调用激活函数生成最终的提取到的特征。

convolvedImage = sigmoid(convolvedImage);

这样我们就得到了卷积层输出的特征,对于一副大小为 r×c 的图像,如果二维卷积块的大小为 a×b ,特征提取向量filter的组数为 k ,那么最终的特征维数是 k×(ra+1)×(cb+1) ,还是挺大的。我们接下来会引入池化对特征进行聚合,请看下一篇博客。

猜你喜欢

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