Deep Learning 学习随记(七)Convolution and Pooling --卷积和池化
图像大小与参数个数:
前面几章都是针对小图像块处理的,这一章则是针对大图像进行处理的。两者在这的区别还是很明显的,小图像(如8*8,MINIST的28*28)可以采用全连接的方式(即输入层和隐含层直接相连)。但是大图像,这个将会变得很耗时:比如96*96的图像,若采用全连接方式,需要96*96个输入单元,然后如果要训练100个特征,只这一层就需要96*96*100个参数(W,b),训练时间将是前面的几百或者上万倍。所以这里用到了部分联通网络。对于图像来说,每个隐含单元仅仅连接输入图像的一小片相邻区域。
这样就引出了一个卷积的方法:
convolution:
自然图像有其固有特性,也就是说,图像的一部分的统计特性与其他部分是一样的。这也意味着我们在这一部分学习的特征也能用在另一部分上,所以对于这个图像上的所有位置,我们都能使用同样的学习特征。
对于图像,当从一个大尺寸图像中随机选取一小块,比如说8x8作为样本,并且从这个小块样本中学习到了一些特征,这时我们可以把从这个8x8样本中学习到的特征作为探测器,应用到这个图像的任意地方中去。特别是,我们可以用从8x8样本中所学习到的特征跟原本的大尺寸图像作卷积,从而对这个大尺寸图像上的任一位置获得一个不同特征的激活值。
讲义中举得具体例子,还是看例子容易理解:
假设你已经从一个96x96的图像中学习到了它的一个8x8的样本所具有的特征,假设这是由有100个隐含单元的自编码完成的。为了得到卷积特征,需要对96x96的图像的每个8x8的小块图像区域都进行卷积运算。也就是说,抽取8x8的小块区域,并且从起始坐标开始依次标记为(1,1),(1,2),...,一直到(89,89),然后对抽取的区域逐个运行训练过的稀疏自编码来得到特征的激活值。在这个例子里,显然可以得到100个集合,每个集合含有89x89个卷积特征。讲义中那个gif图更形象,这里不知道怎么添加进来...
最后,总结下convolution的处理过程:
假设给定了r * c的大尺寸图像,将其定义为xlarge。首先通过从大尺寸图像中抽取的a * b的小尺寸图像样本xsmall训练稀疏自编码,得到了k个特征(k为隐含层神经元数量),然后对于xlarge中的每个a*b大小的块,求激活值fs,然后对这些fs进行卷积。这样得到(r-a+1)*(c-b+1)*k个卷积后的特征矩阵。
pooling:
在通过卷积获得了特征(features)之后,下一步我们希望利用这些特征去做分类。理论上讲,人们可以把所有解析出来的特征关联到一个分类器,例如softmax分类器,但计算量非常大。例如:对于一个96X96像素的图像,假设我们已经通过8X8个输入学习得到了400个特征。而每一个卷积都会得到一个(96 − 8 + 1) * (96 − 8 + 1) = 7921的结果集,由于已经得到了400个特征,所以对于每个样例(example)结果集的大小就将达到892 * 400 = 3,168,400 个特征。这样学习一个拥有超过3百万特征的输入的分类器是相当不明智的,并且极易出现过度拟合(over-fitting).
所以就有了pooling这个方法,翻译作“池化”?感觉pooling这个英语单词还是挺形象的,翻译“作池”化就没那么形象了。其实也就是把特征图像区域的一部分求个均值或者最大值,用来代表这部分区域。如果是求均值就是mean pooling,求最大值就是max pooling。讲义中那个gif图也很形象,只是不知道这里怎么放gif图....
至于pooling为什么可以这样做,是因为:我们之所以决定使用卷积后的特征是因为图像具有一种“静态性”的属性,这也就意味着在一个图像区域有用的特征极有可能在另一个区域同样适用。因此,为了描述大的图像,一个很自然的想法就是对不同位置的特征进行聚合统计。这个均值或者最大值就是一种聚合统计的方法。
另外,如果人们选择图像中的连续范围作为池化区域,并且只是池化相同(重复)的隐藏单元产生的特征,那么,这些池化单元就具有平移不变性(translation invariant)。这就意味着即使图像经历了一个小的平移之后,依然会产生相同的(池化的)特征(这里有个小小的疑问,既然这样,是不是只能保证在池化大小的这块区域内具有平移不变性?)。在很多任务中(例如物体检测、声音识别),我们都更希望得到具有平移不变性的特征,因为即使图像经过了平移,样例(图像)的标记仍然保持不变。例如,如果你处理一个MNIST数据集的数字,把它向左侧或右侧平移,那么不论最终的位置在哪里,你都会期望你的分类器仍然能够精确地将其分类为相同的数字。
练习:
下面是讲义中的练习。用到了上一章的练习的结构(即在convolution过程中的第一步,用稀疏自编码对xsmall求k个特征)。
以下是主要程序:
主程序cnnExercise.m
%% CS294A/CS294W Convolutional Neural Networks Exercise % Instructions
% ------------
%
% This file contains code that helps you get started on the
% convolutional neural networks exercise. In this exercise, you will only
% need to modify cnnConvolve.m and cnnPool.m. You will not need to modify
% this file. %%======================================================================
%% STEP : Initialization
% Here we initialize some parameters used for the exercise. imageDim = ; % image dimension
imageChannels = ; % number of channels (rgb, so ) patchDim = ; % patch dimension
numPatches = ; % number of patches visibleSize = patchDim * patchDim * imageChannels; % number of input units
outputSize = visibleSize; % number of output units
hiddenSize = ; % number of hidden units epsilon = 0.1; % epsilon for ZCA whitening poolDim = ; % dimension of pooling region %%======================================================================
%% STEP : Train a sparse autoencoder (with a linear decoder) to learn
% features from color patches. If you have completed the linear decoder
% execise, use the features that you have obtained from that exercise,
% loading them into optTheta. Recall that we have to keep around the
% parameters used in whitening (i.e., the ZCA whitening matrix and the
% meanPatch) % --------------------------- YOUR CODE HERE --------------------------
% Train the sparse autoencoder and fill the following variables with
% the optimal parameters: %optTheta = zeros(*hiddenSize*visibleSize+hiddenSize+visibleSize, );
%ZCAWhite = zeros(visibleSize, visibleSize);
%meanPatch = zeros(visibleSize, );
load STL10Features.mat; % -------------------------------------------------------------------- % Display and check to see that the features look good
W = reshape(optTheta(:visibleSize * hiddenSize), hiddenSize, visibleSize);
b = optTheta(*hiddenSize*visibleSize+:*hiddenSize*visibleSize+hiddenSize); displayColorNetwork( (W*ZCAWhite)'); %%======================================================================
%% STEP : Implement and test convolution and pooling
% In this step, you will implement convolution and pooling, and test them
% on a small part of the data set to ensure that you have implemented
% these two functions correctly. In the next step, you will actually
% convolve and pool the features with the STL10 images. %% STEP 2a: Implement convolution
% Implement convolution in the function cnnConvolve in cnnConvolve.m % Note that we have to preprocess the images in the exact same way
% we preprocessed the patches before we can obtain the feature activations. load stlTrainSubset.mat % loads numTrainImages, trainImages, trainLabels %% Use only the first images for testing
convImages = trainImages(:, :, :, :); % NOTE: Implement cnnConvolve in cnnConvolve.m first!
convolvedFeatures = cnnConvolve(patchDim, hiddenSize, convImages, W, b, ZCAWhite, meanPatch); %% STEP 2b: Checking your convolution
% To ensure that you have convolved the features correctly, we have
% provided some code to compare the results of your convolution with
% activations from the sparse autoencoder % For random points
for i = :
featureNum = randi([, hiddenSize]);
imageNum = randi([, ]);
imageRow = randi([, imageDim - patchDim + ]);
imageCol = randi([, imageDim - patchDim + ]); patch = convImages(imageRow:imageRow + patchDim - , imageCol:imageCol + patchDim - , :, imageNum);
patch = patch(:);
patch = patch - meanPatch;
patch = ZCAWhite * patch; features = feedForwardAutoencoder(optTheta, hiddenSize, visibleSize, patch); if abs(features(featureNum, ) - convolvedFeatures(featureNum, imageNum, imageRow, imageCol)) > 1e-
fprintf('Convolved feature does not match activation from autoencoder\n');
fprintf('Feature Number : %d\n', featureNum);
fprintf('Image Number : %d\n', imageNum);
fprintf('Image Row : %d\n', imageRow);
fprintf('Image Column : %d\n', imageCol);
fprintf('Convolved feature : %0.5f\n', convolvedFeatures(featureNum, imageNum, imageRow, imageCol));
fprintf('Sparse AE feature : %0.5f\n', features(featureNum, ));
error('Convolved feature does not match activation from autoencoder');
end
end disp('Congratulations! Your convolution code passed the test.'); %% STEP 2c: Implement pooling
% Implement pooling in the function cnnPool in cnnPool.m % NOTE: Implement cnnPool in cnnPool.m first!
pooledFeatures = cnnPool(poolDim, convolvedFeatures); %% STEP 2d: Checking your pooling
% To ensure that you have implemented pooling, we will use your pooling
% function to pool over a test matrix and check the results. testMatrix = reshape(:, , );
expectedMatrix = [mean(mean(testMatrix(:, :))) mean(mean(testMatrix(:, :))); ...
mean(mean(testMatrix(:, :))) mean(mean(testMatrix(:, :))); ]; testMatrix = reshape(testMatrix, , , , ); pooledFeatures = squeeze(cnnPool(, testMatrix)); if ~isequal(pooledFeatures, expectedMatrix)
disp('Pooling incorrect');
disp('Expected');
disp(expectedMatrix);
disp('Got');
disp(pooledFeatures);
else
disp('Congratulations! Your pooling code passed the test.');
end %%======================================================================
%% STEP : Convolve and pool with the dataset
% In this step, you will convolve each of the features you learned with
% the full large images to obtain the convolved features. You will then
% pool the convolved features to obtain the pooled features for
% classification.
%
% Because the convolved features matrix is very large, we will do the
% convolution and pooling features at a time to avoid running out of
% memory. Reduce this number if necessary stepSize = ;
assert(mod(hiddenSize, stepSize) == , 'stepSize should divide hiddenSize'); load stlTrainSubset.mat % loads numTrainImages, trainImages, trainLabels
load stlTestSubset.mat % loads numTestImages, testImages, testLabels pooledFeaturesTrain = zeros(hiddenSize, numTrainImages, ...
floor((imageDim - patchDim + ) / poolDim), ...
floor((imageDim - patchDim + ) / poolDim) );
pooledFeaturesTest = zeros(hiddenSize, numTestImages, ...
floor((imageDim - patchDim + ) / poolDim), ...
floor((imageDim - patchDim + ) / poolDim) ); tic(); for convPart = :(hiddenSize / stepSize) featureStart = (convPart - ) * stepSize + ;
featureEnd = convPart * stepSize; fprintf('Step %d: features %d to %d\n', convPart, featureStart, featureEnd);
Wt = W(featureStart:featureEnd, :);
bt = b(featureStart:featureEnd); fprintf('Convolving and pooling train images\n');
convolvedFeaturesThis = cnnConvolve(patchDim, stepSize, ...
trainImages, Wt, bt, ZCAWhite, meanPatch);
pooledFeaturesThis = cnnPool(poolDim, convolvedFeaturesThis);
pooledFeaturesTrain(featureStart:featureEnd, :, :, :) = pooledFeaturesThis;
toc();
clear convolvedFeaturesThis pooledFeaturesThis; fprintf('Convolving and pooling test images\n');
convolvedFeaturesThis = cnnConvolve(patchDim, stepSize, ...
testImages, Wt, bt, ZCAWhite, meanPatch);
pooledFeaturesThis = cnnPool(poolDim, convolvedFeaturesThis);
pooledFeaturesTest(featureStart:featureEnd, :, :, :) = pooledFeaturesThis;
toc(); clear convolvedFeaturesThis pooledFeaturesThis; end % You might want to save the pooled features since convolution and pooling takes a long time
save('cnnPooledFeatures.mat', 'pooledFeaturesTrain', 'pooledFeaturesTest');
toc(); %%======================================================================
%% STEP : Use pooled features for classification
% Now, you will use your pooled features to train a softmax classifier,
% using softmaxTrain from the softmax exercise.
% Training the softmax classifer for iterations should take less than
% minutes. % Add the path to your softmax solution, if necessary
% addpath /path/to/solution/ % Setup parameters for softmax
softmaxLambda = 1e-;
numClasses = ;
% Reshape the pooledFeatures to form an input vector for softmax
softmaxX = permute(pooledFeaturesTrain, [ ]);
softmaxX = reshape(softmaxX, numel(pooledFeaturesTrain) / numTrainImages,...
numTrainImages);
softmaxY = trainLabels; options = struct;
options.maxIter = ;
softmaxModel = softmaxTrain(numel(pooledFeaturesTrain) / numTrainImages,...
numClasses, softmaxLambda, softmaxX, softmaxY, options); %%======================================================================
%% STEP : Test classifer
% Now you will test your trained classifer against the test images softmaxX = permute(pooledFeaturesTest, [ ]);
softmaxX = reshape(softmaxX, numel(pooledFeaturesTest) / numTestImages, numTestImages);
softmaxY = testLabels; [pred] = softmaxPredict(softmaxModel, softmaxX);
acc = (pred(:) == softmaxY(:));
acc = sum(acc) / size(acc, );
fprintf('Accuracy: %2.3f%%\n', acc * ); % You should expect to get an accuracy of around % on the test images.
cnnConvolve.m
function convolvedFeatures = cnnConvolve(patchDim, numFeatures, images, W, b, ZCAWhite, meanPatch)
%cnnConvolve Returns the convolution of the features given by W and b with
%the given images
%
% Parameters:
% patchDim - patch (feature) dimension
% numFeatures - number of features
% images - large images to convolve with, matrix in the form
% images(r, c, channel, image number)
% W, b - W, b for features from the sparse autoencoder
% ZCAWhite, meanPatch - ZCAWhitening and meanPatch matrices used for
% preprocessing
%
% Returns:
% convolvedFeatures - matrix of convolved features in the form
% convolvedFeatures(featureNum, imageNum, imageRow, imageCol)
patchSize = patchDim*patchDim;
numImages = size(images, );
imageDim = size(images, );
imageChannels = size(images, ); convolvedFeatures = zeros(numFeatures, numImages, imageDim - patchDim + , imageDim - patchDim + ); % Instructions:
% Convolve every feature with every large image here to produce the
% numFeatures x numImages x (imageDim - patchDim + ) x (imageDim - patchDim + )
% matrix convolvedFeatures, such that
% convolvedFeatures(featureNum, imageNum, imageRow, imageCol) is the
% value of the convolved featureNum feature for the imageNum image over
% the region (imageRow, imageCol) to (imageRow + patchDim - , imageCol + patchDim - )
%
% Expected running times:
% Convolving with images should take less than minutes
% Convolving with images should take around an hour
% (So to save time when testing, you should convolve with less images, as
% described earlier) % -------------------- YOUR CODE HERE --------------------
% Precompute the matrices that will be used during the convolution. Recall
% that you need to take into account the whitening and mean subtraction
% steps
WT = W*ZCAWhite;
bT = b-WT*meanPatch;
% -------------------------------------------------------- convolvedFeatures = zeros(numFeatures, numImages, imageDim - patchDim + , imageDim - patchDim + );
for imageNum = :numImages
for featureNum = :numFeatures % convolution of image with feature matrix for each channel
convolvedImage = zeros(imageDim - patchDim + , imageDim - patchDim + );
for channel = : % Obtain the feature (patchDim x patchDim) needed during the convolution
% ---- YOUR CODE HERE ----
%feature = zeros(,); % You should replace this
offset = (channel-)*patchSize;
feature = reshape(WT(featureNum,(offset+):(offset+patchSize)),patchDim,patchDim); % ------------------------ % Flip the feature matrix because of the definition of convolution, as explained later
feature = flipud(fliplr(squeeze(feature))); % Obtain the image
im = squeeze(images(:, :, channel, imageNum)); % Convolve "feature" with "im", adding the result to convolvedImage
% be sure to do a 'valid' convolution
% ---- YOUR CODE HERE ----
convolveThisChannel = conv2(im,feature,'valid');
convolvedImage = convolvedImage + convolveThisChannel; %三个通道加起来,应该是指三个通道同时用来做判断标准。 % ------------------------ end % Subtract the bias unit (correcting for the mean subtraction as well)
% Then, apply the sigmoid function to get the hidden activation
% ---- YOUR CODE HERE ----
convolvedImage = sigmoid(convolvedImage + bT(featureNum)); % ------------------------ % The convolved feature is the sum of the convolved values for all channels
convolvedFeatures(featureNum, imageNum, :, :) = convolvedImage;
end
end function sigm = sigmoid(x) sigm = ./ ( + exp(-x));
end end
cnnPool.m
function pooledFeatures = cnnPool(poolDim, convolvedFeatures)
%cnnPool Pools the given convolved features
%
% Parameters:
% poolDim - dimension of pooling region
% convolvedFeatures - convolved features to pool (as given by cnnConvolve)
% convolvedFeatures(featureNum, imageNum, imageRow, imageCol)
%
% Returns:
% pooledFeatures - matrix of pooled features in the form
% pooledFeatures(featureNum, imageNum, poolRow, poolCol)
% numImages = size(convolvedFeatures, );
numFeatures = size(convolvedFeatures, );
convolvedDim = size(convolvedFeatures, ); pooledFeatures = zeros(numFeatures, numImages, floor(convolvedDim / poolDim), floor(convolvedDim / poolDim)); % -------------------- YOUR CODE HERE --------------------
% Instructions:
% Now pool the convolved features in regions of poolDim x poolDim,
% to obtain the
% numFeatures x numImages x (convolvedDim/poolDim) x (convolvedDim/poolDim)
% matrix pooledFeatures, such that
% pooledFeatures(featureNum, imageNum, poolRow, poolCol) is the
% value of the featureNum feature for the imageNum image pooled over the
% corresponding (poolRow, poolCol) pooling region
% (see http://ufldl/wiki/index.php/Pooling )
%
% Use mean pooling here.
% -------------------- YOUR CODE HERE --------------------
numBlocks = floor(convolvedDim/poolDim); %每个维度总共分成多少块(/),这里对于不同维数的数据,poolDim要选择能刚好除尽的?
for featureNum = :numFeatures
for imageNum=:numImages
for poolRow = :numBlocks
for poolCol = :numBlocks
features = convolvedFeatures(featureNum,imageNum,(poolRow-)*poolDim+:poolRow*poolDim,(poolCol-)*poolDim+:poolCol*poolDim);
pooledFeatures(featureNum,imageNum,poolRow,poolCol) = mean(features(:));
end
end
end
end
end
结果:
Accuracy: 78.938%
与讲义提到的80%左右差不多。
ps:讲义地址:
http://deeplearning.stanford.edu/wiki/index.php/Feature_extraction_using_convolution
http://deeplearning.stanford.edu/wiki/index.php/Pooling
http://deeplearning.stanford.edu/wiki/index.php/Exercise:Convolution_and_Pooling
Deep Learning 学习随记(七)Convolution and Pooling --卷积和池化的更多相关文章
- Deep Learning 学习随记(八)CNN(Convolutional neural network)理解
前面Andrew Ng的讲义基本看完了.Andrew讲的真是通俗易懂,只是不过瘾啊,讲的太少了.趁着看完那章convolution and pooling, 自己又去翻了翻CNN的相关东西. 当时看讲 ...
- Deep Learning 学习随记(六)Linear Decoder 线性解码
线性解码器(Linear Decoder) 前面第一章提到稀疏自编码器(http://www.cnblogs.com/bzjia-blog/p/SparseAutoencoder.html)的三层网络 ...
- Deep Learning学习随记(一)稀疏自编码器
最近开始看Deep Learning,随手记点,方便以后查看. 主要参考资料是Stanford 教授 Andrew Ng 的 Deep Learning 教程讲义:http://deeplearnin ...
- Deep Learning 学习随记(五)深度网络--续
前面记到了深度网络这一章.当时觉得练习应该挺简单的,用不了多少时间,结果训练时间真够长的...途中debug的时候还手贱的clear了一下,又得从头开始运行.不过最终还是调试成功了,sigh~ 前一篇 ...
- Deep Learning 学习随记(五)Deep network 深度网络
这一个多周忙别的事去了,忙完了,接着看讲义~ 这章讲的是深度网络(Deep Network).前面讲了自学习网络,通过稀疏自编码和一个logistic回归或者softmax回归连接,显然是3层的.而这 ...
- Deep Learning 学习随记(四)自学习和非监督特征学习
接着看讲义,接下来这章应该是Self-Taught Learning and Unsupervised Feature Learning. 含义: 从字面上不难理解其意思.这里的self-taught ...
- Deep Learning学习随记(二)Vectorized、PCA和Whitening
接着上次的记,前面看了稀疏自编码.按照讲义,接下来是Vectorized, 翻译成向量化?暂且这么认为吧. Vectorized: 这节是老师教我们编程技巧了,这个向量化的意思说白了就是利用已经被优化 ...
- Deep Learning 学习随记(三)Softmax regression
讲义中的第四章,讲的是Softmax 回归.softmax回归是logistic回归的泛化版,先来回顾下logistic回归. logistic回归: 训练集为{(x(1),y(1)),...,(x( ...
- Deep Learning 学习随记(三)续 Softmax regression练习
上一篇讲的Softmax regression,当时时间不够,没把练习做完.这几天学车有点累,又特别想动动手自己写写matlab代码 所以等到了现在,这篇文章就当做上一篇的续吧. 回顾: 上一篇最后给 ...
随机推荐
- 窗体前端显示(ShowWindowAsync有许多优点)
H:=FindWindow('Tfrm_MainForm','aa'); if H>0 then begin ShowWindowAsync(h,SW_MAX); SetFore ...
- Android ActivityManager.killBackgroundProcesses方法去结束
android2.2以后,如果服务在ondestroy里加上了start自己,用kill backgroudprocess通常无法结束自己.有一种最新发现的方法,利用反射调用forceStopPack ...
- 别再说“我已经努力了”,你的“努力”一文不值!
有次,让一个研究生男收集一份资料,快下班了问结果,竟然毛也没有.见我要怒,他慷慨激昂地说:"我已经很努力找了,但真的查不到." 作为主管,"我已经努力"这话我不 ...
- Delphi ADOQuery的速度优化 转
今天终于把纠缠了几天的问题改完了,说到底只是一个很小的问题,就是ADOQuery的一个小属性. 把控件DBGridEh的一列的checkbox设为true,将其绑定DataSourceA和DOQu ...
- [转载] cookie、JS记录及跳转到页面原来的位置
额....如下 <!-- 定位页面的 Cookie function SetCookie(sName, sValue) { date = new Date(); s = date.getDate ...
- 【转】OpenGL相关函数库介绍
原文:http://blog.chinaunix.net/uid-20638550-id-1909182.html OpenGL 函数库相关的API有核心库(gl).实用库(glu).辅助库(aux) ...
- CMD打开远程并使用空白密码远程登录
记录一下,在单位管理局域网机器时 写出的小程序: 应用场景:比如异地A的局域网内主机需要远程登录进入系统调试,而A电脑的Radmin之类的远程控制软件无效,就只能使用操作系统自带的远程桌面功能,而,异 ...
- Postman用法简介-Http请求模拟工具
在我们平时开发中,特别是需要与接口打交道时,无论是写接口还是用接口,拿到接口后肯定都得提前测试一下,这样的话就非常需要有一个比较给力的Http请求模拟工具,现在流行的这种工具也挺多的,像火狐浏览器插件 ...
- 使用devpartner的blockchecker检查c++内存错误
在仿写stl的过程中,被一处内存错误卡了很久.当内存池需要多次malloc时会出现堆损坏的错误,初步判断是数组越界,但总是检查不出来.一开始用Dr.Memory检查不出来,就试了一下devpartne ...
- openstack 启用spice
Openstack启用spice协议 #控制节点 #安装 ? 1 apt-get install nova-spiceproxy spice-html5 spice-vdagent #配置 nano ...