MatConvNet的excise 3改为网络配置文件形式

阅读更多
MatConvNet为vlFeat作者写的matlab下的卷积神经网络工具包,可以使用GPU。
主页:http://www.vlfeat.org/matconvnet/
教程:http://www.robots.ox.ac.uk/~vgg/practicals/cnn/index.html

注意:需要下载新版的MatConvNet替换掉教程中工具包中的matconvnet:http://www.vlfeat.org/matconvnet/download/matconvnet-1.0-beta12.tar.gz


本文程序和excise3效果一致,但使用了MatConvNet的examples中类似的网络结构进行定义,可以使用cnn_train函数进行训练。
内容:
  • 演示了自定义网络层、自定义误差函数的方法
  • 演示了自定义errorFunction的方法
  • 演示了对于不同参数分别设置learning rate和weight decay 的方法


不多说,上代码,注释很详细:

function LC_Ex3_usingNetStructure
clc
% -------------------------------------------------------------------------
% Part 3: Learning a simple CNN  改为了使用网络定义
% -------------------------------------------------------------------------
% 改写http://www.robots.ox.ac.uk/~vgg/practicals/cnn/index.htm  的 exercise 3为一个网络
%  注意:MatConvNet工具包已经替换为新版:http://www.vlfeat.org/matconvnet/download/matconvnet-1.0-beta12.tar.gz


setup ;
%%

doSmooth=false;
subMean=false;

doSmooth=true;
subMean=true;


wSize=9;
% -------------------------------------------------------------------------
% Part 3.1: Load an example image and generate its labels
% -------------------------------------------------------------------------
%%
% Load an image
im = rgb2gray(im2single(imread('data/dots.jpg'))) ;

% Compute the location of black blobs in the image
[pos,neg] = extractBlackBlobs(im) ;

%%
% -------------------------------------------------------------------------
% Part 3.2: Image preprocessing
% -------------------------------------------------------------------------

% Pre-smooth the image
if(doSmooth)
    im = vl_imsmooth(im,3) ;
end
%%
% Subtract median value
if(subMean)
    im = im - median(im(:)) ;
end



%% Create pixel-level labels to compute the loss
y = zeros(size(pos),'single') ;
y(pos) = +1 ;
y(neg) = -1 ;


%%  转换为imdb格式

imdb.images.data = {im} ;
imdb.images.labels = {y} ; %labels的数据结构完全由自己决定,与getBatch函数以及误差层的backward函数兼容即可(在backward函数中以layer.class形式出现,layer.class等于getBatch函数的返回值labels);对于分类问题,一般为[1,1,2,2]等类别信息
imdb.images.set = [1];%  样本类型,1为训练样本,2为validation样本,3为测试样本,,但是cnn_train函数只会对训练样本和测试样本进行计算
imdb.meta.sets = {'train', 'val', 'test'} ;%集合名称,即1代表训练集,2代表val集(validation)
imdb.meta.classes ={'1'}; %类别名称




%% -------------------------------------------------------------------------
% Part 3.3: Learning with stochastic gradient descent
% -------------------------------------------------------------------------

trainOpts.batchSize = 1 ;
trainOpts.numEpochs = 500 ; %运行多少轮
trainOpts.continue = false ;%如果trainOpts.expDir已经有对应epoch的网络,是否直接载入
trainOpts.gpus=[]; %gpu下标,不使用GPU则设为[],,如果有两个GPU可以设为 [1 2]
trainOpts.learningRate =.5 ;
trainOpts.expDir = 'data/ex3-experiment' ; %输出的网络结果、实验结果图存在哪儿
trainOpts.momentum=0.9;
trainOpts.weightDecay = 0.0001 ;

trainOpts.errorFunction=@error_ErrPixels; %用于显示误差的自定义函数
trainOpts.errorLabels ={'错误率'};

net=LC_CNN_Ex3('wSize',wSize); %将pos,neg均传给网络,记录到输出层的结构中,便于根据之前的公式计算误差





trainOpts.val=   imdb.images.set==1;  %验证集下标,,必须有验证集,否则报错。。。只好把训练集当成验证集了
[net, info] = cnn_train(net, imdb, @getBatch, ...
    trainOpts) ;

end


%只有一幅图片,直接返回就行了
function  [im, labels]=getBatch(imdb,batch)
   im= imdb.images.data{1};
   im=reshape(im,[size(im) 1]);
   labels=imdb.images.labels{1};
end


%绘图用,用于检测不同epoch下网络的性能,这里返回的指标为分类错误率
function err = error_ErrPixels(opts, labels, res)
% -------------------------------------------------------------------------
resX=res(end-1).x;
y=labels;
        fp = resX >0 & y < 0 ;
        fn = resX < 1 & y > 0 ;
        tn = resX <= 0 & y < 0 ;
        tp = resX >= 1 & y > 0 ;
% err=[fp;fn;tn;tp]; %可以设置多个指标,对应的trainOpts.errorLabels 也要改为多个标签
err=100*(1-sum(sum(tp|tn))/sum(sum(fp|fn|tp|tn)));
end



function net=LC_CNN_Ex3(varargin)
% 改写http://www.robots.ox.ac.uk/~vgg/practicals/cnn/index.html  的 exercise 3为一个网络

opts.wSize=3;
opts=vl_argparse(opts,varargin);


net.layers = {} ;

lr=ones(1,10); 
weightDecay=[1 0];
w = 10 * randn(opts.wSize,opts.wSize, 1) ;  %最后一个表示输出只有一个通道
w = single(w - mean(w(:))) ;
b = single(0) ;
pad1 = ([size(w,1) size(w,1) size(w,2) size(w,2)] - 1) / 2 ;
net.layers{end+1}= struct('type', 'conv', ...
    'weights', {{w, b}}, ...
    'learningRate', [1 2], ...  %自定义learning rate相对于全局的learning rate 的比率,[1 2] 表示w的学习率与全局学习率一致,而偏置b的学习率则为全局学习率的两倍
    'weightDecay',weightDecay,...;%自定义weightDecay相对于全局的weightDecay的比率,[1 0]表示只对w矩阵进行weight decay,而不对偏置b进行weight decay
    'stride', 1, ...
    'pad', pad1) ;

rho2 = 3 ;
pad2 = (rho2 - 1) / 2 ;
net.layers{end+1}= struct('type', 'pool', ...
    'method', 'max', ...
    'pool', rho2, ...
    'stride', 1, ...
    'pad', pad2) ;



%% 自定义的误差函数层
net.layers{end+1}= struct('type', 'custom', ...
    'forward', @forwardFunc , ...  %
    'backward', @backwardFunc) ;
end


function resIp1= forwardFunc(layer, resI, resIp1)   % 计算数据项误差
pos=layer.class==1;
neg=layer.class==-1;
resIp1.x=  mean(max(0, 1 - resI.x(pos))) + ...
    mean(max(0, resI.x(neg)));
end

%后向传播,,求导;;;注意layer.class为该batch内图片的labels。
function resI = backwardFunc(layer, resI, resIp1)  %计算导数

pos=layer.class==1;
neg=layer.class==-1;
resI.dzdx=- single(resI.x < 1 & pos) / sum(pos(:)) + ...
    + single(resI.x > 0 & neg) / sum(neg(:)) ;
end

你可能感兴趣的:(matlab)