卷积神经网络Step by Step(二)
上一篇博客对卷积神经网络的几个重要概念进行总结,现在就从代码的角度对”卷积”,”池化”,”反向传播”进行详细的分析。
代码是基于“UFLDL Tutorial”的excercise代码中的cnn部分实现的,系列博客的最后我会把代码的Github地址分享出来。
“卷积”层
卷积层的核心实现由函数cnnConvolve.m完成,输入参数中filterDim是指特征提取模块的维数(即
先给出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的剖析:
由于我们需要在卷积完成后得到有效数据,即在matlab的conv2函数调用中加了”valid”标志,所以不需要对两个矩阵进行补零操作。
怎么理解这个所谓的二维卷积的过程?相信大家都对一维卷积很熟悉,类似的,二维卷积最开始也有一个翻转的过程,只不过是对矩阵进行上下并且左右反转。在matlab里面的实现是函数
接下来呢,我们拿着这个
从上面的分析可以看出,二维卷积实际上实现的还是一个对应相乘并求和累加的过程:
其中
现在我们就明白了以”卷积”来命名卷积神经网络的原因,在做二维信号(以图像为例)的特征提取时,其基本思想还是和一维的一致,即用权重向量
从代码中的一个小细节可以很好的解释,在调用conv2之间我们对特征提取的向量进行180度的翻转,之前提到过在convolution的过程也要对输入的filter进行翻转,这样一来一回,相互抵消,最终还是原来输入的特征提取向量。这就从侧面说明,卷积层其实并不是要用做卷积,而是用卷积来实现特征提取,核心作用还是分块的特征提取!
filter_rot = rot90(squeeze(filter),2);
再往下看代码,最后就是调用激活函数生成最终的提取到的特征。
convolvedImage = sigmoid(convolvedImage);
这样我们就得到了卷积层输出的特征,对于一副大小为